Skip to main content
POST
Create and stamp a CFDI 4.0 invoice via the configured PAC
Builds, validates, and stamps (timbra) a CFDI 4.0 invoice through the configured PAC (Proveedor Autorizado de Certificación) in a single call. On success, the invoice is fiscally valid at the SAT and is recorded in the organization’s invoice history.

Authentication

Requires an API key with the write: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

* Exactly one of 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.
  • base is required on every tax line in CFDI 4.0 — filled from the item’s amount if omitted.
  • subtotal/total are computed from items[].amount and items[].taxes[].amount.
  • Invoices to público en general (customer.taxId = XAXX010101000, customer.legalName = PUBLICO EN GENERAL, type = I) automatically get the SAT InformacionGlobal node and use = 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).
See 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 to POST /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.
Without an 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/neither customer 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 the write: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

X-API-Key
string
header
required

API Key for authentication (format: sk_...)

Body

application/json
series
string
required
Example:

"A"

folioNumber
string
required
Example:

"1"

date
string
required
Example:

"2026-07-30T22:50:00"

paymentForm
string
required

SAT forma de pago catalog code

Example:

"01"

use
string
required

SAT uso CFDI catalog code

Example:

"G03"

items
object[]
required
type
enum<string>

Ingreso, Egreso, or Traslado (default: I)

Available options:
I,
E,
T
Example:

"I"

paymentMethod
enum<string>

Default: PUE

Available options:
PUE,
PPD
Example:

"PUE"

currency
string

Default: MXN

Example:

"MXN"

exchange
number

Default: 1

Example:

1

export
string

SAT clave de exportación catalog code — default: 01

Example:

"01"

customer
object
customerId
string

Existing customer ID — mutually exclusive with customer

idempotencyKey
string

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.

Example:

"order-8421-attempt-1"

Response

id
string
required

Timbrix invoice record ID

Example:

"0f2a1c3e-1a2b-4c3d-9e8f-1234567890ab"

uuid
string
required

Folio fiscal UUID asignado por el SAT vía PAC

Example:

"d3bfbc57-44af-4390-a064-f0afab85e5df"

status
enum<string>
required
Available options:
valid
Example:

"valid"

series
string
required
Example:

"A"

folioNumber
string
required
Example:

"1"

total
number
required
Example:

116

date
string
required
Example:

"2026-07-30T22:50:00"

xml
string
required

XML del CFDI timbrado (UTF-8)

createdAt
string
required
Example:

"2026-07-30T22:50:03.412Z"