Skip to content

Create an invoice item

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

POST/api/v1/invoice_items

Adds a line to a draft invoice (invoiceId), or creates a pending item that waits for the customer's next invoice: the next subscription invoice, or a draft created with includePendingItems.

The item is an active one-time price (priceId: its product, amount, currency and tax behavior), or a product with a unitAmount (productId, taxBehavior default exclusive), times a quantity. Amounts are integer micros in whole minor units. An item on a draft is in the draft's currency and for its customer. Tax is quoted when the invoice is finalized.

At a glance

  • REST: POST /api/v1/invoice_items
  • MCP tool: invoice_items_create
  • Operation ID: invoice_items.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_…).
invoiceIdinv_… IDNoA draft of the same customer and currency; without it the item is pending.
priceIdprice_… IDNoAn active one-time price with a fixed amount: its product, amount, currency and tax behavior.
productIdprod_… IDNoInstead of a price: the product (its tax category and revenue account), with unitAmount.
unitAmountobjectNoWith productId: the price of one unit.
unitAmount.amountstringYesInteger micros as a string (12500000 = 12.50), in whole minor units of the currency.
unitAmount.currencystringYesISO 4217 currency code.
taxBehaviorone of exclusive, inclusiveNoWith productId: whether unitAmount includes tax (default exclusive).
quantityinteger (1 to 1000000)NoWhole units, 1 to 1000000 (default 1).
descriptionstringNoThe line's text on the invoice (default: the product's name, and the price's nickname).
periodobjectNoThe service period the item covers (shown on the invoice).
period.startdate-timeYes
period.enddate-timeYes
metadataobjectNoYour own key-value pairs (at most 50 keys, values of at most 500 characters).

Response

201 Created with a JSON object:

FieldTypeDescription
idii_… ID
object"invoice_item"
livemodeboolean
customerIdcus_… ID
subscriptionIdsub_… ID or null
invoiceIdinv_… ID or nullThe invoice the item is on; null while it waits for the customer's next invoice.
originone of pending, invoiceinvoice: created for a draft; pending: created for the next invoice.
descriptionstring
productIdprod_… ID
priceIdprice_… ID or null
taxCategoryIdone of 9 values, e.g. electronically_supplied_service, saas, ebook (all in the OpenAPI document)
taxBehaviorone of inclusive, exclusive
quantityinteger
unitAmountmoney
amountmoneyQuantity × unit amount.
periodobject or null
prorationboolean
taxDatedate-time or nullThe date whose tax rates apply (a proration's change date).
metadataobject
createdAtdate-time
updatedAtdate-time

Examples

Add two consulting days to a draft

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

{
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf47yk",
  "productId": "prod_01m4tx5nj8emwbyf7y9vcf47yr",
  "unitAmount": {
    "amount": "600000000",
    "currency": "EUR"
  },
  "quantity": 2,
  "description": "Implementation workshop (days)"
}

Response (201):

JSON
{
  "id": "ii_01m4tx5nj8emwbyf7y9vcf47ys",
  "object": "invoice_item",
  "livemode": false,
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "subscriptionId": null,
  "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf47yk",
  "origin": "invoice",
  "description": "Implementation workshop (days)",
  "productId": "prod_01m4tx5nj8emwbyf7y9vcf47yr",
  "priceId": null,
  "taxCategoryId": "consulting_remote",
  "taxBehavior": "exclusive",
  "quantity": 2,
  "unitAmount": {
    "amount": "600000000",
    "currency": "EUR"
  },
  "amount": {
    "amount": "1200000000",
    "currency": "EUR"
  },
  "period": null,
  "proration": false,
  "taxDate": null,
  "metadata": {},
  "createdAt": "2026-10-20T08:30:00.000Z",
  "updatedAt": "2026-10-20T08:30:00.000Z"
}

A setup fee for the customer's next invoice

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

{
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "priceId": "price_01m4tx5nj8emwbyf7y9vcf47yj"
}

Response (201):

JSON
{
  "id": "ii_01m4tx5nj8emwbyf7y9vcf47ys",
  "object": "invoice_item",
  "livemode": false,
  "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47ym",
  "subscriptionId": null,
  "invoiceId": null,
  "origin": "pending",
  "description": "Genno Pro (Setup fee)",
  "productId": "prod_01m4tx5nj8emwbyf7y9vcf47yh",
  "priceId": "price_01m4tx5nj8emwbyf7y9vcf47yj",
  "taxCategoryId": "saas",
  "taxBehavior": "exclusive",
  "quantity": 1,
  "unitAmount": {
    "amount": "49000000",
    "currency": "EUR"
  },
  "amount": {
    "amount": "49000000",
    "currency": "EUR"
  },
  "period": null,
  "proration": false,
  "taxDate": null,
  "metadata": {},
  "createdAt": "2026-10-20T08:30:00.000Z",
  "updatedAt": "2026-10-20T08:30:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is malformed, both or neither of priceId and productId, an archived product, the item's customer isn't the draft's.Fix the fields listed in details.issues and send the request again.
resource_not_found404The customer, the invoice, the price or the 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_status_invalid409invoiceId names an invoice that isn't a draft.Check the invoice's status (details.status) and what it still allows (details.allowed_actions). Drafts are edited and finalized; open invoices are sent, paid, voided or marked uncollectible; paid and void invoices don't change (corrections are credit notes).
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.