Skip to content

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_customer or create_customer actions first
  • Note customer IDs for quote/invoice creation

The General screen in BaseCloud Settings. A Locale and Formatting section sets Default Currency to Rand ZAR, Default Font to Poppins, Default Font Size to 11pt and Business Timezone to Africa/Johannesburg. An Accounting section holds a single setting, "Invoice prices are", described as setting whether unit prices on quotes and invoices are entered inclusive or exclusive of tax, with its dropdown open on three choices: Tax exclusive, which is selected, Tax inclusive, and No tax. Below, Email Settings toggles cover inserting reference IDs in outgoing emails and including BaseCloud footer branding, and an AI and Automation section has automatic client matching enabled with a note that both suggestions and automatic matching consume billable tokens

Tax handling is an account-wide setting, not a per-invoice one. Settings → General → Accounting decides whether unit prices are entered Tax exclusive, Tax inclusive, or No tax — and it governs how figures a task writes are interpreted. Sending a tax-exclusive amount into an account set to tax-inclusive does not fail; it produces a quietly wrong total.

Outputs

Which fields appear depends on the action. Customer and invoice lookups populate their own groups.

Reference fields as {{task_<ID>_<field>}}.

Field Type Notes
output string The Sage response body for the main call. Present only on some actions.
response string The Sage response body for an invoice call. Present only on some actions.
customer_matched boolean true when an existing customer was found. Present only on some actions.
customer_matched_id string The matched customer's Sage ID. Present only on some actions.
customer_matched_name string The matched customer's name. Present only on some actions.
customer_matched_email string The matched customer's email. Present only on some actions.
invoice_matched boolean true when an existing invoice was found. Present only on some actions.
invoice string The matched invoice record. Present only on some actions.

Always emitted

Field Type Notes
run boolean Whether the task succeeded.
run_text string What happened, including the reason on failure.

Fields marked as action-dependent may be absent

This task does several different things depending on its action setting, and only the fields relevant to that action are emitted. Check a real run in the OUTPUT panel before referencing one downstream.

Configuration

Builder fields

The Field column is the label as it appears in the task builder; Key is the name the value is stored under and referenced by.

Field Key Type Default Notes
Action sage_action select create_quote Options: Create Customer · Find Customer · Create Quote · Create Tax Invoice · Fetch Quote · Fetch Tax Invoice
Username Username text –
Password Password text –
Company ID companyid text –
Customer Name Customer Name text – Only shown when sage_action is create_customer
Customer Email Customer Email text – Only shown when sage_action is create_customer
Customer Name Customer Name text – Only shown when sage_action is find_customer
Customer ID Customer Id text –
Document Number Document Number text –
Customer Reference Customer Reference text –
Expiry Date Expiry Date text – Only shown when sage_action is create_quote
Due Date Due Date text – Only shown when sage_action is create_tax_invoice
Tax Inclusive Tax Inclusive select false Options: No · Yes
Item Code(s) Item Code text –
Tax Type ID(s) Item TaxTypeId text –
Item Description(s) Item Description text –
Item Comments (optional) Item Comments text –
Item Quantity(ies) Item Quantity text –
Unit Price(s) Item Unit Price text –
Quote ID Quote ID text – Only shown when sage_action is fetch_quote
Invoice ID Invoice ID text – Only shown when sage_action is fetch_tax_invoice

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:

  1. Get Current Document Number:
  2. Calls /SystemSettings/GetDocumentNumber?documentTypeId=1 (Quotes)
  3. Stores original DocumentNumber and NextNumber for reset
  4. Lookup Item Selection IDs:
  5. For each Item Code: GET /Item/Get?code={code}&companyid={companyId}
  6. Extracts SelectionId (internal Sage item ID)
  7. Fails if any item code not found
  8. Validate Line Items:
  9. All pipe-delimited arrays must be same length
  10. Exception: Item Comment can be shorter (auto-filled with empty strings)
  11. 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)
        }
      ]
    }
    
  12. Create Quote:
  13. POST to /Quote/save with Authorization header (Basic Auth)
  14. Returns full quote object with QuoteID
  15. Reset Document Number:
  16. POST /SystemSettings/SetDocumentNumber back to original
  17. 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 response for 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:

  1. POST to /customer/save
  2. Body: { Name: "...", Email: "..." }
  3. Returns complete customer object including CustomerID

