Source: https://billingmart.com/developers/api/payables # Bills and vendors The other side of the ledger: vendors, the bills they send, and what has been paid against them. [All sections](https://billingmart.com/developers/api) [Authentication](https://billingmart.com/developers/authentication) **On this page** - GET List - POST Create - GET Get - POST Pause - GET List - POST Create - GET Get - PATCH Update - GET Payments - GET List - POST Create - GET Get - PATCH Update - POST Archive - POST Set allocations - POST Discard - POST Submit approval - POST Approve - POST Reject - OBJ RecurringBill - OBJ Bill - OBJ Vendor On this page - GET List - POST Create - GET Get - POST Pause - GET List - POST Create - GET Get - PATCH Update - GET Payments - GET List - POST Create - GET Get - PATCH Update - POST Archive - POST Set allocations - POST Discard - POST Submit approval - POST Approve - POST Reject - OBJ RecurringBill - OBJ Bill - OBJ Vendor recurring bills ## List GET `/v1/recurring-bills` List recurring-bill schedules. Scope `bills:read` Effect Read only MCP tool `list_recurring_bills` 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 | | `vendorId`optional | query | `id` | — | | `active`optional | query | `boolean` | — | ### Returns `data`: [`RecurringBill[]`](https://billingmart.com/developers/api/payables#object-RecurringBill) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/recurring-bills" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` recurring bills ## Create POST `/v1/recurring-bills` Create a schedule that drafts a bill for a vendor on a frequency. Each occurrence is a DRAFT bill that a person opens; nothing is paid or approved. Totals are derived from the lines. A start date in the past answers 409 MISSED_OCCURRENCES with the count until missed is skip or issue. Scope `bills:write` Effect Writes a draft or record MCP tool `create_recurring_bill` 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 | | --- | --- | --- | | `vendorId`required | `id` | — | | `title`optional | `string` | up to 200 chars | | `frequency`required | `enum` | One of `weekly`, `biweekly`, `monthly`, `quarterly`, `semiannually`, `annually` | | `startDate`required | `string` | matches `^\d{4}-\d{2}-\d{2}$` | | `endDate`optional | `string` | matches `^\d{4}-\d{2}-\d{2}$` | | `occurrenceLimit`optional | `integer` | min 1 · max 600 | | `netDays`optional | `integer` | min 0 · max 365 | | `category`optional | `string` | up to 80 chars | | `notes`optional | `string` | up to 4000 chars | | `currency`optional | `Currency` | — | | `lineItems[]`required | `object[]` | up to 200 items · at least 1 | | `lineItems[].id`optional | `id` | — | | `lineItems[].description`optional | `string` | What the line is for. Optional with a presetKey (the item’s name is used). — up to 2000 chars | | `lineItems[].quantityMilli`optional | `integer` | Quantity in thousandths: 1000 is one unit, 1500 is 1.5 hours. Defaults to 1000. | | `lineItems[].rateBasis`optional | `enum` | How the price applies: fixed for one flat charge, hourly, daily, perUnit, percentage… Optional with a presetKey. — One of `fixed`, `hourly`, `daily`, `weekly`, `monthly`, `perUnit`, `perMile`, `perKilometre`, `percentage` | | `lineItems[].unitPrice`optional | `object` | Price per unit in integer minor units of the document currency ($5,000.00 is 500000). | | `lineItems[].unitPrice.minorUnits`required | `integer` | — | | `lineItems[].unitPrice.currency`required | `Currency` | — | | `lineItems[].rateBasisPoints`optional | `integer` | — | | `lineItems[].taxTreatment`optional | `string` | — | | `lineItems[].taxRateBasisPoints`optional | `integer` | — | | `lineItems[].discountBasisPoints`optional | `integer` | — | | `lineItems[].presetKey`optional | `string` | The key of one of the business’s products and services (get_business_context lists them); the server fills what the line leaves out. — up to 64 chars | | `missed`optional | `enum` | One of `skip`, `issue` | | `businessId`optional | `id` | — | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `NOT_FOUND` , `VALIDATION_FAILED` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/recurring-bills" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"vendorId":"","frequency":"weekly","startDate":""}' ``` recurring bills ## Get GET `/v1/recurring-bills/{recurringBillId}` One recurring-bill schedule. Scope `bills:read` Effect Read only MCP tool `get_recurring_bill` Retries Safe to repeat ### Parameters Get parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `recurringBillId`required | path | `id` | — | ### Returns `data`: [`RecurringBill`](https://billingmart.com/developers/api/payables#object-RecurringBill) Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/recurring-bills/{recurringBillId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` recurring bills ## Pause POST `/v1/recurring-bills/{recurringBillId}/pause` Pause a recurring-bill schedule: no further bill is drafted until a person resumes it in the console. Scope `bills:write` Effect Writes a draft or record MCP tool `pause_recurring_bill` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Pause parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `recurringBillId`required | path | `id` | — | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `NOT_FOUND` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/recurring-bills/{recurringBillId}/pause" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` bills ## List GET `/v1/bills` List bills, newest first. A discarded draft is left out unless discarded=true. Scope `bills:read` Effect Read only MCP tool `list_bills` 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 | | `status`optional | query | `enum` | One of `draft`, `open`, `partiallyPaid`, `paid`, `overdue`, `void` | | `vendorId`optional | query | `id` | — | | `jobId`optional | query | `id` | — | | `discarded`optional | query | `boolean` | — | ### Returns `data`: [`Bill[]`](https://billingmart.com/developers/api/payables#object-Bill) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/bills" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` bills ## Create POST `/v1/bills` Create a bill as a DRAFT. Totals are derived server-side from the lines, never taken from input. Scope `bills:write` Effect Writes a draft or record MCP tool `create_bill` 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 | | --- | --- | --- | | `vendorName`required | `string` | up to 200 chars | | `currency`required | `Currency` | — | | `vendorId`optional | `id` | — | | `vendorEmail`optional | `string` | up to 320 chars | | `reference`optional | `string` | up to 64 chars | | `issueDate`optional | `string` | matches `^\d{4}-\d{2}-\d{2}$` | | `dueDate`optional | `string` | matches `^\d{4}-\d{2}-\d{2}$` | | `category`optional | `string` | up to 80 chars | | `notes`optional | `string` | up to 4000 chars | | `lineItems[]`optional | `object[]` | up to 200 items | | `lineItems[].id`optional | `id` | — | | `lineItems[].description`optional | `string` | What the line is for. Optional with a presetKey (the item’s name is used). — up to 2000 chars | | `lineItems[].quantityMilli`optional | `integer` | Quantity in thousandths: 1000 is one unit, 1500 is 1.5 hours. Defaults to 1000. | | `lineItems[].rateBasis`optional | `enum` | How the price applies: fixed for one flat charge, hourly, daily, perUnit, percentage… Optional with a presetKey. — One of `fixed`, `hourly`, `daily`, `weekly`, `monthly`, `perUnit`, `perMile`, `perKilometre`, `percentage` | | `lineItems[].unitPrice`optional | `object` | Price per unit in integer minor units of the document currency ($5,000.00 is 500000). | | `lineItems[].unitPrice.minorUnits`required | `integer` | — | | `lineItems[].unitPrice.currency`required | `Currency` | — | | `lineItems[].rateBasisPoints`optional | `integer` | — | | `lineItems[].taxTreatment`optional | `string` | — | | `lineItems[].taxRateBasisPoints`optional | `integer` | — | | `lineItems[].discountBasisPoints`optional | `integer` | — | | `lineItems[].presetKey`optional | `string` | The key of one of the business’s products and services (get_business_context lists them); the server fills what the line leaves out. — up to 64 chars | | `businessId`optional | `id` | — | | `jobAllocations[]`optional | `object[]` | up to 10 items | | `jobAllocations[].jobId`required | `id` | — | | `jobAllocations[].amount`required | `object` | — | | `jobAllocations[].amount.minorUnits`required | `integer` | — | | `jobAllocations[].amount.currency`required | `Currency` | — | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/bills" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"vendorName":"","currency":"USD"}' ``` bills ## Get GET `/v1/bills/{billId}` One bill with its lines and what is still due. Scope `bills:read` Effect Read only MCP tool `get_bill` Retries Safe to repeat ### Parameters Get parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Returns `data`: [`Bill`](https://billingmart.com/developers/api/payables#object-Bill) Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/bills/{billId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` bills ## Update PATCH `/v1/bills/{billId}` Update a bill. A DRAFT takes vendor, dates, reference, category, notes and lines (totals re-derived); an opened bill takes notes and category only; a void bill nothing. Scope `bills:write` Effect Writes a draft or record MCP tool `update_bill` Retries No Idempotency-Key on this route ### Parameters Update parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`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 | | --- | --- | --- | | `expectedUpdatedAt`optional | `string` | up to 40 chars | | `vendorId`optional | `id` | — | | `vendorName`optional | `string` | up to 200 chars | | `vendorEmail`optional | `string` | up to 320 chars | | `reference`optional | `string` | up to 64 chars | | `issueDate`optional | `string` | matches `^\d{4}-\d{2}-\d{2}$` | | `dueDate`optional | `string` | matches `^\d{4}-\d{2}-\d{2}$` | | `category`optional | `string` | up to 80 chars | | `notes`optional | `string` | up to 4000 chars | | `lineItems[]`optional | `object[]` | up to 200 items | | `lineItems[].id`optional | `id` | — | | `lineItems[].description`optional | `string` | What the line is for. Optional with a presetKey (the item’s name is used). — up to 2000 chars | | `lineItems[].quantityMilli`optional | `integer` | Quantity in thousandths: 1000 is one unit, 1500 is 1.5 hours. Defaults to 1000. | | `lineItems[].rateBasis`optional | `enum` | How the price applies: fixed for one flat charge, hourly, daily, perUnit, percentage… Optional with a presetKey. — One of `fixed`, `hourly`, `daily`, `weekly`, `monthly`, `perUnit`, `perMile`, `perKilometre`, `percentage` | | `lineItems[].unitPrice`optional | `object` | Price per unit in integer minor units of the document currency ($5,000.00 is 500000). | | `lineItems[].unitPrice.minorUnits`required | `integer` | — | | `lineItems[].unitPrice.currency`required | `Currency` | — | | `lineItems[].rateBasisPoints`optional | `integer` | — | | `lineItems[].taxTreatment`optional | `string` | — | | `lineItems[].taxRateBasisPoints`optional | `integer` | — | | `lineItems[].discountBasisPoints`optional | `integer` | — | | `lineItems[].presetKey`optional | `string` | The key of one of the business’s products and services (get_business_context lists them); the server fills what the line leaves out. — up to 64 chars | ### Returns `data`: [`Bill`](https://billingmart.com/developers/api/payables#object-Bill) Errors this route can answer besides the shared ones: `INVALID_TRANSITION` , `ACTION_PENDING_ON_TARGET` . Example request Sample ``` curl -X PATCH "https://api.billingmart.com/v1/bills/{billId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` bills ## Payments GET `/v1/bills/{billId}/payments` The payments recorded against one bill, as ledger entries (entryId is what void_bill_payment takes), oldest first. Scope `bills:read` Effect Read only MCP tool `list_bill_payments` Retries Safe to repeat ### Parameters Payments parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Returns `data`: [`LedgerEntry[]`](https://billingmart.com/developers/api/invoices#object-LedgerEntry) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/bills/{billId}/payments" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` vendors ## List GET `/v1/vendors` List vendors, newest first (contact details masked unless contacts:read). Scope `bills:read` Effect Read only MCP tool `list_vendors` 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 | | `archived`optional | query | `boolean` | — | ### Returns `data`: [`Vendor[]`](https://billingmart.com/developers/api/payables#object-Vendor) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/vendors" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` vendors ## Create POST `/v1/vendors` Create a vendor. Contact details are stored as given; nothing is verified or contacted. Scope `bills:write` Effect Writes a draft or record MCP tool `create_vendor` 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 | | --- | --- | --- | | `name`required | `string` | up to 200 chars | | `contactName`optional | `string` | up to 200 chars | | `email`optional | `string` | up to 320 chars | | `phone`optional | `string` | up to 32 chars | | `taxId`optional | `string` | up to 64 chars | | `defaultCategory`optional | `string` | up to 80 chars | | `defaultCurrency`optional | `Currency` | — | | `paymentTermsDays`optional | `integer` | min 0 · max 365 | | `notes`optional | `string` | up to 4000 chars | | `businessId`optional | `id` | — | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/vendors" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"name":""}' ``` vendors ## Get GET `/v1/vendors/{vendorId}` One vendor. Scope `bills:read` Effect Read only MCP tool `get_vendor` Retries Safe to repeat ### Parameters Get parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `vendorId`required | path | `id` | — | ### Returns `data`: [`Vendor`](https://billingmart.com/developers/api/payables#object-Vendor) Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/vendors/{vendorId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` vendors ## Update PATCH `/v1/vendors/{vendorId}` Update a vendor’s editable fields. Scope `bills:write` Effect Writes a draft or record MCP tool `update_vendor` Retries No Idempotency-Key on this route ### Parameters Update parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `vendorId`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 200 chars | | `contactName`optional | `string` | up to 200 chars | | `email`optional | `string` | up to 320 chars | | `phone`optional | `string` | up to 32 chars | | `taxId`optional | `string` | up to 64 chars | | `defaultCategory`optional | `string` | up to 80 chars | | `defaultCurrency`optional | `Currency` | — | | `paymentTermsDays`optional | `integer` | min 0 · max 365 | | `notes`optional | `string` | up to 4000 chars | ### Returns `data`: [`Vendor`](https://billingmart.com/developers/api/payables#object-Vendor) Example request Sample ``` curl -X PATCH "https://api.billingmart.com/v1/vendors/{vendorId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` vendors ## Archive POST `/v1/vendors/{vendorId}/archive` Archive or restore a vendor. Never deleted: bills point at it. Scope `bills:write` Effect Writes a draft or record MCP tool `archive_vendor` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Archive parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `vendorId`required | path | `id` | — | ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Archive request body | Field | Type | Notes | | --- | --- | --- | | `archived`optional | `boolean` | — | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/vendors/{vendorId}/archive" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` bills ## Set allocations POST `/v1/bills/{billId}/allocations` Charge a DRAFT bill to work records: the list replaces the one stored, and expectedUpdatedAt (the bill updatedAt you read) is required. Each amount is in the bill currency; together they never exceed the bill total, and what is left stays unallocated. Scope `bills:write` Effect Writes a draft or record MCP tool `allocate_bill_to_jobs` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Set allocations parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Set allocations request body | Field | Type | Notes | | --- | --- | --- | | `expectedUpdatedAt`required | `string` | up to 40 chars | | `allocations[]`required | `object[]` | up to 10 items | | `allocations[].jobId`required | `id` | — | | `allocations[].amount`required | `object` | — | | `allocations[].amount.minorUnits`required | `integer` | — | | `allocations[].amount.currency`required | `Currency` | — | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `INVALID_TRANSITION` , `ALLOCATION_EXCEEDS_TOTAL` , `CURRENCY_MISMATCH` , `JOB_CLOSED` , `NOT_FOUND` , `EDIT_CONFLICT` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/bills/{billId}/allocations" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"expectedUpdatedAt":""}' ``` bills ## Discard POST `/v1/bills/{billId}/discard` Discard a DRAFT bill. Refused once opened, or while an action on it is pending. Scope `bills:write` Effect Writes a draft or record MCP tool `discard_draft_bill` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Discard parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `INVALID_TRANSITION` , `ACTION_PENDING_ON_TARGET` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/bills/{billId}/discard" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` bills ## Submit approval POST `/v1/bills/{billId}/submit-approval` Submit a DRAFT bill for approval. If the workspace policy covers its total, an approver must approve it before it can be opened; otherwise it answers that none is needed. Scope `bills:write` Effect Writes a draft or record MCP tool `submit_bill_for_approval` Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Submit approval parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `NOT_FOUND` , `INVALID_TRANSITION` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/bills/{billId}/submit-approval" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` bills ## Approve POST `/v1/bills/{billId}/approve` Approve a bill that is waiting for approval, as the person whose API key this is. The person who entered the bill cannot (unless nobody else could); the last required approval opens the bill. Scope `bills:approve` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Approve parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `NOT_FOUND` , `INVALID_TRANSITION` , `PERMISSION_DENIED` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/bills/{billId}/approve" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` bills ## Reject POST `/v1/bills/{billId}/reject` Reject a bill that is waiting for approval, with a reason. It goes back to a draft the submitter can edit and submit again. Scope `bills:approve` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Reject parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `billId`required | path | `id` | — | ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Reject request body | Field | Type | Notes | | --- | --- | --- | | `reason`required | `string` | up to 500 chars | ### Returns `data`: `object` Errors this route can answer besides the shared ones: `NOT_FOUND` , `INVALID_TRANSITION` , `PERMISSION_DENIED` . Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/bills/{billId}/reject" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"reason":""}' ``` Object ## RecurringBill A schedule that drafts bills: rent, software, insurance. Each occurrence is a DRAFT bill the hourly runner makes under a deterministic id; nothing is paid and nothing is approved by the schedule. With `openAutomatically` the runner also opens the draft through the bill-opening rules. RecurringBill fields | Field | Type | Notes | | --- | --- | --- | | `id`required | `Id` | — | | `tenant`required | `TenantRef` | — | | `vendorId`required | `Id` | The vendor each bill is made for. The vendor's name and email are read from the vendor record when the bill is drafted, never copied here, so renaming a vendor renames the next bill. | | `title`optional | `string` | Untrusted text — | | `frequency`required | `RecurringFrequency` | — | | `anchorDay`optional | `integer` | Day of the period to draft on; a 31 in a 30-day month clamps to the last day. The same rule as a recurring invoice, by the same shared code. | | `startDate`required | `DateOnly` | — | | `endDate`optional | `DateOnly` | — | | `occurrenceLimit`optional | `integer` | Counts DRAFTED occurrences; skipped ones do not use it up. | | `skippedOccurrences`optional | `integer` | SERVER-WRITTEN. Occurrences passed over on purpose when a resume or a timing edit would have drafted bills for dates before today and the caller chose `missed: skip`. | | `occurrencesIssued`optional | `integer` | SERVER-WRITTEN. How many bills this schedule has drafted. | | `nextRunAt`optional | `IsoTimestamp` | SERVER-WRITTEN. Resolved from anchorDay in the tenant's timezone. | | `lastRunAt`optional | `IsoTimestamp` | — | | `blockedAt`optional | `IsoTimestamp` | SERVER-WRITTEN. When the runner parked this schedule because it could not draft (the vendor is archived or gone, or the draft is not valid). Cleared when a later run succeeds or the schedule is edited. | | `blockedCode`optional | `string` | SERVER-WRITTEN. The error code the runner stopped on. A code, never tenant text. | | `currency`required | `Currency` | — | | `lineItems`required | `LineItem[]` | — | | `category`optional | `string` | Untrusted text Carried onto each bill. | | `notes`optional | `string` | Untrusted text Carried onto each bill. | | `netDays`optional | `integer` | Due date = the bill date + netDays. Absent: the bill is drafted with no due date, and a person sets one before opening it. | | `openAutomatically`optional | `boolean` | Off when absent. When true the runner opens each drafted bill through the same rules as opening one by hand. Set only by a signed-in owner or admin: never by an API key or an agent. | | `active`required | `boolean` | — | | `createdAt`required | `IsoTimestamp` | — | | `updatedAt`optional | `IsoTimestamp` | — | | `createdBy`optional | `Id` | — | | `lastWriteActor`optional | `WriteActor` | Who last wrote this record, and when, stamped by the server core. An EDIT_CONFLICT names it. | Object ## Bill A payable: money the tenant owes a vendor. Deliberately NOT an invoice with the sign flipped — a bill has no public link, no metering, no gateway path, and its lines are not rebillable without an explicit expense record. Bill fields | Field | Type | Notes | | --- | --- | --- | | `id`required | `Id` | — | | `tenant`required | `TenantRef` | — | | `vendorId`optional | `Id` | The vendor record the snapshot below was copied from. Optional: a one-off bill may name a vendor with no record. | | `vendorName`required | `string` | Untrusted text — | | `vendorEmail`optional | `Email` | — | | `reference`optional | `string` | Untrusted text The vendor's own invoice number. | | `status`required | `BillStatus` | — | | `currency`required | `Currency` | — | | `issueDate`optional | `DateOnly` | — | | `dueDate`optional | `DateOnly` | — | | `lineItems`optional | `LineItem[]` | — | | `total`required | `Money` | — | | `amountPaid`optional | `Money` | SERVER-WRITTEN. | | `amountDue`optional | `Money` | SERVER-DERIVED. | | `category`optional | `string` | Untrusted text — | | `taxCategory`optional | `TaxCategoryCode` | The tax category a person confirmed (a code of the taxonomy). Never set by a suggestion alone. | | `taxCategoryVersion`optional | `string` | The taxonomy edition `taxCategory` is a code of, e.g. `us-sch-c-2026`. | | `taxCategorySource`optional | `TaxCategorySource` | — | | `taxScheduleCode`optional | `TaxCategoryCode` | The TOP category `taxCategory` resolved to when it was confirmed (itself for a top category; a sub-category's parent), so a later rename or move never rewrites a past report. | | `taxScheduleLine`optional | `string` | The form line of `taxScheduleCode` at confirmation, e.g. `Line 8`; absent where the category is not a line of the form. | | `attachmentStoragePath`optional | `string` | — | | `notes`optional | `string` | Untrusted text — | | `paidAt`optional | `IsoTimestamp` | — | | `createdAt`required | `IsoTimestamp` | — | | `updatedAt`optional | `IsoTimestamp` | — | | `discardedAt`optional | `IsoTimestamp` | . Set by a function when a never-numbered draft is discarded: it leaves every default list and cannot be sent or opened. Soft, never a status value (a money-enum addition is a breaking change). | | `discardedBy`optional | `Id` | . The uid or credential that discarded it. | | `createdBy`optional | `Id` | — | | `approval`optional | `BillApproval` | The approval record, beside the status: written only by the approval functions, absent while the workspace has no approval policy or the bill never needed one. | | `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. | | `jobAllocations`optional | `JobAllocation[]` | The work records this bill is charged to. | | `jobIds`optional | `Id[]` | FUNCTION-WRITTEN: the record ids named in `jobAllocations`, so a record can find its bills with one equality query. At most 50 ids. | | `meteredAt`optional | `IsoTimestamp` | When this bill was counted as a send because it is allocated to a work record. Counted once, never refused. FUNCTION-WRITTEN. | | `meteredPeriod`optional | `string` | The tenant-local month ( `YYYY-MM`) in which it was counted. FUNCTION-WRITTEN. | Object ## Vendor Someone the tenant pays. Staff data written through the rules, never an identity: no contact key, no identity link, no verification. A bill copies the vendor's name and email into its own snapshot, so editing a vendor never rewrites a bill. Archived, never deleted. Vendor fields | Field | Type | Notes | | --- | --- | --- | | `id`required | `Id` | — | | `tenant`required | `TenantRef` | — | | `name`required | `string` | Untrusted text The vendor's trading name; every API and MCP response wraps it in the data envelope. | | `contactName`optional | `string` | Untrusted text — | | `email`optional | `Email` | — | | `phone`optional | `PhoneE164` | — | | `address`optional | `Address` | — | | `taxId`optional | `string` | The vendor's tax registration id. Sensitive business data: never logged, and an audit event records only that it changed. | | `defaultCategory`optional | `string` | Untrusted text Pre-fills a bill's category. | | `defaultTaxCategory`optional | `TaxCategoryCode` | The tax category a new record of this payee starts from: it is suggested first, free of AI credits, and a person still confirms. | | `defaultCurrency`optional | `Currency` | — | | `paymentTermsDays`optional | `integer` | Net days. The console pre-fills a bill's due date as issue date + terms; the server never infers a due date from it. | | `notes`optional | `string` | Untrusted text — | | `archived`optional | `boolean` | Absent on a fresh record: active is `archived !== true`. | | `createdAt`required | `IsoTimestamp` | — | | `updatedAt`optional | `IsoTimestamp` | — | | `createdBy`optional | `Id` | The creating user's uid. The rules refuse any other value on create and any change after. | | `updatedBy`optional | `Id` | Who made the last change. On a console write the rules require the signed-in uid, so the audit trigger takes the actor from a stamp the rules verified; on a REST write, the credential id. | | `updatedVia`optional | `enum` | Which door made the last change. `console` is audited by the vendor trigger; `rest` writes its own audit row. | Next section ## Reports and exports Ageing, income, tax, settlement and reconciliation, computed from stored amounts, plus the accounting export. [Continue to Reports and exports →](https://billingmart.com/developers/api/reports) ## 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/payables. Live plans, prices and limits are published as JSON at https://billingmart.com/plans.json and https://billingmart.com/agent-info.json.