Validaciones SAT
Un CFDI timbrado no es, por sí mismo, un CFDI deducible. Puede haber sido cancelado después de entregarse, estar firmado con un certificado que ya había vencido, haber sido alterado tras la firma, o provenir de un emisor publicado en el listado del artículo 69-B. Nada de eso es visible en el PDF que llega a cuentas por pagar. Una validación SAT verifica el comprobante contra las fuentes oficiales en cualquier momento posterior a su emisión: Fiscalapi ejecuta siete criterios independientes en una sola llamada y devuelve un veredicto por criterio.
Esta página explica el feature. La referencia completa de los endpoints, los modelos y los ejemplos por lenguaje está en validaciones SAT.
Para qué sirve
- Cuentas por pagar: validar cada CFDI de proveedor al recibirlo y detener el pago de comprobantes que no producen efectos fiscales antes de generar un pasivo.
- Conciliación posterior: detectar cancelaciones ocurridas después de que el comprobante ya fue entregado y registrado.
- Compliance de proveedores: revisar de forma recurrente el padrón de proveedores contra los listados 69-B y 69-B Bis, con la fecha de corte de cada consulta.
- Integridad documental: confirmar que el XML almacenado es el mismo que se firmó y que su estructura cumple el Anexo 20 antes de ingresarlo al ERP.
- Auditoría: conservar el veredicto de cada criterio como soporte de la deducción o el acreditamiento.
Validar no es timbrar
El timbrado certifica un comprobante en el momento de su emisión. La validación verifica, después, que ese comprobante siga siendo íntegro, vigente y fiscalmente efectivo. Son dos operaciones distintas y consumen saldos distintos: el timbrado consume timbres, la validación consume créditos de validación. Los saldos nunca se mezclan. Vea timbres.
Marco legal
- CFF, artículos 29 y 29-A: requisitos de expedición de los comprobantes fiscales digitales.
- Anexo 20 de la Resolución Miscelánea Fiscal: estructura del XML del CFDI y de sus complementos.
- CFF, artículo 69-B: operaciones presuntamente inexistentes (EFOS). Publicado el listado definitivo, los comprobantes del emisor no producen ni produjeron efecto fiscal alguno, y el receptor cuenta con 30 días hábiles desde la publicación en el DOF para acreditar la materialidad de la operación o corregir su situación fiscal.
- CFF, artículo 69-B Bis: transmisión indebida del derecho a disminuir pérdidas fiscales.
Cómo funciona
Envíe el comprobante y la lista de criterios que quiere ejecutar. Fiscalapi consulta la fuente oficial de cada criterio, cobra un crédito por criterio solicitado y responde con un resultado por cada uno:
POST /api/v4/sat-validations
├── xml (CFDI timbrado en Base64) → admite los siete criterios
└── tin (RFC) → solo sat.blacklist.69b y sat.blacklist.69bbis
└── validationTypes[] → resultado por criterio (type, status, passed)
Los resultados vuelven en el orden del catálogo, no en el orden en que se solicitaron. No hay estado intermedio ni consulta posterior: la respuesta de la llamada es el resultado final.
Parámetros de entrada
El cuerpo de la petición lleva dos cosas: qué se va a revisar y qué criterios se van a ejecutar sobre ello.
| Campo | Tipo | Requerido | Qué es |
|---|---|---|---|
xml | string | Uno de los dos | CFDI timbrado completo, codificado en Base64 |
tin | string | Uno de los dos | RFC a consultar |
validationTypes | arreglo de strings | Sí | Identificadores de los criterios a ejecutar, sin vacíos ni duplicados |
Qué se va a revisar: xml o tin
xml y tin son excluyentes: la petición debe llevar exactamente uno de los dos. Enviar ambos, o ninguno,
devuelve 400. Lo que se elija determina qué criterios se pueden pedir.
Con xml se revisa un comprobante concreto y se pueden solicitar los siete criterios. Para los listados
69-B y 69-B Bis se consulta el RFC del nodo cfdi:Emisor del propio comprobante.
Con tin solo se consulta la situación de ese RFC en los listados, así que únicamente se admiten
sat.blacklist.69b y sat.blacklist.69bbis; pedir cualquier otro criterio devuelve 400. El RFC no se
contrasta contra ningún comprobante: la respuesta refleja solo lo que dicen los listados sobre ese RFC. Es la
vía para revisar un proveedor cuando todavía no hay una factura suya que validar.
Límites
xml admite hasta 4,000,000 de caracteres y el cuerpo de la petición hasta 10 MB. El tin debe tener
formato de RFC válido.
Los siete criterios de validación
| # | Criterio | Identificador | Se pide con |
|---|---|---|---|
| 1 | Estructura del XML | sat.xml.structure | xml |
| 2 | Vigencia del certificado | sat.certificate.validity | xml |
| 3 | Sello del emisor | sat.cfdi.sello | xml |
| 4 | Sello del SAT | sat.tfd.sello | xml |
| 5 | Estatus del comprobante | sat.cfdi.status | xml |
| 6 | Listado 69-B | sat.blacklist.69b | xml o tin |
| 7 | Listado 69-B Bis | sat.blacklist.69bbis | xml o tin |
Estructura del XML
Verifica, mediante el servicio oficial de verificación de CFDI del SAT, que el documento esté bien formado y
cumpla el Anexo 20 de su versión y los esquemas de los complementos declarados en schemaLocation. Detecta
atributos obligatorios ausentes, valores fuera de catálogo y patrones inválidos.
Estados: Valido aprobatorio · Invalido · NoDisponible · Omitido.
Vigencia del certificado
Comprueba que la fecha de emisión del CFDI esté comprendida entre NotBefore y NotAfter del certificado
del emisor. Un comprobante firmado fuera de la vigencia de su certificado carece de validez aunque el sello
verifique.
Estados: Vigente aprobatorio · Expirado · NoVigenteAun · Omitido.
Sello del emisor
Verifica que el atributo Sello corresponda a la cadena original del comprobante y a la llave pública del
certificado declarado. Confirma que el contenido no fue alterado después de firmarse y que quien firmó posee
la llave privada de ese certificado.
Estados: Valido aprobatorio · Invalido · NoDisponible · Omitido.
Sello del SAT
Verifica que el atributo SelloSAT del Timbre Fiscal Digital corresponda al certificado del SAT identificado
por NoCertificadoSAT. Confirma que el timbre fue emitido por el SAT a través de un PAC y no fue fabricado
ni modificado.
Estados: Valido aprobatorio · Invalido · NoDisponible · Omitido.
Estatus del comprobante
Consulta el servicio de consulta de CFDI del SAT y reporta el estado actual del comprobante. Es el único criterio que refleja cancelaciones posteriores a la emisión: un CFDI con todos los sellos correctos puede estar cancelado.
Estados: Vigente aprobatorio · Cancelado · NoEncontrado · NoDisponible · Omitido.
Listado 69-B
Busca el RFC del emisor en el listado completo del artículo 69-B y devuelve su situación vigente al corte
consultado. Es el criterio con más matices, porque recorre todas las etapas del procedimiento: Presunto es
una alerta de riesgo en la que los comprobantes aún conservan efectos, mientras que Definitivo implica que
no los producen y activa el plazo de 30 días hábiles para el receptor.
Estados: NoListado, Desvirtuado y SentenciaFavorable aprobatorios · Presunto · Definitivo ·
NoDisponible · Omitido.
Listado 69-B Bis
Busca el RFC del emisor en el listado del artículo 69-B Bis, sobre transmisión indebida del derecho a disminuir pérdidas fiscales. Relevante en operaciones con partes relacionadas y reestructuras corporativas.
Estados: NoListado y SentenciaFavorable aprobatorios · Definitivo · NoDisponible · Omitido.
Cómo leer un resultado
Cada elemento de la respuesta trae tres piezas:
passedes el veredicto binario del criterio:truesi el estado obtenido es aprobatorio para ese criterio.status.ides el estado concreto que produjo ese veredicto. Es el valor que conviene registrar, porque distingue casos quepassedagrupa:PresuntoyDefinitivono son lo mismo, aunque ambos denfalse.status.detailses texto libre informativo con los hechos del caso: el RFC y la fecha de corte del listado, el número de certificado, la respuesta del SAT. Puede venirnully no debe interpretarse programáticamente.
Un veredicto adverso no es un error: si la validación se ejecutó, la respuesta es 200 con passed: false.
Dos estados son transversales y no describen un hecho fiscal, sino la ejecución del criterio:
| Estado | Qué significa | Qué hacer |
|---|---|---|
NoDisponible | La fuente oficial no respondió, o no hay un corte importado del listado. El criterio no pudo determinarse. | Reintentar más tarde |
Omitido | La entrada no permitía evaluar ese criterio, por ejemplo un CFDI sin Timbre Fiscal Digital. | Revisar el comprobante enviado |
Que el xml no sea un CFDI timbrado tampoco produce un 400. Un XML mal formado devuelve Invalido en la
estructura y Omitido en el resto; un CFDI legible pero sin timbrar devuelve Omitido en estructura, ambos
sellos y estatus, mientras que la vigencia del certificado y los listados sí se evalúan. En ambos casos se
cobran todos los créditos solicitados.
Créditos de validación
El cobro se hace en créditos de validación, un saldo independiente del de timbres.
- Se consume un crédito por cada criterio solicitado, no por llamada: pedir los siete cuesta siete.
- Se cobra aunque el veredicto sea
passed: false, y aunque el estado seaNoDisponibleuOmitido. - El cobro es todo o nada y previo a la ejecución: si el saldo no alcanza para todos los criterios
solicitados, no se ejecuta ninguno, no se consume nada y la API responde
http 403 Unauthorized. - Los endpoints de catálogo (listar criterios, obtener uno por su identificador y listar sus estados) son de solo lectura y no consumen créditos.
| Escenario | HTTP | ¿Consume créditos? |
|---|---|---|
Ejecución completa, aunque algún criterio dé passed: false | 200 | Sí, uno por criterio |
Estado NoDisponible u Omitido | 200 | Sí |
Petición mal formada: falta xml y tin, vienen ambos, Base64 inválido, criterio desconocido | 400 | No |
| Saldo insuficiente | 403 | No |
| Criterio inexistente o inactivo en los endpoints de catálogo | 404 | No |
| Falla técnica durante la ejecución | 500 | Se reembolsa automáticamente |
| El cliente cancela la petición o se cierra la conexión | Sin respuesta | Sí, el consumo se conserva |
Saldo y recarga
El saldo disponible de cada persona se consulta en availableValidationBalance del recurso
personas; availableBalance es el de timbres. En el dashboard aparecen como
Validaciones disponibles y Timbres disponibles.
Los créditos se compran en la tienda en línea del dashboard y se distribuyen entre las personas de su
organización desde el catálogo de personas, o vía API con el endpoint de timbres indicando
creditType: 2. El valor 1, que es el predeterminado, transfiere timbres.
Auditar el consumo
Cada validación deja un movimiento en el mismo ledger que los timbres, consultable con GET /api/v4/stamps.
El movimiento es de tipo consumo, lleva creditType: 2 y en comments los identificadores de los criterios
cobrados, por ejemplo SAT: sat.xml.structure,sat.blacklist.69b. Eso permite reconciliar el gasto de
créditos criterio por criterio sin instrumentar nada del lado del cliente.
En las respuestas de error, el envelope incluye además un traceIdentifier que es el mismo referenceId del
movimiento: es el dato a citar al reportar un problema. Vea modelo de respuesta y
errores.
Ambiente de pruebas
En el ambiente de pruebas los resultados son ficticios y aleatorios. En https://test.fiscalapi.com la
API no consulta al SAT ni evalúa el XML que envía: devuelve un estado elegido al azar de entre los que ese
criterio admite. Por eso dos llamadas idénticas dan resultados distintos, details siempre viene null y
nunca verá NoDisponible ni Omitido. Los créditos se cobran igual. Este ambiente sirve únicamente
para conocer el contrato y probar su integración: nunca lo use como fuente de verdad fiscal ni tome una
decisión de negocio con su resultado.
Consulte ambientes para las credenciales y la URL de cada uno.
Disponible en los SDK
El feature está expuesto en los cinco SDK oficiales con la misma superficie: tres operaciones de catálogo y una de ejecución.
| SDK | Accesor | Operaciones |
|---|---|---|
| .NET | fiscalApi.SatValidations | GetTypesAsync, GetTypeByIdAsync, GetStatusesAsync, ValidateAsync |
| JavaScript / TypeScript | fiscalApi.satValidations | getTypes, getTypeById, getStatuses, validate |
| Python | fiscalapi.sat_validations | get_types, get_type_by_id, get_statuses, validate |
| Java | fiscalApi.getSatValidationService() | getTypes, getTypeById, getStatuses, validate |
| PHP | $fiscalApi->getSatValidationService() | getTypes, getTypeById, getStatuses, validate |
Los cinco exponen las constantes SatValidationTypeIds y SatValidationStatusIds; conviene usarlas en lugar
de literales. Los ejemplos por lenguaje de cada operación están en validaciones SAT; la
instalación de cada paquete, en SDKs.
Preguntas frecuentes
¿Qué diferencia hay entre validar un CFDI y timbrarlo? El timbrado certifica un comprobante en el momento de su emisión. La validación verifica, en cualquier momento posterior, que el XML siga siendo íntegro, vigente y fiscalmente efectivo: sellos, certificado, estatus en el SAT y situación del emisor en los listados del artículo 69-B.
¿Un CFDI de un emisor publicado en el listado definitivo sigue siendo válido? No produce efectos fiscales. Publicado el listado definitivo del artículo 69-B, los comprobantes del emisor se consideran, con efectos generales, sin efecto fiscal alguno, y el receptor cuenta con 30 días hábiles para acreditar la materialidad de la operación o corregir su situación fiscal.
¿Con qué frecuencia se actualizan los listados 69-B y 69-B Bis?
Fiscalapi incorpora cada publicación oficial del SAT. Cada respuesta de los criterios de listado incluye en
details la fecha de corte del listado consultado, de modo que su sistema sabe con qué información decidió.
¿Puedo ejecutar solo algunos criterios?
Sí. validationTypes indica exactamente cuáles ejecutar y solo se cobran esos. Para consultar los listados
69-B y 69-B Bis basta enviar el RFC del emisor, sin XML.