vsmsconnect — API — accounting-push

← all endpoints

POST/api/v1/businesses/:businessId/accounting/sage100/sync auth: apikey

On-premise Sage 100 agent push. Headless agent POSTs a batch of normalised `AccountingInvoice[]` for the business; the helper inserts → dedupes → auto-fiscalises (when the flag is on). API key must have `scope=sage100` (enforced by `requireScope`); empty array is allowed (used by the agent's first-run dry-run wizard).

handlers: AccountingAgentSyncController.syncSage100

Inputs

namerequireddefaultdescription
businessId path
uuid
yes—Target business UUID. Must match the API key's `BusinessId`.
Authorization header
string
yes—`ApiKey <key>` — validated by `requireApiKey` against `ApiKeys.KeyHash`.
invoices body
PushInvoice[]
yes—Array of pushed invoices. Each entry mirrors `AccountingInvoice` with optional `posSaleId`/`posRegisterId`/`originalPosSaleId`/`cashierId`/payment `tenders[]`. Empty array allowed.

Outputs

200
APIResponseDataObject<PushInvoicesResponse>
`{ fetched, inserted, duplicates, jobIds[], outcomes[] }`.
401
APIError
Missing or invalid API key.
403
APIError
API key scope does not match `sage100`.
POST/api/v1/businesses/:businessId/accounting/sage300/sync auth: apikey

On-premise Sage 300 agent push. Same shape as the Sage 100 endpoint but scope-bound to `sage300`.

handlers: AccountingAgentSyncController.syncSage300

Inputs

namerequireddefaultdescription
businessId path
uuid
yes—Target business UUID.
Authorization header
string
yes—`ApiKey <key>`.
invoices body
PushInvoice[]
yes—Array of pushed invoices.

Outputs

200
APIResponseDataObject<PushInvoicesResponse>
Push result summary.
401
APIError
Missing or invalid API key.
403
APIError
API key scope does not match `sage300`.
POST/api/v1/businesses/:businessId/accounting/sage200evolution/sync auth: apikey

On-premise Sage 200 Evolution agent push. Scope-bound to `sage200evolution`. Per-row register→till routing via `Tills.PosRegisterId`; unrouted invoices return `outcomes[].outcome='register_unmapped'` and fire `SAGE200_RECEIPT_UNROUTED` audit. Supports advance-sale deposits (one `AccountingInvoicePayment` per `_etblInvoiceDeposits` row, fan-out to N `NormalizedInvoicePayment`s).

handlers: AccountingAgentSyncController.syncSage200Evolution

Inputs

namerequireddefaultdescription
businessId path
uuid
yes—Target business UUID.
Authorization header
string
yes—`ApiKey <key>`.
invoices body
PushInvoice[]
yes—Array of pushed invoices. Deposit rows arrive as separate payments under the same invoice.

Outputs

200
APIResponseDataObject<PushInvoicesResponse>
Push result summary including per-invoice `outcomes` for unrouted receipts.
401
APIError
Missing or invalid API key.
403
APIError
API key scope does not match `sage200evolution`.
POST/api/v1/businesses/:businessId/accounting/amicus/sync auth: apikey

On-premise AMICUS agent push. Scope-bound to `amicus`. Per-row register→till routing (null till → sign-but-don't-print), `PosSaleId` persisted on `Invoices`, refund referent resolution via `originalPosSaleId`. Supports split-tender (one payment with `tenders[]`). Unrouted invoices return `outcomes[].outcome='register_unmapped'` and fire `AMICUS_RECEIPT_UNROUTED` audit.

handlers: AccountingAgentSyncController.syncAmicus

Inputs

namerequireddefaultdescription
businessId path
uuid
yes—Target business UUID.
Authorization header
string
yes—`ApiKey <key>`.
invoices body
PushInvoice[]
yes—Array of pushed invoices. Each may carry `posSaleId`, `posRegisterId`, `originalPosSaleId`, `cashierId`, and split-tender `payments[].tenders[]`.

Outputs

200
APIResponseDataObject<PushInvoicesResponse>
Push result summary including per-invoice `outcomes` for unrouted receipts.
401
APIError
Missing or invalid API key.
403
APIError
API key scope does not match `amicus`.
GET/api/v1/businesses/:businessId/accounting/sync/status auth: jwt (administrator | view_invoices | submit_invoices)

Return the last-push timestamp per on-premise source (sage100, sage300, sage200evolution, amicus) for the business. Reads `ImportBatches.CreatedAt` per source via `findLatestCreatedAtBySources`; null when the source has never pushed.

handlers: AccountingAgentSyncController.status

Inputs

namerequireddefaultdescription
businessId path
uuid
yes—Target business UUID.

Outputs

200
APIResponseDataObject<PushStatusResponse>
Map of source → `{ lastPushAt: string | null }` (ISO-8601 timestamp).
403
APIError
USER_FORBIDDEN — businessId on path does not match the caller's JWT.