Skip to content

Create a draft invoice

The invoices.create operation: POST /api/v1/invoices in the REST API and the invoices_create tool in the MCP server.

POST/api/v1/invoices

Creates a draft invoice for a customer of the brand, outside any subscription: setup fees, consulting, enterprise contracts billed by bank transfer (spec §16.15). A draft has no number yet: edit it, add or remove items (invoice_items.create, invoice_items.delete), then finalize it (invoices.finalize: number, tax quoted at that moment, PDF) and send it (invoices.send).

  • Items: each an active one-time price (priceId), or a product with a unitAmount (productId), with a quantity. Amounts are integer micros in whole minor units; every item is in the invoice's currency. includePendingItems also bills the customer's pending invoice items in that currency.
  • Collection: send_invoice (default) emails the invoice with a due date, daysUntilDue after the issue date (default 14) or a fixed dueDate, and the entity's bank transfer details. charge_automatically charges the customer's default payment method.

Tax isn't computed on a draft: draft.subtotal is before tax.

Business customers without a valid VAT ID are taxed as consumers: only a valid tax ID makes the sale business-to-business. In the EU a consumer's country needs two pieces of location evidence that agree, so a customer created through the API with only its billing address (one evidence item) can't be invoiced: invoices.finalize refuses with evidence_conflict. Add its VAT ID first (customers.tax_ids.add; once the register confirms it, the billing address is enough), or finalize after the customer bought once through a hosted checkout, whose IP address and card country are stored as evidence.

At a glance

  • REST: POST /api/v1/invoices
  • MCP tool: invoices_create
  • Operation ID: invoices.create
  • Scope: Brand
  • Permission: invoices:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the invoices:write scope
  • Since: M5

Request

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
customerIdcus_… IDYesThe customer (cus_…).
collectionMethodone of charge_automatically, send_invoiceNosend_invoice: emailed with a due date and bank transfer details, paid by bank transfer (spec §16.9). charge_automatically: the customer's default payment method is charged.
daysUntilDueinteger (0 to 365)Nosend_invoice: days from the issue date to the due date, 0 to 365 (default 14).
dueDatestringNosend_invoice: a fixed due date instead of daysUntilDue.
currencystringNoThe invoice's currency. Required without items; with items it must be theirs.
itemsarray of objectNoThe invoice's items, 0 to 100 (add more later with invoice_items.create).
items[].priceIdprice_… IDNoAn active one-time price with a fixed amount: its product, amount, currency and tax behavior.
items[].productIdprod_… IDNoInstead of a price: the product (its tax category and revenue account), with unitAmount.
items[].unitAmountobjectNoWith productId: the price of one unit.
items[].unitAmount.amountstringYesInteger micros as a string (12500000 = 12.50), in whole minor units of the currency.
items[].unitAmount.currencystringYesISO 4217 currency code.
items[].taxBehaviorone of exclusive, inclusiveNoWith productId: whether unitAmount includes tax (default exclusive).
items[].quantityinteger (1 to 1000000)NoWhole units, 1 to 1000000 (default 1).
items[].descriptionstringNoThe line's text on the invoice (default: the product's name, and the price's nickname).
includePendingItemsbooleanNoAlso bill the customer's pending invoice items in this currency (not a subscription's).
metadataobjectNoYour own key-value pairs (at most 50 keys, values of at most 500 characters).

Response

201 Created with a JSON object:

