Zeng Book
ProductIndustriesIntegrationsPricingResources
Sign inContact salesTry it free
Introduction
  • Overview
  • Quickstart
API reference
  • Authentication
  • Errors
  • Rate limits
  • Pagination
  • Interactive explorer
Resources
  • Organization
  • Leads
  • Clients
  • Projects
  • Quotations
  • Invoices
Integrations
  • Overview
  • Webhooks
  • Public portal
  • Zapier
  • Make / n8n recipes
  • Xero (coming soon)

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/quotations

Returns quotations in your org, newest first, cursor-paginated.

Query parameters:

  • limit, cursor — see pagination.
  • status — optional, one of DRAFT, 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 + gst

GST and retention are snapshotted at issue, so historical numbers stay stable even when the org changes its current GST rate.

Related webhook events

  • quotation.created
  • quotation.sent
  • quotation.accepted
  • quotation.rejected

See the event reference for payload shapes.