POST
/v1/mx/invoices
Crear una factura
Crea y timbra un CFDI 4.0 en una sola llamada. La respuesta llega cuando el PAC devuelve el UUID: la llamada es síncrona, así que cuando te contestamos el comprobante ya está presentado o ya sabemos por qué no.
Manda siempre
Idempotency-Key. Si repites la llamada con la misma clave te devolvemos la factura original en vez de timbrar dos veces, con la cabecera Idempotency-Replayed: true.
Parámetros
- customer objeto · requerido si no mandas customer_id
- El receptor. Lleva tax_id, legal_name, tax_regime y postal_code; opcionales default_cfdi_use, email, tax_residency y foreign_tax_id. Ver Clientes. Lo buscamos entre los clientes del emisor que timbra. El comprobante sale con lo que mandes, y al timbrarse guardamos esos datos en el cliente; un rechazo lo deja como estaba. Con XAXX010101000 ponemos el código postal del emisor, que es el único que el SAT acepta.
- customer_id entero · requerido si no mandas customer
- Un cliente que ya tienes guardado, por su id. Lo buscamos entre los clientes del emisor que timbra: el id de un cliente de otro emisor contesta not_found.
- issuer_id entero · requerido si tienes más de un emisor
- Con qué RFC se timbra. Si tu cuenta tiene un solo emisor lo puedes omitir; con dos o más lo pedimos, porque adivinarlo sería timbrar con el RFC equivocado.
- cfdi_use string · opcional
- Clave del catálogo de uso del CFDI, por ejemplo G03 para gastos en general. Si lo omites usamos el uso predeterminado del cliente. Lo validamos contra el régimen y el tipo de persona del receptor: un uso que no le aplica contesta validation_failed sin llamar al PAC.
- payment_method string · opcional
- PUE cuando el pago ya se hizo en una sola exhibición; PPD cuando queda a crédito y se liquidará después con un complemento de pago. Por omisión, PUE.
- payment_form string · opcional
- Clave del catálogo de formas de pago del SAT, por ejemplo 03 para transferencia electrónica de fondos. Por omisión, 03. Con payment_method PPD tiene que ser 99 (Por definir): el SAT rechaza cualquier otra, y contestamos 422 antes de timbrar.
- items arreglo · requerido
- Los conceptos. Cada uno lleva description, quantity y unit_price, más product_service_key y unit_key. Si mandas product_id, la descripción, el precio y las dos claves salen del producto guardado; lo que mandes en la partida gana. quantity es 1 si no la dices. El producto tiene que ser del emisor que timbra, o contestamos not_found.
- items[].tax_object string · opcional
- El ObjetoImp de la partida, del catálogo c_ObjetoImp: 01, 02, 03 o 04. Sin él, el del producto, y si no 02.
- items[].discount decimal · opcional
- El descuento de la partida, en la moneda del comprobante. No puede ser mayor que su importe. El descuento del comprobante es la suma de los de las partidas.
- items[].vat_rate / withholding_rate / vat_withholding_rate decimal · opcionales
- Las tasas de esa partida, con los mismos valores que las del comprobante. Sin ellas, la partida usa las del comprobante. Una factura puede mezclar tasas.
- items[].vat_withheld decimal · opcional
- El IVA retenido de esa partida tal como lo calcula tu cliente, cuando no es el de la tasa. Calculamos la tasa de seis decimales que lo da exacto y es la que se timbra. Si ninguna lo da, contestamos 422 con las dos cifras más cercanas que sí se pueden timbrar.
- items[].tax_factor string · opcional
- Tasa o Exento. Exento es una partida que es objeto del impuesto y no lo causa; no es lo mismo que vat_rate 0, que es tasa cero.
- items[].identification_number string · opcional
- El NoIdentificacion del concepto: tu clave del producto o su número de serie. En una factura global va el folio del comprobante de venta que ampara cada concepto (regla 2.7.1.21 de la RMF). Hasta 100 caracteres y sin |.
- items[].ieps_rate / ieps_quota decimal · opcionales
- El IEPS de la partida, a tasa o a cuota, nunca los dos: el traslado lleva un solo factor. A tasa va sobre la base; a cuota se multiplica por la cantidad, porque grava por unidad de medida y no por importe. Manda ieps_in_vat_base: false si el IEPS no debe entrar en la base del IVA; omitirlo lo deja dentro, que es lo ordinario.
- relations arreglo · opcional
- Los comprobantes que éste relaciona, cada uno con uuid y relation_type del catálogo c_TipoRelacion (01 a 07). Un sustituto relaciona con 04 al que reemplaza. Después cancelas el original con motivo 01 y el UUID del sustituto en substitute_uuid. Una nota de crédito relaciona con 01 la factura que corrige.
- voucher_type string · opcional
- I, ingreso, por omisión. E para una nota de crédito: tiene que llevar relations con la factura que corrige (relation_type 01), o contestamos validation_failed. Cualquier otro valor contesta invalid_parameter.
- global_information objeto · opcional
- Para una factura global: periodicity (01 diario, 02 semanal, 03 quincenal, 04 mensual, 05 bimestral), month (01 a 12, o 13 a 18 si es bimestral) y year (2019 en adelante). Van los tres juntos y el receptor es XAXX010101000, público en general. En cada concepto, identification_number lleva el folio de la venta que ampara.
- series / vat_rate string / decimal · opcionales
- La serie es A si no dices otra, y el folio siempre lo asignamos nosotros: es lo que mantiene la secuencia del emisor sin huecos. vat_rate acepta 0.16, 0.08 (franja fronteriza) o 0; por omisión, 0.16.
- tax_included booleano · opcional
- Manda true si tus precios ya traen el IVA adentro, como se ven en un menú o en una etiqueta. Nosotros separamos la base y el traslado, y el total del comprobante queda exactamente en lo que cobraste. Sin esto, bajar los precios a la base por tu cuenta desfasa el total un centavo seguido: $59 y $89 son $148 en la caja y $147.99 en la factura.
- withholding_rate decimal · opcional
- ISR retenido: 0.0125, 0.10 o 0. Por omisión, 0. Un emisor RESICO (régimen 626) retiene 1.25% cuando le factura a una persona moral; una persona física que cobra honorarios a una moral, 10%. Va explícito y no lo deducimos del régimen: quién retiene depende del receptor, y esa decisión es tuya.
- vat_withholding_rate decimal · opcional
- IVA retenido. Por omisión, 0. Las tasas de ley son 0.106667 (dos terceras partes del 16%: honorarios, renta o comisiones de una persona física), 0.04 (flete), 0.06 (servicios especializados) y la tasa del IVA completa (desperdicios). En la región fronteriza, dos tercios del 8% son 0.053333. Se acepta una tasa a menos de 0.0001 de una de ésas, como 0.10667, porque así la calculan muchos clientes; más lejos es un error. Nunca puede retener más IVA del que traslada la partida. Va junto con withholding_rate y no en su lugar: el mismo recibo retiene ISR e IVA.
- currency string · opcional
- Clave del catálogo c_Moneda: MXN, USD, EUR, CAD, GBP, CHF, AUD, CNY, BRL, COP, ARS, PEN, CLP, JPY, KWD. Por omisión, MXN. Los importes de items van en esta moneda y el comprobante los escribe tal cual, sin convertirlos a pesos.
- exchange_rate decimal · condicional
- Los pesos que costaba una unidad de esa moneda el día de la emisión, hasta seis decimales. Requerido en cuanto currency no es MXN, y no se acepta cuando sí lo es: el SAT pide TipoCambio en toda moneda extranjera y lo rechaza en pesos. En MXN aceptamos 1 y lo descartamos. No lo consultamos por ti — el tipo de cambio de un comprobante es el de su fecha, y queda escrito con él.
- issued_at string · opcional
- La fecha del comprobante en ISO 8601, para facturar hoy algo de ayer. Por omisión, el instante del timbrado. El artículo 29-A la limita a las 72 horas anteriores y no admite fechar hacia adelante, así que fuera de ese rango contestamos 422 sin llamar al PAC y sin gastarte un timbre. Sin offset la leemos en la zona horaria de tu código postal de expedición, que es contra la que el SAT valida el Fecha: 2026-08-25T14:30 son las 14:30 de donde expides. Con offset explícito manda el offset.
Respuesta
Devolvemos 201
con el UUID en cuanto el PAC responde. Si el PAC rechaza el timbrado
devolvemos 422
con su motivo traducido a un código estable, y la factura en estado
error
dentro de details:
el borrador se queda, para que puedas leer el rechazo contra un folio real.
- id entero
- Identificador de la factura dentro de oden.tax.
- status string
- draft, stamping, stamped, error o canceled.
- uuid string
- Folio fiscal del SAT, 36 caracteres. Llega en null si todavía no hay timbre.
- series / number string / entero
- La serie y el folio consecutivo dentro de ella.
- folio string
- Las dos anteriores juntas, que es como se lee un comprobante: A-1044.
- cfdi_use / payment_form / payment_method string
- Lo que lleva el comprobante, ya con los valores por omisión resueltos.
- vat_rate / withholding_rate / vat_withholding_rate string
- Las tasas del comprobante.
- issued_at / stamped_at / canceled_at string
- Fecha del comprobante, del timbrado y de la cancelación, en ISO 8601 con zona horaria. null mientras no haya pasado.
- subtotal / transferred_taxes / total string
- Importes con dos decimales. Van como texto a propósito: un número en JSON es un flotante. transferred_taxes es el IVA más el IEPS, igual que el TotalImpuestosTrasladados del comprobante: los dos son impuestos trasladados y el SAT los pide en un solo total.
- withheld_taxes string
- ISR retenido, ya restado del total. 0.00 en un comprobante sin retención.
- vat_withheld_taxes string
- IVA retenido, ya restado del total. Va aparte del anterior porque son dos impuestos distintos, y sumarlos deja un importe que no corresponde a ninguno.
- currency string
- Clave del catálogo c_Moneda con que se timbró el comprobante.
- exchange_rate string
- El TipoCambio del comprobante, hasta seis decimales. Llega en null cuando la moneda es MXN.
- issuer objeto
- El emisor tal como quedó en el comprobante: id, tax_id, legal_name, tax_regime y postal_code (el del lugar de expedición).
- customer objeto
- El receptor tal como quedó en el comprobante: id, tax_id, legal_name, tax_regime y postal_code, más tax_residency y foreign_tax_id cuando es extranjero.
- items arreglo
- Los conceptos: product_service_key, unit_key, description, quantity, unit_price y amount, con sus importes ya calculados.
- items[].transferred_taxes string
- Lo que trasladó esa partida: su IVA más su IEPS, con el mismo criterio que el campo de arriba. Las partidas suman el total del comprobante, que es lo que hace que se pueda conciliar línea por línea. Si necesitas los dos por separado, la tasa que mandaste los reconstruye; dínoslo y los devolvemos partidos.
- xml_url / pdf_url string
- Sólo cuando hay comprobante. Son estables: puedes guardarlas.
- error objeto
- Sólo en una factura rechazada, con code y message.
- cancellation objeto
- Sólo si se pidió cancelarla. Ver Cancelar una factura.
Errores comunes
Todos tienen la misma forma: {"error": {"code", "message"}}, con
el code
en inglés para que puedas hacer switch y el mensaje en español para mostrarlo.
- unauthorized
- Falta la llave o ya fue revocada. Va como Authorization: Bearer.
- invoice_limit_reached
- Con el plan Básico, tu cuenta ya timbró 100 facturas este mes. 429, con Retry-After hasta el día 1.
- payment_required
- La cuenta tiene un pago pendiente.
- issuer_required
- Tienes más de un emisor y la llamada no dijo cuál.
- issuer_not_ready
- Al emisor le falta su RFC, su régimen, su código postal o su CSD.
- not_found
- El issuer_id, customer_id o product_id no es de tu cuenta o de ese emisor, o no existe. 404.
- missing_parameter
- Falta un campo obligatorio, como items o el receptor. El mensaje dice cuál.
- invalid_parameter
- Un campo no se puede usar: una cantidad o una tasa que no es número, una fecha que no es fecha.
- validation_failed
- Algún dato no pasó nuestras validaciones. details trae cada campo con sus motivos. No se crea borrador.
- folio_conflict
- Otra factura tomó el folio al mismo tiempo. 409. Reintenta.
- csd_revoked
- Tu certificado venció o fue revocado. Sube uno vigente en Configuración o por la API.
- csd_not_from_sat
- El certificado no lo expidió el SAT. Es lo que pasa con un CSD de prueba en producción.
- date_out_of_range
- El PAC dice que la fecha quedó fuera de las 72 horas. Pasa cuando un borrador envejeció antes de timbrarse; un issued_at fuera de rango en la llamada llega como validation_failed.
- invalid_seal
- El sello no coincide con la cadena original (CFDI40102).
- duplicate_cfdi
- Ese comprobante ya tiene un timbre previo.
- pac_unavailable
- El PAC no contestó a tiempo y pudo haber timbrado. Reintenta con la misma Idempotency-Key: le preguntamos al PAC antes de timbrar otra vez.
- stamping_unconfirmed
- No pudimos confirmar si el PAC timbró una factura que quedó sin respuesta. Búscala en el SAT y, si no aparece, timbra con otra Idempotency-Key.
- schema_invalid
- El XML no pasó el esquema del SAT. No llegó al PAC ni costó timbre. 422.
- stamping_failed
- No pudimos preparar o terminar el timbrado por un motivo nuestro. Reintenta.