FieldTypeDescription
idinv_… ID
object"invoice"
livemodeboolean
entityIdent_… ID
brandIdbrd_… ID
numberstring or nullThe invoice number: gap-free per legal entity, mode, brand series and year (§18.2). Null for a draft: the number is taken at finalization.
numberingobject or null
customerIdcus_… ID or null
subscriptionIdsub_… ID or null
collectionMethodone of charge_automatically, send_invoice
kindone of invoice, receipt or nullinvoice (business customers) or receipt (the receipt-invoice consumers get); null for a draft.
statusone of 9 values, e.g. draft, pending_registration, issued (all in the OpenAPI document)draft → open (finalized) → paid, void or uncollectible. Checkout invoices are issued (paid at once), or pending_registration: a full invoice charged before the tax registration exists; the receipt went out and the formal invoice follows (§18.1).
languageone of en, de, fr, hr, it, es or null
issuedAtdate-time or null
issueDatestring or nullThe issue date in the seller's time zone.
taxPointdate-time or null
taxPointDatestring or nullThe date of supply in the seller's time zone.
daysUntilDueinteger or nullsend_invoice: days from the issue date to the due date.
dueDatestring or nullsend_invoice: when payment is due (fixed at finalization).
sellerobject or null
buyerobject or null
currencystring
linesarray of object
lines[].idstringThe tax quote's line ID.
lines[].descriptionstring
lines[].productIdprod_… ID or null
lines[].priceIdprice_… ID or null
lines[].quantityinteger
lines[].taxCategoryIdone of 9 values, e.g. electronically_supplied_service, saas, ebook (all in the OpenAPI document)
lines[].taxBehaviorone of inclusive, exclusive
lines[].unitAmountmoneyThe net price of one unit (may be finer than the minor unit).
lines[].netmoney
lines[].taxobject
lines[].tax.ratePpmstringParts per million as a string (19% = "190000").
lines[].tax.amountmoney
lines[].tax.jurisdictionIdstring or null
lines[].tax.regimeIdstring or null
lines[].tax.decisionone of charge, reverse_charge, exempt, not_taxable, out_of_scope, not_collected, blockedWhat happened to the tax: charge, reverse_charge, exempt, not_taxable, out_of_scope, not_collected.
lines[].tax.rateKindone of standard, reduced, super_reduced, parking, zero, exempt, not_taxable or null
lines[].tax.rateIdstring or null
lines[].tax.pendingRegistrationboolean
lines[].grossmoney
lines[].kindone of licensed, metered, late_usage, proration, invoice_item or nullWhere the line came from (§16.3 order); null on checkout invoices.
lines[].periodobject or null
lines[].subscriptionItemIdstring or null
lines[].invoiceItemIdii_… ID or null
lines[].discountmoney or nullWhat discounts took off the line before tax.
lines[].meteredQuantitystring or nullA metered line's usage (its quantity is 1).
totalsobject or null
taxCurrencyTotalsobject or nullThe tax in the seller's tax currency when the invoice is in another one (§18.3).
creditAppliedmoney or nullTaken from the customer's credit balance at finalization (§16.11).
amountDuemoney or nullWhat the customer pays: the gross total less the credit applied. Null on checkout invoices.
notesarray of object
notes[].codeone of reverse_charge, exempt, out_of_scope, registration_pending, oss_scheme
notes[].textstringThe note as printed.
fieldCheckobject or nullWhat the knowledge base's invoicing rules ask for that the invoice lacks (missing), and requirements Ownrecord can't check yet (unchecked).
pendingRegistrationbooleanA full invoice with a line charged before the registration exists (§18.1).
paymentIdsarray of pay_… ID
creditNoteIdsarray of cn_… ID
ledgerTxnIdsarray of txn_… ID
quoteIdtq_… ID or nullThe tax quote the invoice shows (null for a draft).
quoteIdsarray of tq_… IDEvery quote of the invoice: lines taxed at another date (prorations) have their own quote.
pdfobject or nullNull for a draft: the PDF is rendered at finalization.
finalizedAtdate-time or null
paidAtdate-time or null
paymentobject or nullHow the invoice was paid: bank_transfer (marked paid), processor (a card or debit payment) or credit_balance.
voidedAtdate-time or null
markedUncollectibleAtdate-time or null
emailedAtdate-time or null
sentAtdate-time or nullWhen invoices.send last emailed the invoice.
draftobject or nullA draft's lines before tax (tax is quoted at finalization); null once finalized.
metadataobject
versionintegerPass it as expectedVersion to refuse a change if the invoice changed. Rendering the PDF and emailing the invoice change it too.
createdAtdate-time
updatedAtdate-time

Examples

Two consulting days for a business customer, sent for payment

HTTP
POST /api/v1/invoices
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "items": [
    {
      "productId": "prod_01m4tx5nj8emwbyf7y9vcf47yr",
      "unitAmount": {
        "amount": "600000000",
        "currency": "EUR"
      },
      "quantity": 2,
      "description": "Implementation workshop (days)"
    }
  ],
  "metadata": {
    "contract": "ENT-2026-07"
  }
}

Response (201):

