AccountingKitDocs

Provider-native Xero API

Lossless Xero operations for accounting workflows that exceed the portable model.

Why this API exists

The normalized resource API covers portable accounting fields. Production quote-to-cash and procure-to-pay workflows also depend on provider-native fields such as Xero ContactPersons, Terms, BrandingThemeID, LineAmountTypes, delivery instructions, and status transition rules. AccountingKit therefore exposes a typed transport boundary without discarding the original Xero document.

Native operations use the same API key, connection authorization, rate budget, audit log, idempotency, encrypted raw cache, and provider error handling as normalized operations.

One active AccountingKit connection owns each Xero tenant. This is required because Xero sends app-wide webhook events with a tenant ID but no AccountingKit environment identifier; ambiguous tenant ownership is rejected during connection rather than routed by recency.

Live provider lookup

Fetch and cache a resource when the caller already holds its immutable Xero ID:

GET /v1/connections/{connection_id}/invoices/by-provider-id/{xero_invoice_id}

Search Xero live with constrained exact filters:

POST /v1/connections/{connection_id}/quotes/search
Content-Type: application/json

{"number":"QU-1042"}

Supported filters are provider_id, external_reference, number, name, status, and page. Arbitrary Xero where clauses are intentionally not exposed.

Lossless writes

Send a single native Xero resource inside provider_data. The standard Idempotency-Key header is required.

POST /v1/connections/{connection_id}/invoices
Idempotency-Key: order-ZEN-1042
Content-Type: application/json

{
  "provider_data": {
    "Type": "ACCREC",
    "Contact": {"ContactID": "..."},
    "Reference": "ZEN-1042",
    "LineAmountTypes": "Inclusive",
    "LineItems": [],
    "Status": "AUTHORISED"
  }
}

For a status or partial update where omitted Xero fields must be retained, set preserve_existing: true. AccountingKit fetches the live provider record, overlays the supplied fields, and writes the merged document.

Accounts use Xero's account-specific transport (PUT /Accounts to create and POST /Accounts/{AccountID} to update). Contacts, invoices, quotes, payments, purchase orders, and accounts accept provider-native creates where Xero supports them. Organizations, tax rates, and branding themes are explicitly read-only in v1.

Quote search uses Xero's native QuoteNumber and Status parameters and then applies an exact client-side match because Xero's quote-number filter is partial. Quote conversion follows Xero's state machine (DRAFT → SENT → ACCEPTED → INVOICED) and strips quote-owned line IDs and calculated amounts before creating the invoice.

Rendered documents

The provider actions support Xero-rendered invoice, quote, and purchase-order PDFs:

  • invoice.download_pdf
  • quote.download_pdf
  • purchase_order.download_pdf

Pass either AccountingKit's resource_id or Xero's provider_id. Invoice online URLs and organization deep links remain separate provider actions.

Payment lifecycle

Xero invoice webhooks trigger a targeted live read. AccountingKit maintains a dedicated payment projection per connection and invoice, so unrelated reads cannot erase the prior webhook state. The durable operation emits:

  • invoice.updated for every accepted invoice event;
  • invoice.payment_changed when status, amount paid, or amount due changes;
  • invoice.paid only on a transition from a non-paid state to paid.

The transition snapshot is persisted as an operation step before delivery. If delivery dispatch fails and the operation retries, the original transition is replayed instead of being lost.

Invoice cancellation

Cancel an invoice through the dedicated idempotent action:

POST /v1/connections/{connection_id}/invoices/{resource_id}/cancel
Idempotency-Key: cancel-order-ZEN-1042
Content-Type: application/json

{"reason":"Customer cancelled before onboarding"}

When the caller already stores Xero's immutable invoice ID, use POST /v1/connections/{connection_id}/invoices/by-provider-id/{xero_invoice_id}/cancel.

AccountingKit reads the current invoice from Xero before choosing the transition. DRAFT and SUBMITTED invoices become DELETED; unpaid AUTHORISED invoices become VOIDED; already deleted or voided invoices succeed idempotently. Paid, part-paid, credited, and unknown states are rejected instead of guessing or issuing an invalid Xero mutation.

On this page