Developers / Numbers

Numbers / Receivables / Invoices

Batch-ingest receivables invoices and drive their commit/void lifecycle.

POST /v1/numbers-receivables-invoices
POST /v1/numbers-receivables-invoices/{id}/commit
POST /v1/numbers-receivables-invoices/{id}/void

Persists 1–500 receivables invoices in a single JSON request. Each item becomes its own transaction header with capture_channel='api_partner'; lines are exploded into three legs (trading, VAT bucket, AR control). The per-item post_status field controls whether the header lands as draft (d) or committed (c). Lifecycle endpoints transition existing headers individually.

Required scope

numbers.receivables-invoices.write

Batch request

Content-Type: application/json

POST /v1/numbers-receivables-invoices
{
  "schema_version": "1.0.0",
  "items": [
    {
      "external_identifier": "019f0000-aaaa-7bbb-8ccc-1234567890ab",
      "counterparty_identifier": "019f1111-bbbb-7ccc-9ddd-222222222222",
      "transaction_date": "2026-05-28",
      "due_date":         "2026-06-27",
      "transaction_currency": "ZAR",
      "narration": "Consulting fees - May 2026",
      "post_status": "committed",
      "lines": [
        { "order": 1, "account_number": "4000", "description": "Consulting fee", "line_amount": "1000.00", "vat201_rate_code": "20180401-1" }
      ]
    }
  ]
}

Item fields

FieldRequiredNotes
external_identifierNoPartner UUID v7. Unique per client; re-using returns 409 external-identifier-conflict.
counterparty_identifierYesMosaic-issued counterparty UUID. Must have an active trade-receivables control account.
transaction_dateYesYYYY-MM-DD.
due_dateNoYYYY-MM-DD.
transaction_currencyYesISO 4217 alpha-3 (uppercase).
narrationYes1–250 chars.
purchase_order_numberNo≤ 50 chars.
document_numberNoWhen omitted, server allocates the next INV-NNNNNN.
post_statusNodraft (default) or committed.
linesYes1+ lines; each order, account_number, description, line_amount, vat201_rate_code. account_number is resolved to an active account; unknown numbers fail the item with account-number-unknown.

Batch response

Returns 200 whenever at least one item was persisted (per-item outcomes in results[]). Returns 422 with the same body shape when every item failed.

200 OK (application/json)
{
  "schema_version": "1.0.0",
  "submitted_count": 1,
  "succeeded_count": 1,
  "failed_count":    0,
  "results": [
    {
      "index": 0,
      "status": "created",
      "transaction_header_identifier": "019f1234-5678-7abc-9def-0123456789ab",
      "external_identifier": "019f0000-aaaa-7bbb-8ccc-1234567890ab",
      "post_status_effective": "committed",
      "document_number": "INV-000123",
      "_links": { "self": "/v1/numbers-receivables-invoices/019f1234-5678-7abc-9def-0123456789ab" },
      "warnings": []
    }
  ]
}

Lifecycle

EndpointTransitionNotes
POST /{id}/commitdcRefused with 409 state-transition-invalid if the current status is not d.
POST /{id}/voidd|cvRefused with 409 vat-return-locked if the transaction date sits on or before any active lock (vat_period_locked_date, numbers_date_locked_final, numbers_date_locked). Refused with 409 asset-register-linked if the invoice has active asset-register cost entries. Soft-locks cannot be bypassed by API partners.

Lifecycle endpoints take no request body, require an Idempotency-Key, and return 204 No Content on success.

VAT rate identifiers

Identical to Spending Methods. Use the SARS-aligned codes (e.g. 20180401-1 for standard-rated output VAT) on each line.

Idempotency

Same semantics as Spending Methods: a fresh UUID v7 per logical request, replays return the original body plus an Idempotent-Replay: true header.

Errors (per item)

Problem typeWhen it occurs
counterparty-not-foundcounterparty_identifier does not belong to the client.
counterparty-receivables-account-missingCounterparty has no active trade-receivables control account.
account-number-unknownOne or more account_number values cannot be resolved.
vat-rate-unknownOne or more vat201_rate_code values cannot be resolved.
vat-control-account-missingNo active VAT control account configured for the client.
external-identifier-conflictexternal_identifier is already used for this client.
double-entry-imbalancedServer-side double-entry guard failed.