Best Practice:

  • Use find_customer first 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:

  1. GET /Customer/Get?name={name}&companyid={companyId}
  2. URL-encodes special characters:
  3. & → %26
  4. Space → %20
  5. Other special chars encoded
  6. 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:

  1. GET /Quote/Get?documentNumber={number}&companyid={companyId}
  2. Returns full quote object if found
  3. Sets task_21001_found=false if 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:

  1. GET /TaxInvoice/Get?documentNumber={number}&companyid={companyId}
  2. Returns full invoice object if found
  3. Sets task_21001_found=false if not found

Real-World Examples

Raise an invoice when a deal is won

CRM Trigger  (status changed to "Won")
  └─ Match to Client   look the client up
      └─ Sage          create a tax invoice for {{task_15001_match_client_name}}

Store the Sage customer ID on the client as a custom field so this step can map it straight in.

Create the Sage customer the first time you invoice them

CRM Trigger
  └─ Sage              customer lookup by email
      └─ If Statement  {{task_21001_customer_matched}} is false
          └─ Sage      create the customer

customer_matched, customer_matched_id and customer_matched_name tell you whether the customer already exists, so you only create when you need to.

Email the invoice once Sage has it

Form Submission
  └─ Sage      create the invoice
      └─ Email  confirm to the client

Troubleshooting

Error: "Failed to get current document number"

Cause: Cannot retrieve document number sequence from Sage API

Solutions:

  1. Verify credentials (Username, Password, Company ID) are correct

  2. Check Sage API access is enabled for account

  3. Test credentials manually: Visit https://accounting.sageone.co.za/api/2.0.0/SystemSettings/GetDocumentNumber?documentTypeId=1&companyid={companyId} with Basic Auth

  4. Contact Sage support if API access issues persist

  5. 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:

  1. Verify item code exists: Log into Sage → Inventory → Items → Search for code

  2. Check exact spelling and case (usually case-insensitive but whitespace matters)

  3. Create missing items in Sage first

  4. Use standardized item codes stored in CRM or database

  5. Validate item codes before invoice creation:

    Loop through item codes → Sage fetch item → If not found, alert user
    

Error: "Sage line items length mismatch"

Cause: Pipe-delimited arrays have different numbers of items

Solutions:

  1. Count pipes in each field - must be equal:
Item Code: "A|B|C"        // 3 items
Item Quantity: "1|2|3"    // 3 items
Item Unit Price: "10|20"  // 2 items ✗ MISMATCH
  1. Use Formatter task to validate array lengths before Sage task

  2. Exception: Item Comment can be shorter (auto-filled with empty strings)

  3. Debug: Output arrays to Workflow Note to check lengths

  4. Build every line-item list from the same source so the arrays stay the same length

Error: "Failed to create quote/invoice"

Cause: Sage API rejected document creation

Solutions:

  1. Check {{task_21001_response}} for Sage error details

  2. Common issues:

  3. Customer ID doesn't exist (use find_customer first)
  4. Tax Type ID invalid (check Sage tax type configuration)
  5. Document number already exists (use unique numbers)
  6. Date format incorrect (must be DD/MM/YYYY HH:mm)
  7. Negative quantities or prices
  8. Validate all required fields are populated

  9. Test with minimal invoice (1 line item) first

  10. Ensure Tax Inclusive matches price format (inclusive vs exclusive)

Customer Not Found with find_customer

Cause: Exact name match not found in Sage

Solutions:

  1. Check for typos or extra spaces in customer name

  2. Sage search is exact match - "Acme Corp" ≠ "Acme Corporation"

  3. Use standardized naming in CRM to match Sage

  4. Create customer first if not found:

If {{task_21001_found}} equals false → create_customer action
  1. Check special characters are properly handled (&, commas, etc.)

Document Number Sequence Issues

Cause: Manual document number conflicts with Sage auto-increment

Solutions:

  1. Use unique prefixes for CRM-generated documents:
  2. CRM quotes: CRM-QU-001
  3. CRM invoices: CRM-INV-001
  4. Sage internal: QU001, INV001

  5. Query max document number before creation:

Sage fetch to get latest → Increment by 1 → Use in create
  1. Document number reset may fail - check Sage permissions

  2. Consider using Sage's auto-numbering (pass empty string or omit)

Authentication Failures

Cause: Invalid Basic Auth credentials