JSON
{
  "id": "inv_01m4tx5nj8emwbyf7y9vcf47yk",
  "object": "invoice",
  "livemode": false,
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "number": null,
  "numbering": null,
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "subscriptionId": null,
  "collectionMethod": "send_invoice",
  "kind": null,
  "status": "draft",
  "language": null,
  "issuedAt": null,
  "issueDate": null,
  "taxPoint": null,
  "taxPointDate": null,
  "daysUntilDue": 14,
  "dueDate": null,
  "seller": null,
  "buyer": null,
  "currency": "EUR",
  "lines": [],
  "totals": null,
  "taxCurrencyTotals": null,
  "creditApplied": null,
  "amountDue": null,
  "notes": [],
  "fieldCheck": null,
  "pendingRegistration": false,
  "paymentIds": [],
  "creditNoteIds": [],
  "ledgerTxnIds": [],
  "quoteId": null,
  "quoteIds": [],
  "pdf": null,
  "finalizedAt": null,
  "paidAt": null,
  "payment": null,
  "voidedAt": null,
  "markedUncollectibleAt": null,
  "emailedAt": null,
  "sentAt": null,
  "draft": {
    "lines": [
      {
        "kind": "invoice_item",
        "description": "Implementation workshop (days)",
        "quantity": "2",
        "amount": {
          "amount": "1200000000",
          "currency": "EUR"
        },
        "discount": {
          "amount": "0",
          "currency": "EUR"
        },
        "subtotal": {
          "amount": "1200000000",
          "currency": "EUR"
        },
        "taxBehavior": "exclusive",
        "taxCategoryId": "consulting_remote",
        "productId": "prod_01m4tx5nj8emwbyf7y9vcf47yr",
        "priceId": null,
        "invoiceItemId": "ii_01m4tx5nj8emwbyf7y9vcf47ys",
        "period": null
      }
    ],
    "subtotal": {
      "amount": "1200000000",
      "currency": "EUR"
    }
  },
  "metadata": {
    "contract": "ENT-2026-07"
  },
  "version": 1,
  "createdAt": "2026-10-20T08:30:00.000Z",
  "updatedAt": "2026-10-20T08:30:00.000Z"
}

An empty draft, items added later

HTTP
POST /api/v1/invoices
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "currency": "EUR",
  "daysUntilDue": 30
}

Response (201):

JSON
{
  "id": "inv_01m4tx5nj8emwbyf7y9vcf47yk",
  "object": "invoice",
  "livemode": false,
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "number": null,
  "numbering": null,
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "subscriptionId": null,
  "collectionMethod": "send_invoice",
  "kind": null,
  "status": "draft",
  "language": null,
  "issuedAt": null,
  "issueDate": null,
  "taxPoint": null,
  "taxPointDate": null,
  "daysUntilDue": 30,
  "dueDate": null,
  "seller": null,
  "buyer": null,
  "currency": "EUR",
  "lines": [],
  "totals": null,
  "taxCurrencyTotals": null,
  "creditApplied": null,
  "amountDue": null,
  "notes": [],
  "fieldCheck": null,
  "pendingRegistration": false,
  "paymentIds": [],
  "creditNoteIds": [],
  "ledgerTxnIds": [],
  "quoteId": null,
  "quoteIds": [],
  "pdf": null,
  "finalizedAt": null,
  "paidAt": null,
  "payment": null,
  "voidedAt": null,
  "markedUncollectibleAt": null,
  "emailedAt": null,
  "sentAt": null,
  "draft": {
    "lines": [],
    "subtotal": {
      "amount": "0",
      "currency": "EUR"
    }
  },
  "metadata": {},
  "version": 1,
  "createdAt": "2026-10-20T08:30:00.000Z",
  "updatedAt": "2026-10-20T08:30:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is missing or malformed: both daysUntilDue and dueDate, no currency without items, an item with both or neither of priceId and productId, an archived product, amounts that aren't whole minor units.Fix the fields listed in details.issues and send the request again.
resource_not_found404The customer, a price or a product isn't this brand's in this mode (param names it).Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
customer_deleted400The customer was deleted.Create a new customer for this buyer. Deleted customers stay readable for the records they belong to, but can't be changed.
invoice_item_price_unusable400A price is archived, recurring, a credit pack or a custom amount (use a product with unitAmount).Use an active one-time price with a fixed amount, or give the product (productId) and a unitAmount instead. Recurring prices are billed by subscriptions and credit packs by checkout.
invoice_currency_mismatch400An item's currency isn't the invoice's.Every item of an invoice is in the invoice's currency (details.invoice_currency). Create a separate draft for the other currency.
idempotency_key_reused409The idempotency key was used before for another request.Use a new Idempotency-Key for a different request, or resend the original request unchanged.
scope_required400The request names no brand (an org or entity key without Ownrecord-Brand).Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (details.required_scope).
permission_denied403You can't change this brand's invoices (invoices:write: finance, owners and admins).Ask an organization owner or admin for a role or scope that allows this action.
livemode_not_allowed403You have no live-mode access, so you can't use live invoices.Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_required, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.