API REST v1
Base: https://cfid.vitasoft.com.mx/api/v1. JSON en UTF-8. Errores en español con la lista issues (campo, mensaje, nivel: error bloquea, aviso no).
Autenticación
Cree una API key en Empresa, usuarios y API. Cada key pertenece a una empresa (RFC emisor) y tiene un rol (lectura, facturista, administrador).
Authorization: Bearer cfid_xxxxxxxxxxxxxxxxxxxx
Idempotencia
Envíe Idempotency-Key: <id único de su sistema> al crear CFDI o pagos. Si repite la petición (p. ej. por un timeout) recibe el mismo comprobante, nunca uno duplicado.
Códigos de respuesta al timbrar
| 201 | Timbrado. Incluye uuid y ligas a XML/PDF. |
| 202 | Aceptado; el PAC no respondió y se reintentará solo (status: pendiente, reintento_programado). Consulte GET /cfdi/{id}. |
| 422 | Rechazado por la revisión previa o por el PAC; ver issues / error. |
| 401 / 403 | API key inválida / rol insuficiente. |
Endpoints
POST /cfdi/validar — revisión previa sin timbrar ni consumir folio. Devuelve valido, issues y totales.
POST /cfdi — crear y timbrar (Ingreso, Egreso, Traslado). El emisor se toma de la API key; serie con folio automático.
curl -X POST https://cfid.vitasoft.com.mx/api/v1/cfdi \
-H "Authorization: Bearer $CFID_KEY" -H "Idempotency-Key: pedido-1001" -H "Content-Type: application/json" -d '{
"tipo": "I", "serie": "A", "forma_pago": "03", "metodo_pago": "PUE", "moneda": "MXN",
"receptor": {"rfc": "URE180429TM6", "nombre": "UNIVERSIDAD ROBOTICA ESPAÑOLA", "regimen_fiscal": "601",
"codigo_postal": "86991", "uso_cfdi": "G03"},
"conceptos": [{"clave_prod_serv": "81112100", "cantidad": "1", "clave_unidad": "E48", "unidad": "Servicio",
"descripcion": "Hosting mensual", "valor_unitario": "1000.00", "objeto_imp": "02",
"traslados": [{"impuesto": "002", "tipo_factor": "Tasa", "tasa_o_cuota": "0.160000"}]}]
}'
Campos opcionales: folio, tipo_cambio (si moneda ≠ MXN), condiciones_pago, lugar_expedicion (por defecto el C.P. de la empresa), relacionados: [{"tipo_relacion": "01", "uuids": ["…"]}], informacion_global: {"periodicidad": "04", "meses": "01", "anio": 2026} (factura global a XAXX010101000), por concepto descuento, no_identificacion, retenciones: [{"impuesto": "001", "tipo_factor": "Tasa", "tasa_o_cuota": "0.100000"}]; IVA exento: {"impuesto":"002","tipo_factor":"Exento"}.
GET /cfdi — listar. Filtros: status, tipo, receptor_rfc, uuid, desde, hasta (AAAA-MM-DD), limit, offset.
GET /cfdi/{id} · GET /cfdi/{id}/xml · GET /cfdi/{id}/pdf
POST /cfdi/{id}/timbrar — reintentar ahora uno en pendiente (reenvía el mismo XML sellado; sin riesgo de duplicado).
POST /cfdi/{id}/cancelar (rol administrador) — {"motivo": "02"} o {"motivo": "01", "folio_sustitucion": "UUID-del-CFDI-que-lo-sustituye"}. Motivos: 01 con relación, 02 sin relación, 03 no se llevó a cabo la operación, 04 operación nominativa en factura global. Estatus resultante: cancelado o cancelando (cuando el SAT pide aceptación del receptor; se verifica solo).
POST /cfdi/{id}/sat — consultar el estatus en el SAT (Vigente / Cancelado / No Encontrado).
POST /cfdi/{id}/enviar — {"para": ["cliente@correo.com"]}: envía XML + PDF.
POST /pagos — emitir Complemento de Pago 2.0 sobre facturas PPD (mismo cliente, MXN):
{"fecha_pago": "2026-10-14T10:00:00", "forma_pago": "03", "num_operacion": "SPEI 123",
"documentos": [{"id": 15, "importe": "580.00"}, {"uuid": "…", "importe": "1160.00"}]}
La parcialidad, saldo anterior, saldo insoluto e impuestos proporcionales se calculan solos.
POST /recibidos/xml — cargar un CFDI recibido (cuerpo = XML, Content-Type: application/xml). GET /recibidos — listar (emisor_rfc, limit).
GET /catalogos/{nombre}?q= — catálogos SAT: regimen_fiscal, uso_cfdi, forma_pago, metodo_pago, objeto_imp, tipo_relacion, exportacion, periodicidad, meses, motivo_cancelacion, moneda, clave_prod_serv (con q), clave_unidad (con q).
Respuesta de un CFDI
{"id": 15, "tipo": "I", "serie": "A", "folio": "7", "uuid": "5FB2822E-…", "status": "timbrado",
"receptor": {"rfc": "URE180429TM6", "nombre": "…"}, "moneda": "MXN", "total": "1160.00", "metodo_pago": "PUE", "saldo": null,
"pac": "sw", "sandbox": false, "error": null, "reintento_programado": null, "fecha": "…", "timbrado": "…",
"cancelacion": null, "sat": null, "links": {"self": "/api/v1/cfdi/15", "xml": "/api/v1/cfdi/15/xml", "pdf": "/api/v1/cfdi/15/pdf"}}
Estatus: borrador, timbrando, pendiente, timbrado, error, cancelando, cancelado.