Source: https://billingmart.com/developers/api/templates # Templates and pay themes How an invoice and its pay page look. Drafts only; publishing is an approved action. [All sections](https://billingmart.com/developers/api) [Authentication](https://billingmart.com/developers/authentication) **On this page** - GET List - POST Create - GET Get - PATCH Update - GET Preview - POST Generate - POST Generate - GET List - POST Create - GET Get - PATCH Update - OBJ Template - OBJ PayPageTheme On this page - GET List - POST Create - GET Get - PATCH Update - GET Preview - POST Generate - POST Generate - GET List - POST Create - GET Get - PATCH Update - OBJ Template - OBJ PayPageTheme templates ## List GET `/v1/templates` Invoice templates, drafts and published, newest first. Scope `templates:read` Effect Read only MCP tool `list_templates` Retries Safe to repeat ### Parameters List parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `limit`optional | query | `integer` | min 1 · max 50 | | `cursor`optional | query | `string` | up to 256 chars | | `state`optional | query | `enum` | One of `draft`, `published` | ### Returns `data`: [`Template[]`](https://billingmart.com/developers/api/templates#object-Template) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/templates" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` templates ## Create POST `/v1/templates` Create a DRAFT invoice template. Server-side the same block validation the console runs; `state` is forced to draft and publication fields are refused. Scope `templates:write` Effect Writes a draft or record MCP tool `create_template_draft` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Create request body | Field | Type | Notes | | --- | --- | --- | | `businessId`required | `id` | — | | `name`required | `string` | up to 120 chars | | `pageSize`optional | `enum` | One of `a4`, `letter` | | `accentTokenName`optional | `string` | up to 64 chars | | `blocks[]`required | `object[]` | up to 30 items · at least 1 | | `blocks[].kind`required | `string` | up to 40 chars | | `blocks[].text`optional | `string` | up to 500 chars | | `blocks[].align`optional | `enum` | One of `start`, `center`, `end` | | `blocks[].visible`optional | `boolean` | — | | `blocks[].spacingSteps`optional | `integer` | min 0 · max 12 | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/templates" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"businessId":"","name":""}' ``` templates ## Get GET `/v1/templates/{templateId}` One invoice template with its blocks. Scope `templates:read` Effect Read only MCP tool `get_template` Retries Safe to repeat ### Parameters Get parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `templateId`required | path | `id` | — | ### Returns `data`: [`Template`](https://billingmart.com/developers/api/templates#object-Template) Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/templates/{templateId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` templates ## Update PATCH `/v1/templates/{templateId}` Edit a DRAFT invoice template. A published template is immutable and is refused. Scope `templates:write` Effect Writes a draft or record MCP tool `update_template_draft` Retries No Idempotency-Key on this route ### Parameters Update parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `templateId`required | path | `id` | — | ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Update request body | Field | Type | Notes | | --- | --- | --- | | `name`optional | `string` | up to 120 chars | | `pageSize`optional | `enum` | One of `a4`, `letter` | | `accentTokenName`optional | `string` | up to 64 chars | | `blocks[]`optional | `object[]` | up to 30 items · at least 1 | | `blocks[].kind`required | `string` | up to 40 chars | | `blocks[].text`optional | `string` | up to 500 chars | | `blocks[].align`optional | `enum` | One of `start`, `center`, `end` | | `blocks[].visible`optional | `boolean` | — | | `blocks[].spacingSteps`optional | `integer` | min 0 · max 12 | ### Returns `data`: [`Template`](https://billingmart.com/developers/api/templates#object-Template) Example request Sample ``` curl -X PATCH "https://api.billingmart.com/v1/templates/{templateId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` templates ## Preview GET `/v1/templates/{templateId}/preview` Render an invoice template — draft or published — over a sample invoice and return a short-lived signed URL. Nothing is sent and no real invoice is used. Scope `templates:read` Effect Read only MCP tool `preview_template_pdf` Retries Safe to repeat ### Parameters Preview parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `templateId`required | path | `id` | — | ### Returns `data`: [`PdfPreview`](https://billingmart.com/developers/api/invoices#object-PdfPreview) Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/templates/{templateId}/preview" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` templates ## Generate POST `/v1/templates/generate` Design a DRAFT invoice template from a description. It is a draft: no invoice or PDF uses it until a person approves publishing it. Scope `templates:write` Effect Writes a draft or record MCP tool `generate_template_draft` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Generate request body | Field | Type | Notes | | --- | --- | --- | | `businessId`required | `id` | — | | `description`required | `string` | at least 10 chars · up to 2000 chars | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `AI_DISABLED` , `AI_CAP_REACHED` , `AI_CREDITS_EXHAUSTED` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/templates/generate" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"businessId":"","description":""}' ``` pay themes ## Generate POST `/v1/pay-themes/generate` Design a DRAFT pay-page theme from a description. It renders nowhere until a person approves publishing it. Scope `templates:write` Effect Writes a draft or record MCP tool `generate_pay_theme_draft` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Generate request body | Field | Type | Notes | | --- | --- | --- | | `businessId`required | `id` | — | | `description`required | `string` | at least 10 chars · up to 2000 chars | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `AI_DISABLED` , `AI_CAP_REACHED` , `AI_CREDITS_EXHAUSTED` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/pay-themes/generate" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"businessId":"","description":""}' ``` pay themes ## List GET `/v1/pay-themes` Pay-page themes, drafts and published, newest first. Scope `templates:read` Effect Read only MCP tool `list_pay_themes` Retries Safe to repeat ### Parameters List parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `limit`optional | query | `integer` | min 1 · max 50 | | `cursor`optional | query | `string` | up to 256 chars | | `state`optional | query | `enum` | One of `draft`, `published` | ### Returns `data`: [`PayPageTheme[]`](https://billingmart.com/developers/api/templates#object-PayPageTheme) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/pay-themes" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` pay themes ## Create POST `/v1/pay-themes` Create a DRAFT pay-page theme. The three seam tokens must be present and pass the contrast check in both themes; `logoUrl` must be inside this tenant’s own Storage prefix. Scope `templates:write` Effect Writes a draft or record MCP tool `create_pay_theme_draft` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Create request body | Field | Type | Notes | | --- | --- | --- | | `businessId`required | `id` | — | | `name`required | `string` | up to 120 chars | | `headline`required | `string` | up to 120 chars · matches `^[^<]*$` | | `subheadline`optional | `string` | up to 200 chars · matches `^[^<]*$` | | `layout`required | `enum` | One of `single`, `split` | | `showLineItems`required | `boolean` | — | | `logoUrl`optional | `string` | up to 512 chars | | `tokenOverrides`required | `object` | — | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/pay-themes" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"businessId":"","name":"","headline":"","layout":"single","showLineItems":false,"tokenOverrides":{}}' ``` pay themes ## Get GET `/v1/pay-themes/{themeId}` One pay-page theme. Scope `templates:read` Effect Read only MCP tool `get_pay_theme` Retries Safe to repeat ### Parameters Get parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `themeId`required | path | `id` | — | ### Returns `data`: [`PayPageTheme`](https://billingmart.com/developers/api/templates#object-PayPageTheme) Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/pay-themes/{themeId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` pay themes ## Update PATCH `/v1/pay-themes/{themeId}` Edit a DRAFT pay-page theme. A published theme is immutable and is refused. Scope `templates:write` Effect Writes a draft or record MCP tool `update_pay_theme_draft` Retries No Idempotency-Key on this route ### Parameters Update parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `themeId`required | path | `id` | — | ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Update request body | Field | Type | Notes | | --- | --- | --- | | `name`optional | `string` | up to 120 chars | | `headline`optional | `string` | up to 120 chars · matches `^[^<]*$` | | `subheadline`optional | `string` | up to 200 chars · matches `^[^<]*$` | | `layout`optional | `enum` | One of `single`, `split` | | `showLineItems`optional | `boolean` | — | | `logoUrl`optional | `string` | up to 512 chars | | `tokenOverrides`optional | `object` | — | ### Returns `data`: [`PayPageTheme`](https://billingmart.com/developers/api/templates#object-PayPageTheme) Example request Sample ``` curl -X PATCH "https://api.billingmart.com/v1/pay-themes/{themeId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` Object ## Template An InvoiceTemplate document — a STRUCTURED DOCUMENT, never markup. The AI emits schema-validated JSON and never HTML, CSS or script; out-of-schema fields are discarded, not stored. A generated template is a DRAFT until a human publishes it. The renderer is a real pdf-lib renderer, so what is previewed is what is sent. Template fields | Field | Type | Notes | | --- | --- | --- | | `id`required | `Id` | — | | `tenant`required | `TenantRef` | — | | `name`required | `string` | Untrusted text — | | `state`required | `PublishState` | — | | `origin`optional | `enum` | `ai` is what makes the draft-until-published rule non-negotiable. `api` is a draft written through REST or MCP: still a draft until a person publishes it. | | `blocks`required | `TemplateBlock[]` | Ordered layout blocks. A closed vocabulary is the point: an open one is markup with extra steps. | | `pageSize`optional | `enum` | — | | `accentTokenName`optional | `string` | A semantic token name from brand/tokens, not a hue. A consumer that references blue-500 cannot be re-themed. | | `rationale`optional | `string` | Untrusted text The Designer's one or two sentences on why this layout fits. Shown to the person editing, never rendered on the invoice. | | `aiRaw`optional | `string` | The model's raw answer, verbatim and digit-masked, kept beside the human-edited copy so "what did it actually propose" survives the edit. Written by the generator, never by a client. | | `createdBy`optional | `Id` | — | | `publishedAt`optional | `IsoTimestamp` | — | | `publishedBy`optional | `Id` | The human who published. Absent while draft — an AI cannot fill this in. | | `createdAt`required | `IsoTimestamp` | — | | `updatedAt`optional | `IsoTimestamp` | — | | `lastWriteActor`optional | `WriteActor` | Who last wrote this record, and when — stamped by the server core. An EDIT_CONFLICT names it, so the person refused knows who saved the newer version. | Object ## PayPageTheme PayPageTheme is computed by the server for this request, not a stored document, so no contract describes it. Its fields are the TypeScript type of the same name that the handler returns. Next section ## Messages and activity The delivery log of every email and text, the audit trail of who did what, and your own notifications and their settings. [Continue to Messages and activity →](https://billingmart.com/developers/api/messages) ## Try it against your sandbox Create a bmk_test_ key in the console. It can only reach your sandbox workspace. [Start free](https://app.billingmart.com/sign-up) [All sections](https://billingmart.com/developers/api) --- This is the Markdown copy of https://billingmart.com/developers/api/templates. Live plans, prices and limits are published as JSON at https://billingmart.com/plans.json and https://billingmart.com/agent-info.json.