PDFs
Render a finished PDF for any customer- or vendor-facing document. The same templates the FinzBooks dashboard uses produce the bytes — branch identity, GSTIN block, HSN/SAC summary, signature image, declaration text all in place.
Each endpoint returns the raw PDF inline so a browser tab can preview it. Pass ?download=true when you want a forced Content-Disposition: attachment instead. The first call for a given document version triggers Puppeteer; subsequent calls return a cached S3 object via redirect, which is why download is fast on the second hit.
Authentication & scopes
Every PDF route gates on the resource's standard READ scope. A token that can list invoices (AIBooks.invoices.READ) can download invoice PDFs — there is no separate “PDF” scope. Multi-org tokens must include ?organization_id on every call.
Common request headers
Authorization: Bearer aibooks_pat_XXXX... // PAT or OAuth access token
X-AIBooks-Org: org_8f9a1c2d // required for multi-org tokens
Accept: application/pdfCommon response headers
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="INV-2026-0042.pdf"
Content-Length: 184236
Cache-Control: private, max-age=900
X-AIBooks-Render: cached // or "fresh" on a first render
X-AIBooks-Version: 7 // document version this PDF was rendered against
<binary PDF bytes>When ?download=true is supplied theContent-Disposition flips to attachment so the browser writes the file to disk instead of opening it.
/invoices/{invoice_id}/pdfInvoice PDFAIBooks.invoices.READRenders the invoice using the org's active template (configured in Settings → Templates). The branch's GSTIN, signatory name, declaration text, and bank-details footer are pulled in automatically.
| Param | Where | Notes |
|---|---|---|
invoice_id | path | Invoice ID. 404 if not in the active org. |
download | query | Pass true to force an attachment response. |
template | query | Override the org default. One of classic / modern / boxed / tally. Useful when an integrator wants a different look than the dashboard sends. |
Sample request
GET /api/public/v1/invoices/inv_8c3f1a9b/pdf?template=modern&download=true HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2d
Accept: application/pdfSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="INV-2026-0042.pdf"
Content-Length: 184236
X-AIBooks-Render: cached
X-AIBooks-Version: 7
%PDF-1.7
%âãÏÓ
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj
... [184,168 more bytes] ...
%%EOFStatus doesn't matter — DRAFT and CANCELLED invoices render too, with their state visible at the top of the document. Approved invoices include the IRN + QR when e-invoicing is enabled for the branch.
/bills/{bill_id}/pdfBill PDFAIBooks.bills.READRenders the vendor bill from the same template family. Note this is the internal-facingrepresentation — you typically don't email a bill back to the vendor (they sent you theirs). Use this for archival or for sending a copy to an internal approver.
Sample request
GET /api/public/v1/bills/bill_2d4e6f8a/pdf HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2d
Accept: application/pdfSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="BILL-2026-0118.pdf"
Content-Length: 152042
X-AIBooks-Render: fresh
X-AIBooks-Version: 2
%PDF-1.7 ... [binary bytes] ... %%EOF/estimates/{estimate_id}/pdfEstimate PDFAIBooks.estimates.READStandard quote layout with line items, totals, expiry date, and a footer noting validity. Recipients usually receive this attached to an email via the /estimates/{id}/email endpoint — that wraps this same render with an SES delivery.
Sample request
GET /api/public/v1/estimates/est_9b1c3d5e/pdf HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2dSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="EST-2026-0073.pdf"
Content-Length: 96512
X-AIBooks-Render: cached
X-AIBooks-Version: 3
%PDF-1.7 ... [binary bytes] ... %%EOF/credit_notes/{credit_note_id}/pdfCredit note PDFAIBooks.creditnotes.READIncludes a clear “Credit Note” banner so it doesn't get confused with a fresh invoice during GST review. Parent invoice number is referenced in the metadata block when the credit note was raised against one.
Sample request
GET /api/public/v1/credit_notes/cn_7a2b4c6d/pdf?download=true HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2dSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="CN-2026-0015.pdf"
Content-Length: 72944
X-AIBooks-Render: cached
X-AIBooks-Version: 1
%PDF-1.7 ... [binary bytes] ... %%EOF/debit_notes/{debit_note_id}/pdfDebit note PDFAIBooks.debitnotes.READBuyer-side version of the above. Includes the reason text + reference to the original bill where present.
Sample request
GET /api/public/v1/debit_notes/dn_5e7f9a1b/pdf HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2dSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="DN-2026-0008.pdf"
Content-Length: 68812
X-AIBooks-Render: fresh
X-AIBooks-Version: 1
%PDF-1.7 ... [binary bytes] ... %%EOF/purchase_orders/{purchase_order_id}/pdfPurchase order PDFAIBooks.purchaseorders.READStandard PO layout with line items, expected delivery date, and the buyer's shipping address. Emitted to vendors as a confirmation document before they raise their invoice.
Sample request
GET /api/public/v1/purchase_orders/po_1a3b5c7d/pdf?download=true HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2dSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="PO-2026-0044.pdf"
Content-Length: 88216
X-AIBooks-Render: cached
X-AIBooks-Version: 4
%PDF-1.7 ... [binary bytes] ... %%EOF/payments/{payment_id}/pdfPayment voucher PDFAIBooks.payments.READA receipt document showing the payment amount, mode (BANK / CASH / UPI / CHEQUE), reference / UTR number, and the invoice(s) or bill(s) the payment was applied against. Used as proof-of-payment by both sides of the transaction.
Sample request
GET /api/public/v1/payments/pay_9d8c7b6a/pdf HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2dSample response
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="PAY-RCT-2026-0211.pdf"
Content-Length: 52480
X-AIBooks-Render: cached
X-AIBooks-Version: 1
%PDF-1.7 ... [binary bytes] ... %%EOFErrors
On failure the response flips to application/json and the standard envelope shape:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"code": "not_found.resource",
"message": "Invoice 'inv_unknown' not found in this organization."
}| Code | HTTP | When |
|---|---|---|
not_found.resource | 404 | The document doesn't exist in the active org. |
auth.insufficient_scope | 403 | Token doesn't hold the required READ scope. |
validation.invalid_value | 400 | Unknown template value. |
Implementation notes
- PDFs are cached per (document_id, version). Editing the document increments the version, forcing the next request to re-render.
- The first render after a version bump can take up to a few seconds — Puppeteer cold-start. Cached fetches are sub-100ms (a 302 to a presigned S3 URL).
- Use
?template=…to A/B different layouts without changing the org's default in Settings.