Resources
Quotations
A Quotation is a priced proposal sent to a client. Quotations can be BQ-structured (sections with line items) and carry the GST rate and retention percentage active at the time of issue.
List quotations
GET
/api/v1/quotationsReturns quotations in your org, newest first, cursor-paginated.
Query parameters:
limit,cursor— see pagination.status— optional, one ofDRAFT,SENT,ACCEPTED,REJECTED.
terminal
curl "https://www.zengbook.com/api/v1/quotations?status=ACCEPTED" \
-H "Authorization: Bearer zb_live_..."200 OK (list)
{
"data": [
{
"id": "qtn_01HX...",
"number": "Q-2026-0042",
"title": "Tampines BTO — Carpentry package",
"status": "ACCEPTED",
"clientId": "cli_01HX...",
"projectId": "prj_01HX...",
"notes": null,
"gstRateAtIssue": 0.09,
"retentionPct": 0.05,
"createdAt": "2026-04-10T03:00:00.000Z",
"updatedAt": "2026-04-18T11:42:33.000Z"
}
],
"hasMore": false,
"nextCursor": null
}The list response omits line items. Call the detail endpoint to fetch them.
Get a quotation
GET
/api/v1/quotations/{id}Returns a single quotation including its line items.
terminal
curl https://www.zengbook.com/api/v1/quotations/qtn_01HX... \
-H "Authorization: Bearer zb_live_..."200 OK (detail)
{
"id": "qtn_01HX...",
"number": "Q-2026-0042",
"title": "Tampines BTO — Carpentry package",
"status": "ACCEPTED",
"clientId": "cli_01HX...",
"projectId": "prj_01HX...",
"notes": null,
"gstRateAtIssue": 0.09,
"retentionPct": 0.05,
"items": [
{
"id": "qli_01HX...",
"description": "Built-in wardrobe — master bedroom",
"qty": 1,
"unitPrice": 4800,
"sortOrder": 0
},
{
"id": "qli_02HX...",
"description": "Kitchen overhead cabinets",
"qty": 1,
"unitPrice": 3600,
"sortOrder": 1
}
],
"createdAt": "2026-04-10T03:00:00.000Z",
"updatedAt": "2026-04-18T11:42:33.000Z"
}Computing totals
The API returns line-item-level numbers. To compute a quotation total exactly the way Zeng Book does (subtotal → retention → net → GST → total), follow this order:
typescript
const subtotal = items.reduce((sum, it) => sum + it.qty * it.unitPrice, 0)
const retention = subtotal * (q.retentionPct ?? 0)
const net = subtotal - retention
const gst = net * q.gstRateAtIssue
const total = net + gstGST and retention are snapshotted at issue, so historical numbers stay stable even when the org changes its current GST rate.
Related webhook events
quotation.createdquotation.sentquotation.acceptedquotation.rejected
See the event reference for payload shapes.