Empezar
Inicio rápido
- 1
Ten a la mano tus credenciales
Cada cuenta tiene un usuario y una contraseña por ambiente. Guárdalos como variables de entorno: todos los ejemplos de esta documentación los leen de ahí. ¿Aún no los tienes? Entra a tu cuenta (o créala) y activa la API: ahí salen los de los dos ambientes.
¿Ya usabas el servicio anterior? Escríbenos y ligamos tu cuenta.
Terminalexport DUBSARIA_USUARIO="tu-usuario" export DUBSARIA_CLAVE="tu-contraseña" - 2
Carga tu sello (CSD)
Una sola vez por RFC. En pruebas usa el CSD de prueba que publica el SAT:
EKU9003173C9, con la contraseña12345678a. Antes de guardarlo se revisa que la llave abra, que corresponda al certificado y que esté vigente.CERTIFICADO=$(base64 < EKU9003173C9.cer | tr -d '\n') LLAVE=$(base64 < EKU9003173C9.key | tr -d '\n') curl https://pruebas.timbrado.idea15.com/api/CargarCertificado \ -u "$DUBSARIA_USUARIO:$DUBSARIA_CLAVE" \ -H "Content-Type: application/json" \ -d @- <<FIN { "certificadoBase64": "$CERTIFICADO", "llaveBase64": "$LLAVE", "password_Llave": "$CLAVE_LLAVE" } FINRespuesta · HTTP 200{ "Codigo": "100", "Mensaje": "Certificado cargado exitosamente." } - 3
Timbra tu primera factura
Guarda este comprobante como
factura.json. Es una factura de ingreso con IVA; en los ejemplos están todos los demás tipos.factura.json{ "comprobante": { "Exportacion": "01", "LugarExpedicion": "94734", "MetodoPago": "PUE", "TipoDeComprobante": "I", "Total": "116.00", "Moneda": "MXN", "SubTotal": "100.00", "FormaPago": "03", "Fecha": "2026-10-29T21:19:05", "Folio": "1", "Serie": "PRUEBA", "Emisor": { "Rfc": "EKU9003173C9", "Nombre": "ESCUELA KEMPER URGATE", "RegimenFiscal": "601" }, "Receptor": { "Rfc": "EKU9003173C9", "Nombre": "ESCUELA KEMPER URGATE", "UsoCFDI": "G03", "RegimenFiscalReceptor": "601", "DomicilioFiscalReceptor": "94734" }, "Conceptos": [ { "ClaveProdServ": "84111506", "Cantidad": "1", "ClaveUnidad": "E48", "Descripcion": "Servicio de prueba", "ValorUnitario": "100.00", "Importe": "100.000000", "ObjetoImp": "02", "Impuestos": { "Traslados": [ { "Base": "100.000000", "Impuesto": "002", "TipoFactor": "Tasa", "TasaOCuota": "0.160000", "Importe": "16.000000" } ] } } ], "Impuestos": { "Traslados": [ { "Base": "100.00", "Impuesto": "002", "TipoFactor": "Tasa", "TasaOCuota": "0.160000", "Importe": "16.00" } ], "TotalImpuestosTrasladados": "16.00" } } }Y mándalo:
curl https://pruebas.timbrado.idea15.com/api/TimbrarCfdiObj \ -u "$DUBSARIA_USUARIO:$DUBSARIA_CLAVE" \ -H "Content-Type: application/json" \ -d @factura.jsonRespuesta · HTTP 200{ "Codigo": "100", "Mensaje": "Comprobante timbrado exitosamente", "UUID": "988B5F3A-889E-4C9C-BAC7-0FEE99589858", "XMLBase64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxj…", "PDFBase64": null, "IdSeguimiento": "8ce2fefe4ebfae89987a6b49d2f4acbf09542845e2be24e0091cb3aa9ad00d43" }Cambia la Fecha por la de ahora
El SAT acepta hasta 72 horas atrás. Si mandas exactamente el mismo comprobante otra vez, la respuesta es 506 con el mismo UUID: así funciona la protección contra timbres dobles. - 4
Guarda el XML y el IdSeguimiento
XMLBase64es el CFDI timbrado completo: es lo que le entregas a tu cliente y lo que guardas cinco años. Guarda tambiénIdSeguimiento: con él preguntas por el desenlace si alguna vez una respuesta no llega (reintentos).Pythonimport base64 if datos["Codigo"] in ("100", "506"): with open(f"{datos['UUID']}.xml", "wb") as archivo: archivo.write(base64.b64decode(datos["XMLBase64"]))
Listo
