Conventions
Format
- Request and response bodies are JSON (
Content-Type: application/json), with three exceptions: endpoints that attach a file usemultipart/form-data(see Uploading files); the report export endpoints return a PDF or Excel file; andgetPaymentViewreturns HTML. - Property names are
camelCase. - Dates and timestamps are ISO 8601 strings, for example
2026-09-25or2026-09-25T00:00:00.000Z. - Amounts are plain JSON numbers in the business's currency, rounded to 2 decimals.
IDs are chosen by the caller
Records such as contacts, items, accounts, taxes, transactions and payments are identified by a string ID (contactId, itemId, accountId, taxId, txnId, paymentId) that you generate when creating the record. Use a UUID or another globally unique string.
Create, update and upsert
Write endpoints are named upsert…. If a record with that ID already exists in your business it is updated; otherwise it is created. There is no separate create/update call. To update, send the full record again with the same ID — fields you omit are treated as unset, so read the record first, modify it, and send it back.
Because the ID is yours, retrying a timed-out create with the same ID does not produce a duplicate.
Lists and "no content"
List endpoints return a JSON array. When there is nothing to return they respond 204 No Content with an empty body rather than 200 [] — make sure your client handles an empty body.
Incremental sync (gtimeStamp)
Many list endpoints take an optional trailing path segment, /{gtimeStamp}. Pass an ISO 8601 timestamp (URL-encoded) to receive only records changed at or after that time — use this to sync efficiently instead of downloading everything each run.
GET /masterdata/getItems/2026-09-01T00%3A00%3A00.000Z
An invalid timestamp returns 400.
JSON in query strings
Filters on read endpoints are passed as JSON encoded into a query parameter (URL-encode it):
curl -G "$BASE_URL/txndata/getTxns/Invoice" \
-H "x-api-key: YOUR_API_KEY" \
--data-urlencode 'dateFilter={"predefinedDateFilter":"Custom","fromDate":"2026-04-01","toDate":"2026-09-25"}'
dateFilter
| Field | Type | Notes |
|---|---|---|
predefinedDateFilter | string | One of Today, Yesterday, ThisWeek, LastWeek, ThisMonth, LastMonth, Last30Days, Last90Days, ThisQuarter, LastQuarter, ThisYear, LastYear, Custom, AllTime. |
fromDate, toDate | ISO 8601 string | Used with Custom. |
fyStartMonth, fyStartDay | integer | Optional financial-year start (month 1–12, day 1–31) for ThisYear/LastYear. |
Unknown properties in dateFilter are rejected with 400.
Uploading files
upsertTxn, upsertPayment, upsertItemwFile and upsertContactwFile accept an optional attachment, so they take multipart/form-data instead of a JSON body. The record itself is sent as a JSON string in a form field:
| Endpoint | JSON field | File field |
|---|---|---|
POST /txndata/upsertTxn | txnDto | file |
POST /txndata/upsertPayment | paymentDto | file |
POST /masterdata/upsertItemwFile | itemDto | files (one or more) |
POST /masterdata/upsertContactwFile | contact | file (one or more) |
curl -X POST "$BASE_URL/txndata/upsertTxn" \
-H "x-api-key: YOUR_API_KEY" \
-F 'txnDto={"txnHeader":{...},"lineItems":[...]}'
Note that upsertTxn and upsertPayment always use multipart, even with no attachment. upsertItem and upsertContact (without a file) take a plain JSON body.