Solutions:

  1. Verify Username and Password are correct (test in Sage web UI)

  2. Check Company ID is numeric and correct

  3. Use Variable task to securely store credentials (don't hardcode password)

  4. Ensure Sage API key configured on BaseCloud server

  5. Check account has API access enabled (may require premium Sage plan)

  6. Test with curl:

    curl -u "username:password" "https://accounting.sageone.co.za/api/2.0.0/Customer/Get?companyid=123456"
    

Tax Type ID Confusion

Cause: Incorrect or unknown tax type IDs

Solutions:

  1. Tax Type IDs are numeric (e.g., 1, 2, 3) and company-specific

  2. Standard South African VAT: Usually ID 2 (15%)

  3. Find your tax type IDs:

  4. Log into Sage One
  5. Navigate to Settings → General → Accounting
  6. Note numeric IDs (may need Sage support for API IDs)

  7. Create reference table in CRM:

Tax Type 1: Exempt (0%)
Tax Type 2: Standard VAT (15%)
Tax Type 3: Zero-rated
  1. Use consistent tax types across all line items for simplicity

Best Practices

Credential Management

  1. Secure Storage:
  2. Store Sage password in CRM Variables (encrypted)
  3. Use {{sage_password}} reference in tasks
  4. Never hardcode credentials in automation

  5. Access Control:

  6. Use dedicated Sage user for API access
  7. Limit permissions to necessary operations
  8. Rotate password regularly

  9. Company ID:

  10. Store as CRM setting or owner-level variable
  11. Use {{owner_sage_company_id}} for multi-tenant setups

Item Code Standardization

  1. CRM Item Master:
  2. Maintain item code lookup table in CRM database
  3. Map CRM product IDs to Sage item codes
  4. Include descriptions, prices, tax types

  5. Validation:

  6. Pre-validate item codes exist in Sage before invoice creation
  7. Alert users to missing items early in workflow

  8. Naming Convention:

  9. Use uppercase, short codes (e.g., CONSULT, DESIGN, DEV)
  10. Avoid special characters
  11. Keep codes consistent across CRM and Sage

Customer Synchronization

  1. Proactive Sync:
  2. Create Sage customer when CRM client created (if applicable)
  3. Store sage_customer_id in CRM client record immediately

  4. Duplicate Prevention:

  5. Always use find_customer before create_customer
  6. Check CRM for existing sage_customer_id first

  7. Name Standardization:

  8. Use consistent naming format (e.g., always "Company Name (Pty) Ltd")
  9. Strip special characters that may cause search issues

Document Numbering

  1. Unique Prefixes:
  2. Distinguish CRM-generated docs from Sage internal docs
  3. Example: CRM-INV-{{client_id}}-{{timestamp}}

  4. Sequential Safety:

  5. Don't rely on Sage auto-increment for CRM workflows
  6. Generate unique numbers in CRM (timestamp, UUID, client ID combo)

  7. Reference Field:

  8. Always populate Reference field with CRM context
  9. Example: Deal #{{deal_id}} - {{deal_name}}
  10. Enables easy cross-referencing between systems

Error Handling

  1. Validation Before Creation:
  2. Check customer exists in Sage
  3. Validate all item codes
  4. Verify array lengths match
  5. Test date format

  6. If Conditions:

  7. Wrap Sage actions in error-checking conditions
  8. Provide fallback workflows for failures
  9. Alert users to errors with actionable details

  10. Logging:

  11. Always create Workflow Notes for Sage actions
  12. Include Sage IDs, document numbers, amounts
  13. Log errors with full context for debugging

Performance Optimization

  1. Batch Operations:
  2. Group multiple services into single invoice (see Example 4)
  3. Avoid creating separate invoice per line item

  4. Caching:

  5. Cache item lookups in CRM to reduce Sage API calls
  6. Store frequently-used item Selection IDs

  7. Off-Peak Scheduling:

  8. Schedule bulk operations (monthly billing) during off-peak hours
  9. 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:

  1. Discount Line Item: Add negative price line item
  2. Pre-calculate: Subtract discount from unit price before creation
  3. 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:

  1. Timer Trigger: Periodically fetch invoices by document number
  2. Store Sage data in CRM (status, amounts, dates)
  3. 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_invoice to 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:

  1. CRM Recurring Workflow:
  2. Timer Trigger: Monthly/weekly
  3. Create invoice via Sage task
  4. Store in CRM for tracking

  5. Sage Internal Recurring:

  6. Set up recurring invoices in Sage One UI
  7. 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


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)