Documents API¶
Documents are the core resource. Every document carries a document_type — one of
invoice, credit_note, quote, receipt, proforma, purchase_order, or
delivery_note — and follows the same lifecycle, rendering, and delivery flow. Invoices are
simply documents with document_type: "invoice".
This page is the canonical reference for creating, reading, updating, deleting, and transitioning documents, plus the stateless validate/calculate/render operations.
Create Document¶
Creates a draft document linked to a business profile and customer. Returns 200 OK.
Required fields: number, issue_date, currency, business_profile_id,
customer_id, line_items.
number must be unique within your account
Reusing a number returns 409 conflict, naming the document that already
holds it:
{
"error": {
"status": 409,
"code": "conflict",
"message": "Document number 'INV-2026-001' is already used by inv_01ABC"
}
}
The number stays taken once the document is finalized, and stays taken if it
is archived — archiving is not deletion. Uniqueness is per account, so two
businesses may each issue their own INV-2026-001.
This matters beyond tidiness: an invoice number is the document's identity, and a serial unique for the financial year is a requirement under CGST Rule 46 among others. Let the API allocate numbers with numbering sequences if you would rather not manage this yourself.
{
"document_type": "invoice",
"number": "INV-2026-001",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"business_profile_id": "bp_01ABC",
"customer_id": "cus_01XYZ",
"line_items": [
{
"name": "Web Development",
"quantity": "10",
"unit_price": "150.00",
"unit": "hours",
"taxes": [{ "name": "Sales Tax", "rate": "8.875" }]
}
],
"discounts": [
{ "type": "percentage", "value": "5", "reason": "Early bird" }
],
"shipping": {
"description": "Express Delivery",
"amount": "15.00"
},
"custom_fields": [
{ "label": "PO Number", "value": "PO-2026-042" }
],
"payment": {
"instructions": "Wire transfer preferred",
"accepted_methods": ["bank_transfer", "credit_card"],
"bank_account": {
"bank_name": "First National Bank",
"account_number": "1234567890",
"routing_number": "021000021"
}
},
"branding": {
"primary_color": "#0066CC",
"accent_color": "#003366",
"footer_text": "Thank you for your business!"
}
}
If document_type is omitted it defaults to invoice.
Response:
{
"data": {
"id": "doc_01ABC",
"document_type": "invoice",
"number": "INV-2026-001",
"status": "draft",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"locale": null,
"business_profile_id": "bp_01ABC",
"customer_id": "cus_01XYZ",
"source_document_id": null,
"reason": null,
"data": { "...full document data..." },
"totals": {
"subtotal": { "amount": "1500.00", "currency": "USD" },
"discount_total": { "amount": "75.00", "currency": "USD" },
"tax_total": { "amount": "126.47", "currency": "USD" },
"shipping_total": { "amount": "15.00", "currency": "USD" },
"total": { "amount": "1566.47", "currency": "USD" }
},
"created_at": "2026-07-20T00:00:00Z",
"updated_at": "2026-07-20T00:00:00Z",
"finalized_at": null
}
}
Pass an Idempotency-Key header to safely retry creation.
Try it
List Documents¶
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Results per page (1–100) |
cursor |
string | — | Pagination cursor |
document_type |
string | — | Filter by document type |
status |
string | — | Filter by status |
Response:
{
"data": [ { "id": "doc_01ABC", "document_type": "invoice", "...": "..." } ],
"pagination": {
"has_more": false,
"next_cursor": null
}
}
Try it
Get Document¶
Fetch a single document by its doc_* id, including its computed totals and
full data. Returns 404 not_found if it doesn't exist.
Response:
{
"data": {
"id": "doc_01ABC",
"document_type": "invoice",
"number": "INV-2026-001",
"status": "sent",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"locale": null,
"business_profile_id": "bp_01ABC",
"customer_id": "cus_01XYZ",
"source_document_id": null,
"reason": null,
"data": { "...full document data..." },
"totals": {
"subtotal": { "amount": "1500.00", "currency": "USD" },
"discount_total": { "amount": "75.00", "currency": "USD" },
"tax_total": { "amount": "126.47", "currency": "USD" },
"shipping_total": { "amount": "15.00", "currency": "USD" },
"total": { "amount": "1566.47", "currency": "USD" }
},
"created_at": "2026-07-20T00:00:00Z",
"updated_at": "2026-07-21T09:00:00Z",
"finalized_at": "2026-07-20T10:00:00Z"
}
}
Try it
Update Document¶
Warning
Only draft documents can be edited. Finalized documents are immutable.
Send only the fields you want to change:
{
"due_date": "2026-09-19",
"line_items": [
{ "name": "Consulting", "quantity": "20", "unit_price": "175.00" }
]
}
Try it
Delete Document¶
Permanently delete a document. Only draft documents can be deleted —
finalized documents are immutable and return 409 conflict.
Response:
Try it
Duplicate Document¶
Creates a new draft copy — same line items and data, a fresh doc_* id, and
status reset to draft. Useful for recurring or near-identical documents;
you'll typically assign a new number with a follow-up update.
The response is the new document (same shape as Get Document).
Try it
Document Lifecycle¶
Documents follow a state machine:
draft → finalized → sent → paid
↘ ↗
→ void
finalized/sent/paid/void → archived → restored (finalized)
Each action below transitions the document and returns the full updated
document (the same shape as Get Document), with status
advanced and the relevant timestamp set (e.g. finalized_at). An action that
isn't allowed from the document's current status returns 409 conflict — see
Allowed State Transitions.
Finalize¶
Lock the document and freeze calculations.
Try it
Mark as Sent¶
Try it
Mark as Paid¶
Try it
Mark as Unpaid¶
Revert a paid document back to sent.
Try it
Void¶
Cancel a finalized or sent document.
Try it
Archive / Restore¶
Try it
Try it
Allowed State Transitions¶
| Current Status | Allowed Actions |
|---|---|
draft |
finalize, delete |
finalized |
mark-sent, void, archive, render, send |
sent |
mark-paid, void, archive |
paid |
mark-unpaid, archive |
void |
archive |
archived |
restore (returns to finalized) |
Render to PDF¶
Generate a PDF for a stored document.
Request:
| Field | Default | Description |
|---|---|---|
template_id |
tpl_modern |
Template to use for rendering |
page_size |
LETTER |
Page size: LETTER or A4 |
expires_in |
3600 |
Seconds until the download URL expires |
Response:
{
"data": {
"id": "rnd_01ABC",
"status": "completed",
"document_type": "invoice",
"format": "pdf",
"download_url": "/api/v1/renders/rnd_01ABC/download",
"calculation": {
"subtotal": { "amount": "1500.00", "currency": "USD" },
"discount_total": { "amount": "75.00", "currency": "USD" },
"tax_total": { "amount": "126.47", "currency": "USD" },
"shipping_total": { "amount": "15.00", "currency": "USD" },
"total": { "amount": "1566.47", "currency": "USD" }
},
"expires_at": "2026-07-20T01:00:00Z",
"created_at": "2026-07-20T00:00:00Z"
}
}
See the Renders API for downloading and inspecting a render.
Try it
Send via Email¶
Send a document by email (it must be finalized first).
See the Deliveries API for the full request/response schema and delivery status tracking.
Try it
List Deliveries¶
Track email delivery status for a document. See the Deliveries API for response details.
Try it
Stateless Operations¶
The following endpoints send data and return results without storing a resource. They accept
a document_type plus an embedded data object (DocumentInvoiceDataInput), which uses
invoice_number, seller, and buyer rather than the stored-document fields (number,
business_profile_id, customer_id).
Validate¶
Validate document data without rendering.
{
"document_type": "invoice",
"data": {
"invoice_number": "INV-001",
"issue_date": "2026-07-20",
"currency": "USD",
"seller": { "name": "Acme Corp" },
"buyer": { "name": "Jane Smith" },
"line_items": [
{ "name": "Service", "quantity": "1", "unit_price": "100.00" }
]
}
}
Response:
Try it
Calculate¶
Compute totals without rendering a PDF.
Same request body as validate. Returns calculated totals:
{
"data": {
"calculation": {
"subtotal": { "amount": "100.00", "currency": "USD" },
"discount_total": { "amount": "0.00", "currency": "USD" },
"tax_total": { "amount": "0.00", "currency": "USD" },
"shipping_total": { "amount": "0.00", "currency": "USD" },
"total": { "amount": "100.00", "currency": "USD" }
}
}
}
Try it
Render (stateless)¶
Generate a PDF directly from data, without creating a stored document.
Every document type is accepted here — invoice, credit_note, quote,
receipt, proforma, purchase_order and delivery_note. The body is the
same for all of them; document_type decides what the finished PDF calls
itself. Use this path when your application already owns the records and only
needs the document; use the managed endpoints above when you want InvoicePDFs to
hold lifecycle, numbering and delivery.
{
"document_type": "invoice",
"data": {
"invoice_number": "INV-001",
"issue_date": "2026-07-20",
"due_date": "2026-08-19",
"currency": "USD",
"seller": {
"name": "Acme Corp",
"legal_name": "Acme Corp Inc.",
"email": "billing@acme.com",
"phone": "+1-555-123-4567",
"tax_id": "US-EIN-12-3456789",
"address": {
"line1": "1 Main St",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US"
}
},
"buyer": {
"name": "Jane Smith",
"email": "jane@example.com"
},
"line_items": [
{
"name": "Web Development",
"description": "Frontend redesign",
"quantity": "10",
"unit_price": "150.00",
"unit": "hours",
"sku": "SVC-WEB-001",
"taxes": [
{ "name": "Sales Tax", "rate": "8.875", "inclusive": false }
]
}
]
},
"template": { "id": "tpl_modern" },
"output": {
"format": "pdf",
"delivery": "url",
"expires_in": 3600
}
}
Response:
{
"data": {
"id": "rnd_01ABC",
"status": "completed",
"document_type": "invoice",
"format": "pdf",
"download_url": "/api/v1/renders/rnd_01ABC/download",
"calculation": {
"subtotal": { "amount": "1500.00", "currency": "USD" },
"discount_total": { "amount": "0.00", "currency": "USD" },
"tax_total": { "amount": "133.13", "currency": "USD" },
"shipping_total": { "amount": "0.00", "currency": "USD" },
"total": { "amount": "1633.13", "currency": "USD" }
},
"expires_at": "2026-07-20T01:00:00Z",
"created_at": "2026-07-20T00:00:00Z"
}
}
Getting the PDF Binary¶
Add Accept: application/pdf or set delivery: "binary" in output to receive the PDF
bytes directly instead of a JSON response with a download URL.
Try it
Document Data Reference¶
The data object of stateless operations describes the document contents.
Parties (seller/buyer)¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Display name |
legal_name |
string | no | Legal entity name |
email |
string | no | Contact email |
phone |
string | no | Phone number |
website |
string | no | Website URL |
tax_id |
string | no | Tax identification number |
registration_number |
string | no | Business registration number |
address |
object | no | Postal address |
bank_account |
object | no | Bank account details |
Line Items¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Item name |
description |
string | no | Item description |
quantity |
string | yes | Decimal quantity (e.g. "2.5") |
unit_price |
string | yes | Price per unit (e.g. "150.00") |
unit |
string | no | Unit label (e.g. "hours", "pcs") |
sku |
string | no | SKU or product code |
discount |
object | no | Per-line discount |
taxes |
array | no | Tax rates applied to this item |
Discounts¶
Per-line discount (on a line item):
Document-level discounts:
Taxes¶
Shipping¶
Custom Fields¶
{
"custom_fields": [
{ "label": "PO Number", "value": "PO-2026-042" },
{ "label": "Project", "value": "Website Redesign" }
]
}
Payment Information¶
{
"payment": {
"instructions": "Please pay within 30 days via wire transfer",
"payment_url": "https://pay.acme.com/inv-001",
"accepted_methods": ["bank_transfer", "credit_card"],
"bank_account": {
"bank_name": "First National Bank",
"account_number": "1234567890",
"routing_number": "021000021",
"swift": "FNBKUS33"
}
}
}
Branding¶
{
"branding": {
"logo_file_id": "fil_01ABC",
"primary_color": "#0066CC",
"accent_color": "#003366",
"font_family": "Inter",
"footer_text": "Thank you for choosing Acme Corp!"
}
}
Ship To¶
{
"ship_to": {
"name": "Warehouse West",
"address": {
"line1": "99 Dock Rd",
"city": "Portland",
"state": "OR",
"postal_code": "97201",
"country": "US"
}
}
}
See Invoice Features for detailed examples of all features, and Calculation Logic for how discounts and taxes interact.