Referencia de la API
La API de CFDI Express timbra CFDI 4.0 ante el SAT desde cualquier sistema que hable HTTPS: facturas PUE, PPD y globales, complementos de pago REP, notas de crédito y cancelaciones con acuse. Es independiente de Shopify y sigue convenciones estilo Stripe, así que si ya integraste Stripe alguna vez, esto te va a resultar familiar.
Integrar con un agente, en una línea
Si vas a implementar con un agente de código —Claude Code, Cursor, Codex, OpenCode— instálale primero la skill oficial de CFDI Express y pídele la integración: se lleva esta referencia completa como contexto.
npx skills add CFDI-Express/skillsMás detalles en Para agentes de IA. Si prefieres escribir el código tú, sigue con los cuatro pasos de abajo.
Empezar en 4 pasos
- Crea tu cuenta en dash.cfdi.express y copia tu llave
sk_test_. Viene con saldo de pruebas. - Registra tu emisor con POST /v1/merchants y sube su CSD con POST /v1/merchants/{id}/csd.
- Timbra tu primer CFDI con POST /v1/invoices.
- Entrega el XML y el PDF con las URLs firmadas que devuelve GET /v1/invoices/{id}.
curl https://api.cfdi.express/v1/balance \
-H "Authorization: Bearer sk_test_..."URL base
Todos los endpoints viven bajo https://api.cfdi.express y los de la versión 1 llevan el prefijo /v1. Sólo se aceptan conexiones HTTPS.
Autenticación
Cada request lleva tu llave secreta como bearer token:
Authorization: Bearer sk_live_...La llave define el modo: sk_test_ timbra contra el sandbox del PAC sin costo y sk_live_ emite CFDIs reales con validez fiscal. Cada modo tiene su propio saldo, sus propios emisores y sus propios documentos; ningún recurso cruza de un modo al otro. Todos los recursos traen el campo livemode para que sepas en cuál estás.
- Las llaves son secretas: úsalas sólo desde tu servidor, nunca desde el navegador o una app móvil.
- El sandbox es gratis e ilimitado. Prueba ahí todo el flujo antes de recargar saldo.
Idempotencia
Los endpoints que timbran o cancelan requieren el header Idempotency-Key. Manda un valor estable por operación lógica —el id de tu pedido, de tu devolución o de tu transacción— y los reintentos son seguros:
| Situación | Respuesta |
|---|---|
| Misma llave, mismo cuerpo, petición ya resuelta | La respuesta original con el header Idempotency-Replayed: true. No gasta otro timbre. |
| Misma llave, otra petición todavía en proceso | 409 request_in_flight |
| Misma llave, cuerpo distinto | 422 idempotency_key_reuse |
Paginación
Las listas usan paginación por cursor: pide hasta limit=100 elementos y, mientras has_more sea true, manda el id del último elemento en starting_after.
curl -G https://api.cfdi.express/v1/invoices \
-H "Authorization: Bearer sk_live_..." \
--data-urlencode "limit=100" \
--data-urlencode "starting_after=inv7k3q9x2m4v1t8p6d0n5cb"Errores
Los errores siguen application/problem+json (RFC 7807) con un code estable pensado para que tu integración —o tu agente de IA— reaccione sin parsear textos:
{
"type": "https://api.cfdi.express/docs/errors/validation_error",
"title": "Validation error",
"status": 400,
"code": "validation_error",
"detail": "Request validation failed",
"errors": [
{ "path": "receiver.zip", "message": "String must match pattern ^\\d{5}$" }
]
}| Status | code | Cuándo aparece |
|---|---|---|
| 400 | validation_error | Algún campo no pasó validación. Incluye errors[] con el path de cada problema, o subcode al validar un CSD. |
| 401 | unauthorized | Falta el header Authorization o la llave no es válida. |
| 403 | forbidden | La llave no tiene acceso a ese recurso. |
| 404 | not_found | El recurso no existe en tu cuenta y modo. |
| 402 | insufficient_credits | No hay saldo suficiente para el timbre. Recarga y reintenta. |
| 402 | monthly_limit_reached | Alcanzaste el límite mensual configurado en tu cuenta. |
| 409 | request_in_flight | Otra petición con el mismo Idempotency-Key sigue en proceso. |
| 422 | idempotency_key_reuse | Reusaste una llave de idempotencia con un cuerpo distinto. |
| 422 | sat_rejected | El SAT rechazó el comprobante. El detalle trae el código del SAT. |
| 429 | rate_limited | Excediste el límite de requests por minuto. |
| 503 | pac_unavailable | El PAC está temporalmente fuera de servicio. Reintenta con la misma llave. |
| 500 | internal_error | Error inesperado de nuestro lado. |
Límites
- 300 requests por minuto por cuenta (configurable). Al excederlo recibes
429conRetry-After; las respuestas traenX-RateLimit-LimityX-RateLimit-Remaining. - El cuerpo de la petición no puede exceder 1 MB.
- Hasta 500 conceptos por factura.
- Las URLs de XML, PDF, ZIP, acuses y logos son firmadas y expiran a los 15 minutos: vuelve a pedir el recurso cuando necesites unas nuevas.
Precio
$1 MXN por timbre con descuentos por volumen, saldo prepagado, sin mensualidad. Cada timbre reserva saldo y lo confirma al recibir el UUID; si el SAT rechaza o el PAC falla, el reembolso es automático y queda registrado en el ledger de transacciones. Las cancelaciones también consumen un timbre. El modo de pruebas es gratis.
Para agentes de IA
Hay dos caminos y se complementan: una skill para que tu agente escriba la integración y un servidor MCP para que facture él mismo.
Skill oficial — que tu agente escriba la integración
La skill cfdi-express-api le da a tu agente de código el contexto completo de esta API: URL base, llaves sk_test_ y sk_live_, idempotencia, paginación, códigos de error, el flujo de 4 pasos y el mapa de todos los endpoints, además de las ligas al OpenAPI y a la referencia en markdown para que lea el esquema exacto en lugar de adivinar campos del SAT.
npx skills add CFDI-Express/skillsnpx skills add CFDI-Express/skills --skill cfdi-express-api
npx skills add CFDI-Express/skills -g -a claude-code- Funciona con Claude Code, Cursor, Codex, OpenCode y cualquier agente soportado por skills.
- Es de código abierto: github.com/CFDI-Express/skills.
- Ya instalada, basta con pedirle lo que necesitas: «timbra un CFDI PUE cuando la orden se marque como pagada, con Idempotency-Key del id de la orden».
Servidor MCP — que tu agente facture
Además de REST, la API expone un servidor MCP en https://api.cfdi.express/mcp (y https://api.cfdi.express/mcp/test para pruebas) que le da a claude.ai, ChatGPT, Claude Code, Cursor o a tu propio agente 14 herramientas para timbrar, cancelar y consultar. Ver la guía del servidor MCP.
Todos los endpoints
Meta
Endpoints públicos de salud del servicio. No requieren llave y sirven para monitoreo.
Saldo y facturación
Consulta tu saldo prepagado, recarga con tarjeta vía Stripe y audita cada centavo con el ledger de transacciones.
Emisores (merchants)
Cada emisor es un RFC con su propio CSD, serie y logo. Una cuenta puede tener varios emisores activos al mismo tiempo.
- POST/v1/merchantsCrear emisor
- GET/v1/merchantsListar emisores
- GET/v1/merchants/{id}Obtener emisor
- PATCH/v1/merchants/{id}Actualizar emisor
- DELETE/v1/merchants/{id}Eliminar emisor
- POST/v1/merchants/{id}/csdSubir CSD
- PUT/v1/merchants/{id}/csdReemplazar CSD
- GET/v1/merchants/{id}/csdConsultar CSD
- PUT/v1/merchants/{id}/logoSubir logo
- DELETE/v1/merchants/{id}/logoEliminar logo
Facturas
Timbrado de CFDI 4.0 de ingreso: nominativas PUE y PPD, y facturas globales al público en general.
Notas de crédito
CFDI de egreso para devoluciones, reembolsos y descuentos posteriores a la factura.
Complementos de pago (REP)
Pagos 2.0 contra facturas PPD, con parcialidades y saldos calculados en el servidor.
Catálogos SAT
Claves de producto/servicio, unidades, usos de CFDI, regímenes fiscales y formas de pago servidos desde nuestra base local.
Referencias
npx skills add CFDI-Express/skills y tu agente de código integra la API por ti.Documentación de la appGuías de la app de Shopify: portal de facturación, CSD y más.