Pagination & filters
Every list endpoint returns the same envelope — a resource-named array plus meta:
{
"templates": [ /* rows */ ],
"meta": {
"count": 12,
"limit": 50,
"offset": 0,
"hasMore": true
// "total": 4231 // present only when totalResults=true
}
}Query parameters:
limit— page size, default50, max100.offset— rows to skip, default0.sortBy—fieldName:ascor:desc; allowed fields are listed per endpoint.totalResults—trueto includemeta.total.
Response shapes
Single resources are bare. GET /templates/:id returns the template's fields directly — not wrapped in { template: … }. Same for GET /jobs/:id, GET /sign-requests/:id, and the corresponding POST creates.
{
"id": "…",
"name": "Invoice",
"fields": [ … ],
"active": true,
"updatedAt": "2026-06-08T12:00:00Z"
}Lists carry a resource-named array key plus meta. See Pagination & filters above.
Render endpoints negotiate via Accept. POST /generate and POST /bulk stream binary when you set Accept: application/pdf or Accept: application/zip respectively; anything else (including the default */*) returns JSON with a presigned download URL.
Money fields are integer EUR cents paired with "currency": "eur". Same convention as Stripe's amount fields — no decimals on the wire.
Errors use { "error": "machine_code", "detail": "human message" }. The machine code is stable across releases; the detail is for humans and may change.
Need help?
Open a ticket from the in-app Support page, or email [email protected].