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.

Terminal
npx skills add CFDI-Express/skills

Má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

  1. Crea tu cuenta en dash.cfdi.express y copia tu llave sk_test_. Viene con saldo de pruebas.
  2. Registra tu emisor con POST /v1/merchants y sube su CSD con POST /v1/merchants/{id}/csd.
  3. Timbra tu primer CFDI con POST /v1/invoices.
  4. Entrega el XML y el PDF con las URLs firmadas que devuelve GET /v1/invoices/{id}.
Tu primer request
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:

Header
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.

Desde la v1.38.0 cada cuenta es un workspace. El header x-account-id indica la cuenta. Si no eres miembro, la respuesta es 403. Las API keys no cambian. Un miembro consulta el saldo y la facturación en solo lectura: POST /v1/billing/checkout_sessions y POST /v1/billing/portal_sessions responden 403. La guía está en Equipo y workspaces.

  • 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ónRespuesta
Misma llave, mismo cuerpo, petición ya resueltaLa respuesta original con el header Idempotency-Replayed: true. No gasta otro timbre.
Misma llave, otra petición todavía en proceso409 request_in_flight
Misma llave, cuerpo distinto422 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.

Siguiente página
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:

400 Bad Request
{
  "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}$" }
  ]
}
StatuscodeCuándo aparece
400validation_errorAlgún campo no pasó validación. Incluye errors[] con el path de cada problema, o subcode al validar un CSD.
401unauthorizedFalta el header Authorization o la llave no es válida.
403forbiddenLa llave no tiene acceso a ese recurso.
404not_foundEl recurso no existe en tu cuenta y modo.
402insufficient_creditsNo hay saldo suficiente para el timbre. Recarga y reintenta.
402monthly_limit_reachedAlcanzaste el límite mensual configurado en tu cuenta.
409request_in_flightOtra petición con el mismo Idempotency-Key sigue en proceso.
422idempotency_key_reuseReusaste una llave de idempotencia con un cuerpo distinto.
422sat_rejectedEl SAT rechazó el comprobante. El detalle trae el código del SAT.
429rate_limitedExcediste el límite de requests por minuto.
503pac_unavailableEl PAC está temporalmente fuera de servicio. Reintenta con la misma llave.
500internal_errorError inesperado de nuestro lado.

Límites

  • 300 requests por minuto por cuenta (configurable). Al excederlo recibes 429 con Retry-After; las respuestas traen X-RateLimit-Limit y X-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.

Instalar
npx skills add CFDI-Express/skills
Sólo esta skill, o para un agente en específico
npx 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 18 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. Desde la v1.38.0 un miembro consulta en solo lectura: POST /v1/billing/checkout_sessions y POST /v1/billing/portal_sessions responden 403.

Emisores (merchants)

Cada emisor es un RFC con su propio CSD, serie y logo. Una cuenta puede tener varios emisores activos al mismo tiempo.

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