Resources
Invoices
Invoices are issued documents, optionally linked to a quotation. The detail endpoint includes line items and recorded payments.
List invoices
GET
/api/v1/invoicesReturns invoices in your org, newest first, cursor-paginated.
Query parameters:
limit,cursor— see pagination.status— optional, one ofDRAFT,SENT,PAID,OVERDUE,VOID.
terminal
curl "https://www.zengbook.com/api/v1/invoices?status=OVERDUE" \
-H "Authorization: Bearer zb_live_..."200 OK (list)
{
"data": [
{
"id": "inv_01HX...",
"number": "INV-2026-0117",
"title": "Progress claim #2 — May",
"status": "OVERDUE",
"clientId": "cli_01HX...",
"projectId": "prj_01HX...",
"quotationId": "qtn_01HX...",
"notes": null,
"issuedAt": "2026-04-30T00:00:00.000Z",
"dueDate": "2026-05-14T00:00:00.000Z",
"gstRateAtIssue": 0.09,
"retentionPct": 0.05,
"createdAt": "2026-04-30T01:22:14.000Z",
"updatedAt": "2026-05-15T00:00:01.000Z"
}
],
"hasMore": true,
"nextCursor": "eyJpZC..."
}Get an invoice
GET
/api/v1/invoices/{id}Returns one invoice, including its line items (sorted by sortOrder asc) and recorded payments (newest first).
terminal
curl https://www.zengbook.com/api/v1/invoices/inv_01HX... \
-H "Authorization: Bearer zb_live_..."200 OK (detail)
{
"id": "inv_01HX...",
"number": "INV-2026-0117",
"title": "Progress claim #2 — May",
"status": "OVERDUE",
"clientId": "cli_01HX...",
"projectId": "prj_01HX...",
"quotationId": "qtn_01HX...",
"notes": null,
"issuedAt": "2026-04-30T00:00:00.000Z",
"dueDate": "2026-05-14T00:00:00.000Z",
"gstRateAtIssue": 0.09,
"retentionPct": 0.05,
"items": [
{
"id": "ili_01HX...",
"description": "Phase 2 — Carpentry installation (40%)",
"qty": 1,
"unitPrice": 18000,
"sortOrder": 0
}
],
"payments": [
{
"id": "pmt_01HX...",
"amount": 5000,
"paidAt": "2026-05-09T00:00:00.000Z",
"method": "BANK_TRANSFER",
"note": "Partial — DBS FAST"
}
],
"createdAt": "2026-04-30T01:22:14.000Z",
"updatedAt": "2026-05-15T00:00:01.000Z"
}Status lifecycle
DRAFT— created but not issued.SENT— issued; due date set.PAID— full payment recorded.OVERDUE— pastdueDatewithout full payment. Set automatically by an hourly cron.VOID— cancelled; no further mutations expected.
Computing totals
The same algorithm as quotations applies. Subtotal → retention → net → GST → total. The payments array tells you how much is still outstanding:
typescript
const subtotal = items.reduce((s, it) => s + it.qty * it.unitPrice, 0)
const retention = subtotal * (inv.retentionPct ?? 0)
const net = subtotal - retention
const gst = net * inv.gstRateAtIssue
const total = net + gst
const paid = payments.reduce((s, p) => s + p.amount, 0)
const outstanding = total - paidRelated webhook events
invoice.createdinvoice.sentinvoice.paidinvoice.overdue(fired by the hourly cron)invoice.voidedpayment.recorded
See the event reference for payload shapes.