Developers
REST API
Read and write any record over a predictable REST interface — list, filter, create, update and act on resources.
The REST API exposes the same records and operations as the interface. If you understand the data model, the endpoints follow naturally: each resource has a collection and a member URL with the usual verbs.
Resource conventions#
| Verb | Path | Does |
| --- | --- | --- |
| GET | /v1/{resource} | List, with filtering and pagination |
| GET | /v1/{resource}/{id} | Fetch one record |
| POST | /v1/{resource} | Create a record |
| PATCH | /v1/{resource}/{id} | Update fields on a record |
| POST | /v1/{resource}/{id}/{action} | Run an action (e.g. confirm, post) |
List and filter#
Collections support filtering, field selection, sorting and cursor pagination:
curl "https://acme.quelixa.com/api/v1/invoices?\
state=posted&\
fields=number,partner,amount_total,state&\
sort=-date&\
limit=50" \
-H "Authorization: Bearer qx_live_8f2c…"{
"data": [
{
"id": "inv_01HX…",
"number": "INV/2026/0042",
"partner": { "id": "res_01H…", "name": "Globex" },
"amount_total": 1260.00,
"state": "posted"
}
],
"next_cursor": "eyJpZCI6…"
}Use fields to keep responses small and stable. Relations are returned as nested objects with an id and a label so you rarely need a second round-trip.
Create a record#
Posting to a collection creates a draft. Most documents then need an explicit action to take effect — mirroring "save" then "confirm" in the app.
# 1. Create a draft invoice
curl -X POST https://acme.quelixa.com/api/v1/invoices \
-H "Authorization: Bearer qx_live_8f2c…" \
-H "Content-Type: application/json" \
-d '{
"partner": "res_01H…",
"lines": [
{ "product": "prd_204", "quantity": 10, "price_unit": 100 }
]
}'
# 2. Confirm it — assigns the number and posts the journal entry
curl -X POST https://acme.quelixa.com/api/v1/invoices/inv_01HX…/confirm \
-H "Authorization: Bearer qx_live_8f2c…"Creating a record rarely touches the ledger. The confirm/post/pay actions are what validate, number and post — exactly as in the interface. Design integrations around create-then-act.
Errors#
Errors use standard HTTP status codes with a JSON body describing the problem.
| Status | Meaning |
| --- | --- |
| 400 | Malformed request or invalid field |
| 401 | Missing or invalid token |
| 403 | Token lacks the required scope |
| 404 | No such record in this workspace |
| 422 | Business rule rejected the operation |
| 429 | Rate limited — back off and retry |
{
"error": {
"type": "validation_error",
"message": "Partner is required to confirm an invoice.",
"field": "partner"
}
}Rate limits#
Calls are rate limited per token. When you exceed the limit you get 429 with a Retry-After header; honour it with exponential backoff.
Don't poll for changes on a tight loop — it burns your rate budget. Subscribe to webhooks and react to events as they happen.