Create Invoice
The issuing organization is resolved from the API key — no organizationId is required. The customer can be sent inline (customer) or referenced by ID (customerId).
Authentication
Requires an API key with thewrite:invoices scope, sent via the X-API-Key header. The issuing organization is resolved from the API key — there is no organizationId parameter anywhere in this request. The issuer’s RFC, legal name, régimen fiscal, and ZIP code are resolved from the organization’s fiscal profile (PUT /organizations/:organizationId/legal) — configure that before creating your first invoice, or this endpoint returns a 400.
This endpoint does not accept Supabase Bearer tokens, since a logged-in user can belong to multiple organizations and the organization can’t be resolved unambiguously that way.
Request Body
customer or customerId is required — sending both, or neither, returns a 400.
subtotal and total are not request fields — they’re computed automatically from items.
customer (inline)
items[]
Business rules applied automatically
- The issuer (RFC, legal name, régimen fiscal, ZIP) is resolved from
organization_legal, matching how Facturapi resolves the issuer from the account profile instead of requiring it on every request. baseis required on every tax line in CFDI 4.0 — filled from the item’samountif omitted.subtotal/totalare computed fromitems[].amountanditems[].taxes[].amount.- Invoices to público en general (
customer.taxId = XAXX010101000,customer.legalName = PUBLICO EN GENERAL,type = I) automatically get the SATInformacionGlobalnode anduse = S01. - The customer’s RFC, régimen fiscal, and uso CFDI are validated against the SAT catalog compatibility matrix before stamping (see Create Customer for the same validation rules).
docs/PAC_CFDI_CONTRACT.md in the repository for the internal payload contract this endpoint translates into before calling the PAC.
Idempotency
Stamping is not safe to blindly retry — if your request toPOST /invoices times out, you can’t tell whether the CFDI was actually stamped at the SAT before the timeout. Pass a unique idempotencyKey (e.g. your own order ID) and retry with the same key: if an invoice was already created for your organization with that key, the existing invoice is returned instead of stamping a second one.
idempotencyKey, every request stamps a new CFDI — retries are your responsibility to avoid.
Example Request
Example Response
Common Errors
400 Bad Request
Invalid or incomplete invoice payload, an issuing organization without complete fiscal data, sending both/neithercustomer and customerId, or a customer whose RFC/régimen/uso CFDI combination fails SAT catalog validation.
401 Unauthorized
Missing or invalid API key.403 Forbidden
The API key does not have thewrite:invoices scope.
404 Not Found
customerId does not exist, or belongs to a different organization than the one owning the API key.
503 Service Unavailable
The PAC did not respond after automatic retries, or returned a transient error. Safe to retry.Authorizations
API Key for authentication (format: sk_...)
Body
"A"
"1"
"2026-07-30T22:50:00"
SAT forma de pago catalog code
"01"
SAT uso CFDI catalog code
"G03"
Ingreso, Egreso, or Traslado (default: I)
I, E, T "I"
Default: PUE
PUE, PPD "PUE"
Default: MXN
"MXN"
Default: 1
1
SAT clave de exportación catalog code — default: 01
"01"
Existing customer ID — mutually exclusive with customer
Client-supplied key to safely retry this request without double-stamping. If an invoice was already created for this organization with the same key, that invoice is returned instead of stamping again.
"order-8421-attempt-1"
Response
Timbrix invoice record ID
"0f2a1c3e-1a2b-4c3d-9e8f-1234567890ab"
Folio fiscal UUID asignado por el SAT vía PAC
"d3bfbc57-44af-4390-a064-f0afab85e5df"
valid "valid"
"A"
"1"
116
"2026-07-30T22:50:00"
XML del CFDI timbrado (UTF-8)
"2026-07-30T22:50:03.412Z"