Accounting platforms
One API over Dinero and e-conomic — what is identical, what a platform can refuse, and the fields that name a choice out of its own lists.
An Invoia key is bound to one connected accounting integration, and that integration is on one accounting platform — today Dinero or e-conomic. Which one it is, is not something your integration has to know.
Every endpoint under /api/v1 behaves the same way on either platform:
the same request bodies, the same response shapes, the same status codes
and the same error code strings. You write the integration once, and it
keeps working when a customer of yours connects the other platform.
What stays the same
- Field names never change by platform. Notably
dinero_invoice_guid,dinero_invoice_number,dinero_credit_note_guidanddinero_credit_note_numbermean "the handle the accounting platform gave this document", whichever platform that is. The names are frozen/v1surface, so they stayed put when the second platform arrived rather than being duplicated per platform. On e-conomic they carry the booked document's own number. DINERO_API_ERRORmeans the same thing. It is the502for "the accounting platform behind your integration failed". Retry it with backoff on either platform.send_errormeans the same thing.nullon a clean issuance, a string when the document was booked but the send to the customer failed. On e-conomic, sending is part of the booking call and cannot fail on its own, so a booked document there always reportsnull— a possible value on both, never a different shape.- Amounts, dates, currencies, recognition, accruals and month-end are Invoia's own arithmetic and are identical by construction.
Fields that name a platform's own choice
A few fields name an entry out of a list the platform keeps. A platform
that keeps no such list reads null and ignores the field, so it is
always safe to send one.
| Field | On Dinero | On e-conomic |
|---|---|---|
customers.vat_zone_ref | null — no VAT zones | required — the agreement's VAT zone |
customers.payment_terms_ref | null | the agreement's payment-terms entry |
customers.layout_ref | null | the customer's default document layout |
customers.customer_group_ref | null — no customer groups | required — the customer group the customer is filed in |
products.account_ref | the account number, as text | required — the product group the revenue is filed in |
Where a value is required and missing, the create comes back as 422 VALIDATION_FAILED with the field named in field_errors — the same
shape as any other validation failure.
To discover the valid values, read an already-mirrored customer or
product (GET /customers, GET /products): every mirrored record echoes
the references the platform holds for it. The workspace's customer and
product editors list what the agreement offers.
Capability-based refusals
Where a platform genuinely cannot do something, the API says so in a stable code rather than letting the platform's own error reach you. Two codes carry this, and neither is retryable with the same payload:
| Code | Status | What happened |
|---|---|---|
PLATFORM_UNSUPPORTED | 403 | The platform behind this key cannot do what the endpoint needs. The message names the platform and the capability. |
PLATFORM_NOT_CONFIGURED | 409 | The connection is missing a choice its platform requires of every record — an e-conomic agreement whose document defaults were never confirmed. An admin finishes the Configure step in the workspace; nothing about your request changes. |
HTTP/1.1 403 Forbidden
{
"error": {
"type": "permission_error",
"code": "PLATFORM_UNSUPPORTED",
"message": "This integration is on a platform that does not support invoicing",
"request_id": "req_…"
}
}Treat PLATFORM_UNSUPPORTED the way you treat SCOPE_INSUFFICIENT: a
property of the credential, not of the call. Stop issuing that request
for that key and surface the message to whoever connected the
integration.
Two further platform differences never reach the API as a refusal, because nothing on the API asks for them:
- e-conomic has no credit-note document type. Crediting an invoice
works on both platforms and
POST /credit-notesis identical; what differs is the document that lands in the books — on e-conomic it is a customer invoice with negative amounts, drawn from the invoice number sequence. - e-conomic keeps no readable record of what became of a send, and a booked document there cannot be sent again through the API. Invoia's own resend lives in the workspace, not on the Public API, so this shows up only there.
E-invoices
Sending over the public-sector e-invoice network works on both platforms.
A customer whose send_method is einvoice on a platform that cannot
route one is refused before anything is booked, as 422 INVALID_SEND_METHOD — the same code as an unknown send method, because
in both cases the fix is on the customer record.