Sage One Accounting¶
Overview¶
The Sage One Accounting task integrates BaseCloud CRM with Sage One (Sage Business Cloud Accounting), enabling automated creation and retrieval of quotes, tax invoices, and customer records in your Sage accounting system.
Key Features:
- 6 Actions: Create quotes/invoices, manage customers, fetch documents
- Basic Authentication: Username/password + company ID
- Document Number Management: Manual control with automatic sequence reset
- Item-Based Line Items: Links to Sage inventory items
- Tax Type Support: Configurable tax rates per line item
- South African Focus: Optimized for ZAR and SA tax regulations
Use Cases:
- Sync CRM deals to Sage quotes and invoices
- Automated customer creation from CRM contacts
- Invoice generation on service completion
- Quote workflows with Sage document management
- Item-based billing with Sage inventory tracking
Prerequisites¶
1. Sage One Account¶
- Active Sage One subscription (South Africa)
- Account with API access enabled
- Username and password for authentication
- Company ID (available in Sage account settings)
2. Sage API Configuration¶
BaseCloud Server Configuration:
- API Key must be configured server-side in
config/sage.js - Contact BaseCloud support to enable Sage integration
- API Base URL:
https://accounting.sageone.co.za/api/2.0.0/
3. Sage Inventory Setup¶
For Invoice/Quote Creation:
- Items must exist in Sage inventory with item codes
- Note exact item codes for use in line items
- Configure tax types in Sage (note numeric IDs)
4. Customer Records¶
For Invoice Creation:
- Customers must exist in Sage with customer IDs
- Use
find_customerorcreate_customeractions first - Note customer IDs for quote/invoice creation
Configuration¶
Action 1: create_quote¶
Create a quote in Sage One with line items.
| Field | Required | Description | Example |
|---|---|---|---|
| sage_action | Yes | Must be "create_quote" | create_quote |
| Username | Yes | Sage One username | accounting@company.com |
| Password | Yes | Sage One password | {{sage_password}} (use Variable) |
| Company ID | Yes | Sage company ID | 123456 |
| Expiry Date | Yes | Quote expiry (DD/MM/YYYY HH:mm) | 30/03/2024 17:00 |
| Customer ID | Yes | Sage customer ID (numeric) | 78901 |
| Document Number | Yes | Custom or sequential number | QU{{quote_number}} |
| Reference | Yes | Reference text | CRM Deal #{{deal_id}} |
| Tax Inclusive | Yes | "true" or "false" | true |
| Item Code | Yes | Pipe-delimited Sage item codes | CONSULT\|DESIGN\|DEV |
| Tax Type | Yes | Pipe-delimited tax type IDs | 2\|2\|2 |
| Item Description | Yes | Pipe-delimited descriptions | Consulting\|Design\|Development |
| Item Comment | No | Pipe-delimited comments (can be empty) | Phase 1\|\|Phase 2 |
| Item Quantity | Yes | Pipe-delimited quantities | 10\|5\|20 |
| Item Unit Price | Yes | Pipe-delimited prices (incl/excl based on Tax Inclusive) | 150.00\|200.00\|100.00 |
Output Variables:
task_21001_response // Full Sage API response object
{
QuoteID: 123456,
CustomerId: 78901,
DocumentNumber: "QU001",
Reference: "CRM Deal #4567",
Total: 3750.00,
TotalIncl: 4312.50,
Lines: [...],
Date: "2024-01-15T00:00:00",
ExpiryDate: "2024-03-30T17:00:00"
}
How It Works:
- Get Current Document Number:
- Calls
/SystemSettings/GetDocumentNumber?documentTypeId=1(Quotes) -
Stores original
DocumentNumberandNextNumberfor reset -
Lookup Item Selection IDs:
- For each Item Code: GET
/Item/Get?code={code}&companyid={companyId} - Extracts
SelectionId(internal Sage item ID) -
Fails if any item code not found
-
Validate Line Items:
- All pipe-delimited arrays must be same length
-
Exception: Item Comment can be shorter (auto-filled with empty strings)
-
Build Quote Object:
{ ID: 0, // 0 for new quotes Date: today, ExpiryDate: provided expiry date (ISO format), CustomerId: numeric customer ID, DocumentNumber: provided document number, Reference: reference text, Inclusive: true/false, Lines: [ { ID: 0, SelectionId: from item lookup, TaxTypeId: numeric tax type, Description: item description, Comments: item comment (or empty), Quantity: decimal, UnitPriceInclusive: price (if Inclusive=true), UnitPriceExclusive: price (if Inclusive=false) } ] } -
Create Quote:
- POST to
/Quote/savewith Authorization header (Basic Auth) -
Returns full quote object with
QuoteID -
Reset Document Number:
- POST
/SystemSettings/SetDocumentNumberback to original - Prevents Sage auto-incrementing its own sequence
Error Scenarios:
- "Failed to get current document number" - Sage API access issue or invalid credentials
- "Failed to get Item Code {code}" - Item doesn't exist in Sage inventory
- "Sage line items length mismatch" - Array lengths don't match
- "Failed to create quote" - Sage API error (check
responsefor details)
Action 2: create_tax_invoice¶
Create a tax invoice in Sage One. Configuration and process identical to create_quote with these differences:
| Field | Value/Difference |
|---|---|
| sage_action | create_tax_invoice |
| Document Type ID | 2 (Tax Invoices instead of 1 for Quotes) |
| API Endpoint | /TaxInvoice/save |
| Due Date | Uses today's date (not ExpiryDate) |
Output Variables:
task_21001_response // Full Sage API response
{
TaxInvoiceID: 234567,
CustomerId: 78901,
DocumentNumber: "INV001",
Reference: "CRM Deal #4567",
Total: 3750.00,
TotalIncl: 4312.50,
Lines: [...],
Date: "2024-01-15T00:00:00",
DueDate: "2024-01-15T00:00:00"
}
All other fields, validation, and processes same as create_quote.
Action 3: create_customer¶
Create a new customer in Sage One.
| Field | Required | Description | Example |
|---|---|---|---|
| sage_action | Yes | Must be "create_customer" | create_customer |
| Username | Yes | Sage One username | accounting@company.com |
| Password | Yes | Sage One password | {{sage_password}} |
| Company ID | Yes | Sage company ID | 123456 |
| Customer Name | Yes | Customer name | {{client_company_name}} |
| Customer Email | Yes | Customer email address | {{client_email}} |
Output Variables:
task_21001_response // Full Sage customer object
{
CustomerID: 78901,
Name: "Acme Corporation",
Email: "billing@acme.com",
Created: "2024-01-15T10:30:00",
CompanyId: 123456
}
How It Works:
- POST to
/customer/save - Body:
{ Name: "...", Email: "..." } - Returns complete customer object including
CustomerID
Best Practice:
- Use
find_customerfirst to avoid duplicates - Store
{{task_21001_response.CustomerID}}in CRM for future use
Action 4: find_customer¶
Search for existing customer in Sage One by name.
| Field | Required | Description | Example |
|---|---|---|---|
| sage_action | Yes | Must be "find_customer" | find_customer |
| Username | Yes | Sage One username | accounting@company.com |
| Password | Yes | Sage One password | {{sage_password}} |
| Company ID | Yes | Sage company ID | 123456 |
| Customer Name | Yes | Exact customer name | {{client_company_name}} |
Output Variables:
task_21001_found // true or false
task_21001_customer_id // Sage customer ID (if found)
task_21001_customer_name // Customer name (if found)
task_21001_customer_email // Customer email (if found)
How It Works:
- GET
/Customer/Get?name={name}&companyid={companyId} - URL-encodes special characters:
&→%26- Space →
%20 - Other special chars encoded
- Returns customer object if exact match found
Search Behavior:
- Exact match only (case-insensitive)
- Special characters properly encoded
- Returns first match if multiple exist
Action 5: fetch_quote¶
Retrieve existing quote from Sage One by document number.
| Field | Required | Description | Example |
|---|---|---|---|
| sage_action | Yes | Must be "fetch_quote" | fetch_quote |
| Username | Yes | Sage One username | accounting@company.com |
| Password | Yes | Sage One password | {{sage_password}} |
| Company ID | Yes | Sage company ID | 123456 |
| Document Number | Yes | Quote document number | QU001 |
Output Variables:
task_21001_found // true or false
task_21001_response // Full Sage quote object (if found)
{
QuoteID: 123456,
DocumentNumber: "QU001",
CustomerId: 78901,
Total: 3750.00,
Lines: [...],
// ... complete quote details
}
How It Works:
- GET
/Quote/Get?documentNumber={number}&companyid={companyId} - Returns full quote object if found
- Sets
task_21001_found=falseif not found
Action 6: fetch_tax_invoice¶
Retrieve existing tax invoice from Sage One by document number.
| Field | Required | Description | Example |
|---|---|---|---|
| sage_action | Yes | Must be "fetch_tax_invoice" | fetch_tax_invoice |
| Username | Yes | Sage One username | accounting@company.com |
| Password | Yes | Sage One password | {{sage_password}} |
| Company ID | Yes | Sage company ID | 123456 |
| Document Number | Yes | Invoice document number | INV001 |
Output Variables:
task_21001_found // true or false
task_21001_response // Full Sage tax invoice object (if found)
{
TaxInvoiceID: 234567,
DocumentNumber: "INV001",
CustomerId: 78901,
Total: 4312.50,
Lines: [...],
// ... complete invoice details
}
How It Works:
- GET
/TaxInvoice/Get?documentNumber={number}&companyid={companyId} - Returns full invoice object if found
- Sets
task_21001_found=falseif not found
Real-World Examples¶
Example 1: Sync CRM Deal to Sage Quote¶
Scenario: When deal reaches "Proposal" stage, automatically create quote in Sage with deal line items.
Workflow:
- Trigger: CRM Trigger - Deal Stage Changed
-
Condition:
{{deal_stage}}equals "Proposal" -
Task: If Condition - Check Customer Exists
-
Task (Inside If - True): Sage - Find Customer
-
Task (Inside If - True): If Condition - Customer Not Found
-
Task (Inside Nested If - True): Sage - Create Customer
-
Task (Inside Nested If - True): Edit Client - Store Customer ID
-
Task: Variable - Prepare Line Items
-
Task: Sage - Create Quote
sage_action: create_quote Username: accounting@company.com Password: {{sage_password}} Company ID: 123456 Expiry Date: {{deal_expiry_date}} Customer ID: {{client_sage_customer_id}} Document Number: QU{{deal_id}} Reference: Deal #{{deal_id}} - {{deal_name}} Tax Inclusive: true Item Code: {{item_codes}} Tax Type: {{tax_types}} Item Description: {{item_descriptions}} Item Comment: ||| // Empty comments Item Quantity: {{item_quantities}} Item Unit Price: {{item_prices}} -
Task: Edit Client - Store Quote ID
-
Task: Workflow Note - Log Quote Creation
-
Task: Email - Notify Sales Team
To: {{deal_owner_email}} Subject: Sage Quote Created - {{client_company_name}} Body: Quote {{task_21001_response.DocumentNumber}} has been created in Sage One. Customer: {{client_company_name}} Total: R{{task_21001_response.TotalIncl}} Expiry: {{deal_expiry_date}} Please review in Sage and send to client.
Result: CRM deals automatically sync to Sage with customer auto-creation and quote generation, eliminating manual data entry.
Example 2: Quote-to-Invoice Conversion¶
Scenario: When deal is won, create tax invoice in Sage using same line items as quote.
Workflow:
- Trigger: CRM Trigger - Deal Stage Changed
-
Condition:
{{deal_stage}}equals "Won" -
Task: Sage - Fetch Quote
-
Task: If Condition - Quote Found
-
Task (Inside If): Formatter - Extract Line Items
-
Task (Inside If): Sage - Create Tax Invoice
sage_action: create_tax_invoice Username: accounting@company.com Password: {{sage_password}} Company ID: 123456 Expiry Date: {{today_date}} // Due today Customer ID: {{task_21001_response.CustomerId}} Document Number: INV{{deal_id}} Reference: Converted from Quote QU{{deal_id}} Tax Inclusive: true Item Code: {{extracted_item_codes}} Tax Type: {{extracted_tax_types}} Item Description: {{extracted_item_descriptions}} Item Comment: ||| Item Quantity: {{extracted_item_quantities}} Item Unit Price: {{extracted_item_prices}} -
Task (Inside If): Edit Client - Store Invoice ID
-
Task (Inside If): Workflow Note - Log Conversion
-
Task (Inside If): Email - Send Invoice Notification
To: {{client_email}} Cc: accounting@company.com Subject: Invoice {{task_21001_response.DocumentNumber}} - {{deal_name}} Body: Congratulations on your purchase! Your invoice is now available in Sage One. Invoice Number: {{task_21001_response.DocumentNumber}} Amount Due: R{{task_21001_response.TotalIncl}} Our accounting team will send the formal invoice shortly.
Result: Won deals automatically convert to Sage tax invoices, maintaining line item accuracy and enabling immediate billing.
Example 3: Item-Based Service Invoicing¶
Scenario: Service completion triggers Sage invoice with predefined item codes from Sage inventory.
Workflow:
- Trigger: CRM Trigger - Service Status Changed
-
Condition:
{{service_status}}equals "Complete" -
Task: MySQL Query - Get Service Details
-
Task: Variable - Prepare Invoice Data
-
Task: Sage - Create Tax Invoice
sage_action: create_tax_invoice Username: accounting@company.com Password: {{sage_password}} Company ID: 123456 Expiry Date: {{service_completion_date}} Customer ID: {{client_sage_customer_id}} Document Number: INV-SRV-{{service_id}} Reference: Service #{{service_id}} - {{service_type}} Tax Inclusive: true Item Code: {{item_code}} Tax Type: {{tax_type}} Item Description: {{item_description}} Item Comment: Completed {{service_completion_date}} Item Quantity: {{item_quantity}} Item Unit Price: {{item_price}} -
Task: MySQL - Update Service Record
-
Task: Email - Send Completion Notice
To: {{client_email}} Subject: Service Complete - Invoice {{task_21001_response.DocumentNumber}} Body: Your service ({{service_type}}) has been completed. Invoice: {{task_21001_response.DocumentNumber}} Amount: R{{task_21001_response.TotalIncl}} You will receive the formal invoice from our accounting team. -
Task: Workflow Note - Log Service Invoicing
Result: Service completions automatically generate Sage invoices with correct item codes, maintaining inventory tracking and accurate accounting.
Example 4: Multi-Service Monthly Billing¶
Scenario: Generate consolidated monthly invoice for client with multiple services, each mapped to Sage item codes.
Workflow:
-
Trigger: Timer Trigger - Monthly (Last day at 18:00)
-
Task: MySQL Query - Get Clients with Unbilled Services
-
Task: Loop - Process Each Client
-
Task (Inside Loop): MySQL Query - Get Client Services
SELECT s.sage_item_code, si.description, si.unit_price, si.tax_type_id, COUNT(*) as quantity, GROUP_CONCAT(s.service_id SEPARATOR ',') as service_ids FROM services s JOIN sage_items si ON s.sage_item_code = si.item_code WHERE s.client_id = {{loop_item_client_id}} AND s.invoiced = 0 AND s.status = 'Complete' GROUP BY s.sage_item_code, si.description, si.unit_price, si.tax_type_id -
Task (Inside Loop): Formatter - Prepare Line Items
-
Task (Inside Loop): Sage - Create Tax Invoice
sage_action: create_tax_invoice Username: accounting@company.com Password: {{sage_password}} Company ID: 123456 Expiry Date: {{last_day_of_month}} Customer ID: {{loop_item_sage_customer_id}} Document Number: INV-{{month_code}}-{{loop_item_client_id}} Reference: Monthly Services - {{month_name}} {{year}} Tax Inclusive: true Item Code: {{item_codes}} Tax Type: {{tax_types}} Item Description: {{descriptions}} Item Comment: {{comments}} Item Quantity: {{quantities}} Item Unit Price: {{prices}} -
Task (Inside Loop): MySQL - Mark Services Invoiced
-
Task (Inside Loop): Email - Send Monthly Invoice Notice
To: {{loop_item_client_email}} Subject: Monthly Invoice - {{month_name}} {{year}} Body: Your monthly service invoice is ready. Invoice: {{task_21001_response.DocumentNumber}} Services: {{service_count}} Total: R{{task_21001_response.TotalIncl}} Please check your Sage account or contact our accounting team. -
Task (Inside Loop): Workflow Note - Log Monthly Invoice
Result: Automated monthly billing consolidates multiple services per client into single Sage invoices, reducing manual invoice entry and improving cash flow.
Example 5: Customer Sync Workflow¶
Scenario: Synchronize CRM clients with Sage customers, updating or creating as needed.
Workflow:
-
Trigger: Manual Button - Sync to Sage
-
Task: If Condition - Check Sage Customer ID Exists
-
Task (Inside If - True): Workflow Note - Skip Existing
-
Task (Inside If - False): Sage - Find Customer
-
Task (Inside If - False): If Condition - Customer Found in Sage
-
Task (Inside Nested If - True): Edit Client - Link Existing Sage Customer
-
Task (Inside Nested If - True): Workflow Note - Linked Existing
-
Task (Inside Nested If - False): Sage - Create New Customer
-
Task (Inside Nested If - False): Edit Client - Store New Customer ID
-
Task (Inside Nested If - False): Workflow Note - Created New
-
Task: Email - Sync Confirmation
Bulk Sync Variation (Loop):
- Trigger: Timer Trigger - Daily (02:00)
- Task: MySQL Query - Get Unsynced Clients
- Task: Loop - Sync Each Client
- Task (Inside Loop): Execute steps 2-10 from above
Result: Automated customer synchronization ensures CRM clients are always available in Sage for invoicing, with duplicate prevention and linking of existing records.
Troubleshooting¶
Error: "Failed to get current document number"¶
Cause: Cannot retrieve document number sequence from Sage API
Solutions:
-
Verify credentials (Username, Password, Company ID) are correct
-
Check Sage API access is enabled for account
-
Test credentials manually: Visit
https://accounting.sageone.co.za/api/2.0.0/SystemSettings/GetDocumentNumber?documentTypeId=1&companyid={companyId}with Basic Auth -
Contact Sage support if API access issues persist
-
Ensure BaseCloud server has Sage API key configured
Error: "Failed to get Item Code {code}"¶
Cause: Item code doesn't exist in Sage inventory
Solutions:
-
Verify item code exists: Log into Sage → Inventory → Items → Search for code
-
Check exact spelling and case (usually case-insensitive but whitespace matters)
-
Create missing items in Sage first
-
Use standardized item codes stored in CRM or database
-
Validate item codes before invoice creation:
Error: "Sage line items length mismatch"¶
Cause: Pipe-delimited arrays have different numbers of items
Solutions:
-
Count pipes in each field - must be equal:
-
Use Formatter task to validate array lengths before Sage task
-
Exception: Item Comment can be shorter (auto-filled with empty strings)
-
Debug: Output arrays to Workflow Note to check lengths
-
Use consistent data source (e.g., MySQL query with CONCAT/GROUP_CONCAT)
Error: "Failed to create quote/invoice"¶
Cause: Sage API rejected document creation
Solutions:
-
Check
{{task_21001_response}}for Sage error details -
Common issues:
- Customer ID doesn't exist (use find_customer first)
- Tax Type ID invalid (check Sage tax type configuration)
- Document number already exists (use unique numbers)
- Date format incorrect (must be DD/MM/YYYY HH:mm)
-
Negative quantities or prices
-
Validate all required fields are populated
-
Test with minimal invoice (1 line item) first
-
Ensure Tax Inclusive matches price format (inclusive vs exclusive)
Customer Not Found with find_customer¶
Cause: Exact name match not found in Sage
Solutions:
-
Check for typos or extra spaces in customer name
-
Sage search is exact match - "Acme Corp" ≠ "Acme Corporation"
-
Use standardized naming in CRM to match Sage
-
Create customer first if not found:
-
Check special characters are properly handled (&, commas, etc.)
Document Number Sequence Issues¶
Cause: Manual document number conflicts with Sage auto-increment
Solutions:
- Use unique prefixes for CRM-generated documents:
- CRM quotes:
CRM-QU-001 - CRM invoices:
CRM-INV-001 -
Sage internal:
QU001,INV001 -
Query max document number before creation:
-
Document number reset may fail - check Sage permissions
-
Consider using Sage's auto-numbering (pass empty string or omit)
Authentication Failures¶
Cause: Invalid Basic Auth credentials
Solutions:
-
Verify Username and Password are correct (test in Sage web UI)
-
Check Company ID is numeric and correct
-
Use Variable task to securely store credentials (don't hardcode password)
-
Ensure Sage API key configured on BaseCloud server
-
Check account has API access enabled (may require premium Sage plan)
-
Test with curl:
Tax Type ID Confusion¶
Cause: Incorrect or unknown tax type IDs
Solutions:
-
Tax Type IDs are numeric (e.g., 1, 2, 3) and company-specific
-
Standard South African VAT: Usually ID 2 (15%)
-
Find your tax type IDs:
- Log into Sage One
- Navigate to Settings → Tax Types
-
Note numeric IDs (may need Sage support for API IDs)
-
Create reference table in CRM:
-
Use consistent tax types across all line items for simplicity
Best Practices¶
Credential Management¶
- Secure Storage:
- Store Sage password in CRM Variables (encrypted)
- Use
{{sage_password}}reference in tasks -
Never hardcode credentials in automation
-
Access Control:
- Use dedicated Sage user for API access
- Limit permissions to necessary operations
-
Rotate password regularly
-
Company ID:
- Store as CRM setting or owner-level variable
- Use
{{owner_sage_company_id}}for multi-tenant setups
Item Code Standardization¶
- CRM Item Master:
- Maintain item code lookup table in CRM database
- Map CRM product IDs to Sage item codes
-
Include descriptions, prices, tax types
-
Validation:
- Pre-validate item codes exist in Sage before invoice creation
-
Alert users to missing items early in workflow
-
Naming Convention:
- Use uppercase, short codes (e.g., CONSULT, DESIGN, DEV)
- Avoid special characters
- Keep codes consistent across CRM and Sage
Customer Synchronization¶
- Proactive Sync:
- Create Sage customer when CRM client created (if applicable)
-
Store
sage_customer_idin CRM client record immediately -
Duplicate Prevention:
- Always use
find_customerbeforecreate_customer -
Check CRM for existing
sage_customer_idfirst -
Name Standardization:
- Use consistent naming format (e.g., always "Company Name (Pty) Ltd")
- Strip special characters that may cause search issues
Document Numbering¶
- Unique Prefixes:
- Distinguish CRM-generated docs from Sage internal docs
-
Example:
CRM-INV-{{client_id}}-{{timestamp}} -
Sequential Safety:
- Don't rely on Sage auto-increment for CRM workflows
-
Generate unique numbers in CRM (timestamp, UUID, client ID combo)
-
Reference Field:
- Always populate Reference field with CRM context
- Example:
Deal #{{deal_id}} - {{deal_name}} - Enables easy cross-referencing between systems
Error Handling¶
- Validation Before Creation:
- Check customer exists in Sage
- Validate all item codes
- Verify array lengths match
-
Test date format
-
If Conditions:
- Wrap Sage actions in error-checking conditions
- Provide fallback workflows for failures
-
Alert users to errors with actionable details
-
Logging:
- Always create Workflow Notes for Sage actions
- Include Sage IDs, document numbers, amounts
- Log errors with full context for debugging
Performance Optimization¶
- Batch Operations:
- Group multiple services into single invoice (see Example 4)
-
Avoid creating separate invoice per line item
-
Caching:
- Cache item lookups in CRM to reduce Sage API calls
-
Store frequently-used item Selection IDs
-
Off-Peak Scheduling:
- Schedule bulk operations (monthly billing) during off-peak hours
- Avoid simultaneous Sage API calls (use delays in loops)
FAQ¶
Q: Can I edit Sage quotes/invoices from BaseCloud?
A: No, Sage API doesn't support document updates. Options:
- Create new document with revised details
- Manually edit in Sage One web UI
- Void and recreate via Sage
Q: How do I handle quotes that are never accepted?
A: Sage quotes don't auto-expire:
- Set up CRM reminder workflow at expiry date
- Manually void old quotes in Sage
- Or leave open (doesn't affect accounting until invoiced)
Q: Can I get Sage quote/invoice PDF from BaseCloud?
A: No, Sage API doesn't return PDFs. Workarounds:
- Access Sage One web UI to download PDF
- Use Sage's email functionality to send to client
- Generate parallel PDF in BaseCloud (Type 22 BaseCloud Accounting)
Q: What tax types are available?
A: Tax types are company-specific in Sage. Common South African setup:
- Type 1: Tax Exempt (0%)
- Type 2: Standard VAT (15%)
- Type 3: Zero-Rated (0% but VAT-registered)
Contact Sage support for your specific tax type IDs.
Q: Can I use Sage with currencies other than ZAR?
A: Sage One SA is optimized for ZAR. Multi-currency support limited:
- Check your Sage plan for multi-currency features
- May require manual currency handling in Sage
- Consider currency conversion in CRM before passing to Sage
Q: How do I handle discounts?
A: Sage API doesn't have dedicated discount field. Options:
- Discount Line Item: Add negative price line item
- Pre-calculate: Subtract discount from unit price before creation
- Manual: Apply discount in Sage UI after creation
Q: Can I delete Sage documents from BaseCloud?
A: No, Sage API doesn't support document deletion. Solutions:
- Void documents in Sage web UI
- Contact Sage support for deletion assistance
- Use naming convention to mark obsolete (e.g., "VOID - ")
Q: What happens if document number already exists?
A: Sage API returns error. Solutions:
- Use unique numbering scheme (timestamp, UUID)
- Implement collision detection with retry logic
- Use Sage auto-numbering (but loses CRM reference tracking)
Q: How do I sync Sage invoices back to CRM?
A: Use fetch_tax_invoice or fetch_quote actions:
- Timer Trigger: Periodically fetch invoices by document number
- Store Sage data in CRM (status, amounts, dates)
- Update client records or dashboards
For real-time sync, consider Sage webhooks (if available in your plan).
Q: Can I create credit notes?
A: Sage API doesn't support credit notes via BaseCloud. Options:
- Create manually in Sage One web UI
- Create negative invoice as workaround (not ideal)
- Request credit note API support from Sage
Q: How do I handle partial payments?
A: Sage tracks payment status internally. From BaseCloud:
- Use
fetch_tax_invoiceto check payment status - Update CRM client record based on Sage status
- Payment recording happens in Sage (not via API)
Q: What's the API rate limit?
A: Sage One API has rate limits (varies by plan). Best practices:
- Add delays between bulk operations (use Delay task)
- Avoid parallel API calls to same Sage account
- Implement retry logic for rate limit errors (429 status)
Q: Can I create recurring invoices?
A: Not directly via API. Workarounds:
- CRM Recurring Workflow:
- Timer Trigger: Monthly/weekly
- Create invoice via Sage task
-
Store in CRM for tracking
-
Sage Internal Recurring:
- Set up recurring invoices in Sage One UI
- Fetch via API for CRM sync
Q: How do I troubleshoot API errors?
A: Check {{task_21001_response}} for error details:
Response structure:
{
StatusCode: 400,
Message: "Descriptive error message",
ModelState: {
"Field": ["Validation error details"]
}
}
Common status codes:
- 400: Bad request (validation error)
- 401: Authentication failed
- 404: Resource not found
- 500: Sage server error
Related Tasks¶
- BaseCloud Accounting - Internal alternative to Sage
- Xero - Alternative accounting integration
- Email - Send invoice notifications
- MySQL - Query CRM data for invoicing
- Loop - Bulk invoice creation
- If Statement - Handle customer creation logic
- Workflow Note - Log Sage actions
- Timer Trigger - Schedule recurring billing
- CRM Trigger - Trigger on deal/client changes
Technical Details¶
- Type ID: 21
- Function:
taskSage()in automationService.js (lines 4446-5028) - API: Sage One Accounting API v2.0.0
- Authentication: HTTP Basic Auth (Username:Password)
- Base URL:
https://accounting.sageone.co.za/api/2.0.0/ - Output Prefix:
task_21001_* - Document Types: 1=Quote, 2=Tax Invoice
- Geographic Focus: South Africa (ZAR, VAT compliance)