Validaciones SAT

Una validación SAT verifica un CFDI timbrado contra los servicios oficiales del SAT: la estructura del XML, la vigencia del certificado del emisor, el sello del comprobante y el del timbre, el estatus del comprobante y las listas negras de los artículos 69-B y 69-B Bis del CFF. Cada verificación es un tipo de validación que se solicita de forma independiente.

Modelo tipo de validación

El modelo tipo de validación (SatValidationType) describe una de las verificaciones que Fiscalapi puede ejecutar sobre un CFDI. Es un catálogo de solo lectura de siete tipos.

Propiedades

  • Name
    id
    Type
    string?
    Description

    Identificador del tipo de validación.

    Type
    enum:
    Values
    "sat.xml.structure""sat.certificate.validity""sat.cfdi.sello"
  • Name
    description
    Type
    string?
    Description

    Descripción de lo que verifica el tipo de validación.


Modelo resultado

El modelo resultado (SatValidationResult) es lo que devuelve la ejecución de una validación: un elemento por cada tipo solicitado, siempre en el orden del catálogo.

Propiedades

  • Name
    type
    Type
    object (SatValidationType)?

    Tipo de validación que se ejecutó.

    • Name
      id
      Type
      string?
      Description

      Identificador del tipo de validación.

    • Name
      description
      Type
      string?
      Description

      Descripción de lo que verifica el tipo de validación.

  • Name
    status
    Type
    object (SatValidationStatus)?

    Estatus obtenido al ejecutar la validación.

    • Name
      id
      Type
      string?
      Description

      Identificador del estatus. Cada tipo de validación admite solo un subconjunto de estos valores: el que devuelve listar estatus de un tipo.

      Type
      enum:
      Values
      "Valido""Vigente""NoListado"
    • Name
      description
      Type
      string?
      Description

      Descripción del estatus.

    • Name
      details
      Type
      string?
      Description

      Datos concretos del caso en texto libre, por ejemplo el número de certificado o la fecha de corte del listado consultado. Puede ser null. Es informativo: no debe interpretarse programáticamente.

  • Name
    passed
    Type
    boolean?
    Description

    true si el estatus obtenido es aprobatorio para ese tipo de validación.


GET/api/v4/sat-validations

Listar tipos de validación

Este endpoint devuelve todos los tipos de validación activos, en el orden del catálogo. No recibe parámetros y no consume créditos.

Request

GET
/api/v4/sat-validations
curl --location 'https://test.fiscalapi.com/api/v4/sat-validations' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'X-API-KEY: <api_key>'

Response

{
    "data": [
        {
            "id": "sat.xml.structure",
            "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el XML sea un documento bien formado y cumpla la estructura del Anexo 20 de su versión y la de los complementos declarados en schemaLocation. Detecta atributos obligatorios ausentes, valores fuera de catálogo y patrones inválidos."
        },
        {
            "id": "sat.certificate.validity",
            "description": "Comprueba que la fecha de emisión del CFDI esté comprendida entre NotBefore y NotAfter del certificado del emisor contenido en Certificado. Un CFDI firmado fuera de la vigencia del certificado carece de validez aunque el sello verifique."
        },
        {
            "id": "sat.cfdi.sello",
            "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el atributo Sello corresponda a la cadena original del comprobante y a la llave pública del certificado contenido en Certificado. Confirma que el contenido no fue alterado después de firmarse y que el firmante posee la llave privada de ese certificado."
        },
        {
            "id": "sat.tfd.sello",
            "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el atributo SelloSAT del TimbreFiscalDigital 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."
        },
        {
            "id": "sat.cfdi.status",
            "description": "Consulta ConsultaCFDIService del SAT con UUID, RFC emisor, RFC receptor y total, y reporta el estado actual del comprobante. Es la única validación que refleja cancelaciones posteriores a la emisión."
        },
        {
            "id": "sat.blacklist.69b",
            "description": "Busca el RFC del emisor en el listado completo del artículo 69-B CFF y devuelve la situación vigente. Definitivo implica que los CFDI del emisor no producen efectos fiscales y activa el plazo de 30 días hábiles para el receptor."
        },
        {
            "id": "sat.blacklist.69bbis",
            "description": "Busca el RFC del emisor en el listado del artículo 69-B Bis CFF (transmisión indebida del derecho a disminuir pérdidas fiscales) y devuelve la situación vigente. Relevante en operaciones con partes relacionadas y reestructuras."
        }
    ],
    "succeeded": true,
    "message": "",
    "details": "",
    "httpStatusCode": 200
}

GET/api/v4/sat-validations/<id>

Obtener tipo de validación por ID

Este endpoint te permite obtener un tipo de validación por su ID. El ID contiene puntos y se envía tal cual, sin codificar. Devuelve 404 si el tipo no existe o está inactivo. No consume créditos.

Request

GET
/api/v4/sat-validations/<id>
curl --location 'https://test.fiscalapi.com/api/v4/sat-validations/sat.xml.structure' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'X-API-KEY: <api_key>'

Response

{
    "data": {
        "id": "sat.xml.structure",
        "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el XML sea un documento bien formado y cumpla la estructura del Anexo 20 de su versión y la de los complementos declarados en schemaLocation. Detecta atributos obligatorios ausentes, valores fuera de catálogo y patrones inválidos."
    },
    "succeeded": true,
    "message": "",
    "details": "",
    "httpStatusCode": 200
}

GET/api/v4/sat-validations/<id>/statuses

Listar estatus de un tipo

Este endpoint devuelve los estatus que un tipo de validación puede tomar al ejecutarse: primero los aprobatorios y, dentro de cada grupo, ordenados alfabéticamente por id. Es de solo lectura: no ejecuta la validación ni consume créditos. La respuesta no incluye el campo passed; esa correspondencia está en modelo resultado. Devuelve 404 si el tipo no existe o está inactivo.

Request

GET
/api/v4/sat-validations/<id>/statuses
curl --location 'https://test.fiscalapi.com/api/v4/sat-validations/sat.xml.structure/statuses' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'X-API-KEY: <api_key>'

Response

{
    "data": [
        {
            "id": "Valido",
            "description": "Documento bien formado que cumple el XSD del Anexo 20 de su versión y los XSD de los complementos declarados en schemaLocation, según el verificador del SAT."
        },
        {
            "id": "Invalido",
            "description": "El documento no está bien formado o el verificador del SAT reporta que incumple el XSD del Anexo 20 o el de alguno de sus complementos."
        },
        {
            "id": "NoDisponible",
            "description": "El verificador del SAT no respondió o rechazó la consulta; la estructura no pudo determinarse y debe reintentarse."
        },
        {
            "id": "Omitido",
            "description": "No se evaluó porque el CFDI no contiene el complemento TimbreFiscalDigital; el verificador del SAT solo evalúa comprobantes timbrados."
        }
    ],
    "succeeded": true,
    "message": "",
    "details": "",
    "httpStatusCode": 200
}

POST/api/v4/sat-validations

Validar

Este endpoint ejecuta las validaciones solicitadas y devuelve un resultado por cada tipo. Los resultados vuelven en el orden del catálogo, no en el orden en que los solicitaste.

Modelo

  • Name
    xml
    Type
    string?
    Description

    CFDI timbrado completo, codificado en Base64. Excluyente con tin. Con xml puedes solicitar cualquier tipo de validación. Las listas negras consultan el RFC del nodo cfdi:Emisor. Máximo 4,000,000 de caracteres; el tamaño máximo del cuerpo de la petición es de 10 MB.

  • Name
    tin
    Type
    string?
    Description

    RFC a consultar. Excluyente con xml. Con tin solo puedes solicitar listas negras (sat.blacklist.69b y sat.blacklist.69bbis). El RFC no se contrasta contra ningún CFDI: la respuesta refleja únicamente la situación del RFC enviado.

  • Name
    validationTypes
    Type
    array of strings
    required
    Description

    Tipos de validación a ejecutar. No admite elementos vacíos ni duplicados, y todos deben existir y estar activos.

    Type
    enum:
    Values
    "sat.xml.structure""sat.certificate.validity""sat.cfdi.sello"

En el ambiente de pruebas los resultados son ficticios y aleatorios. En https://test.fiscalapi.com la API no consulta al SAT ni a su verificador, y ni siquiera evalúa el XML que envías: devuelve un estatus elegido al azar de entre los que ese tipo admite. Por eso dos llamadas idénticas dan resultados distintos, details siempre viene null y nunca verás NoDisponible ni Omitido, ni aun enviando un XML inválido o sin timbrar. Los créditos se cobran igual. Este ambiente sirve únicamente para conocer el contrato y probar tu integración: nunca lo uses como fuente de verdad fiscal ni tomes una decisión de negocio con su resultado. Para eso, producción. Los details que ves en los ejemplos de esta página provienen de producción.

Un resultado adverso no es un error: si la validación se ejecutó, la respuesta es 200 con passed: false. Una petición mal formada devuelve 400 y no consume créditos; un saldo insuficiente devuelve 403 con Créditos de validación insuficientes: se requieren N y el saldo es M y tampoco consume créditos, porque el cobro ocurre después de validar la petición. Si la ejecución falla por un problema técnico (500), el débito se reembolsa automáticamente como un movimiento de tipo reverso en el ledger de timbres. En cambio, si cancelas la petición o se cierra la conexión, el consumo se conserva y no recibes resultados: para entonces las consultas al SAT ya se pagaron.

Que el xml no sea un CFDI timbrado tampoco es un 400: la respuesta es 200, se cobran todos los créditos solicitados y cada tipo reporta lo que pudo determinar. Un XML mal formado, o cuya raíz no es cfdi:Comprobante, devuelve Invalido en sat.xml.structure (con el error del lector en details) y Omitido en los demás tipos. Un CFDI legible pero sin timbrar devuelve Omitido en sat.xml.structure, sat.cfdi.sello, sat.tfd.sello y sat.cfdi.status, mientras que sat.certificate.validity y las listas negras sí se evalúan.

Consulta errores y modelo de respuesta.

Request

POST
/api/v4/sat-validations
curl --location 'https://test.fiscalapi.com/api/v4/sat-validations' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api_key>' \
--data-raw '{
  "xml": "<xml-timbrado-en-base64>",
  "validationTypes": [
    "sat.xml.structure",
    "sat.certificate.validity",
    "sat.cfdi.sello",
    "sat.tfd.sello",
    "sat.cfdi.status",
    "sat.blacklist.69b",
    "sat.blacklist.69bbis"
  ]
}'

Response

{
    "data": [
        {
            "type": {
                "id": "sat.xml.structure",
                "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el XML sea un documento bien formado y cumpla la estructura del Anexo 20 de su versión y la de los complementos declarados en schemaLocation. Detecta atributos obligatorios ausentes, valores fuera de catálogo y patrones inválidos."
            },
            "status": {
                "id": "Valido",
                "description": "Documento bien formado que cumple el XSD del Anexo 20 de su versión y los XSD de los complementos declarados en schemaLocation, según el verificador del SAT.",
                "details": null
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.certificate.validity",
                "description": "Comprueba que la fecha de emisión del CFDI esté comprendida entre NotBefore y NotAfter del certificado del emisor contenido en Certificado. Un CFDI firmado fuera de la vigencia del certificado carece de validez aunque el sello verifique."
            },
            "status": {
                "id": "Vigente",
                "description": "La fecha de emisión del CFDI está comprendida entre NotBefore y NotAfter del certificado del emisor.",
                "details": "Emisión 2026-08-18T11:56:42 (hora de México); certificado 00001000000720012093 de MAX0611157H8 vigente del 2025-11-04 al 2029-11-04"
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.cfdi.sello",
                "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el atributo Sello corresponda a la cadena original del comprobante y a la llave pública del certificado contenido en Certificado. Confirma que el contenido no fue alterado después de firmarse y que el firmante posee la llave privada de ese certificado."
            },
            "status": {
                "id": "Valido",
                "description": "El verificador del SAT confirma que el atributo Sello verifica contra la cadena original del comprobante con la llave pública del certificado del emisor.",
                "details": null
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.tfd.sello",
                "description": "Verifica mediante el servicio oficial de verificación de CFDI del SAT que el atributo SelloSAT del TimbreFiscalDigital 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."
            },
            "status": {
                "id": "Valido",
                "description": "El verificador del SAT confirma que el atributo SelloSAT verifica contra la cadena original del TimbreFiscalDigital con el certificado del SAT identificado por NoCertificadoSAT.",
                "details": null
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.cfdi.status",
                "description": "Consulta ConsultaCFDIService del SAT con UUID, RFC emisor, RFC receptor y total, y reporta el estado actual del comprobante. Es la única validación que refleja cancelaciones posteriores a la emisión."
            },
            "status": {
                "id": "Vigente",
                "description": "ConsultaCFDIService reporta el comprobante como Vigente; se incluyen EsCancelable y EstatusCancelacion devueltos por el SAT.",
                "details": "Estado Vigente; CodigoEstatus S - Comprobante obtenido satisfactoriamente.; EsCancelable Cancelable con aceptación; EstatusCancelacion "
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.blacklist.69b",
                "description": "Busca el RFC del emisor en el listado completo del artículo 69-B CFF y devuelve la situación vigente. Definitivo implica que los CFDI del emisor no producen efectos fiscales y activa el plazo de 30 días hábiles para el receptor."
            },
            "status": {
                "id": "NoListado",
                "description": "El RFC del emisor no figura en ninguna etapa del listado completo del artículo 69-B al corte indicado.",
                "details": "RFC MAX0611157H8; corte del listado 2026-07-31"
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.blacklist.69bbis",
                "description": "Busca el RFC del emisor en el listado del artículo 69-B Bis CFF (transmisión indebida del derecho a disminuir pérdidas fiscales) y devuelve la situación vigente. Relevante en operaciones con partes relacionadas y reestructuras."
            },
            "status": {
                "id": "NoListado",
                "description": "El RFC del emisor no figura en ninguna etapa del listado del artículo 69-B Bis al corte indicado.",
                "details": "RFC MAX0611157H8; corte del listado 2026-06-05"
            },
            "passed": true
        }
    ],
    "succeeded": true,
    "message": "",
    "details": "",
    "httpStatusCode": 200
}

POST/api/v4/sat-validations

Validar solo por RFC

Cuando solo necesitas saber si un RFC está en las listas negras del SAT, envía tin en lugar de xml. Es el mismo endpoint y el mismo modelo, pero en esta modalidad únicamente se admiten sat.blacklist.69b y sat.blacklist.69bbis: solicitar cualquier otro tipo devuelve 400. Consume un crédito por cada tipo solicitado, igual que la validación con xml.

Rige la misma advertencia que en validar: en el ambiente de pruebas el resultado es ficticio y aleatorio, y no debe usarse para decidir nada.

Request

POST
/api/v4/sat-validations
curl --location 'https://test.fiscalapi.com/api/v4/sat-validations' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api_key>' \
--data-raw '{
  "tin": "XAXX010101000",
  "validationTypes": [
    "sat.blacklist.69b",
    "sat.blacklist.69bbis"
  ]
}'

Response

{
    "data": [
        {
            "type": {
                "id": "sat.blacklist.69b",
                "description": "Busca el RFC del emisor en el listado completo del artículo 69-B CFF y devuelve la situación vigente. Definitivo implica que los CFDI del emisor no producen efectos fiscales y activa el plazo de 30 días hábiles para el receptor."
            },
            "status": {
                "id": "NoListado",
                "description": "El RFC del emisor no figura en ninguna etapa del listado completo del artículo 69-B al corte indicado.",
                "details": "RFC XAXX010101000; corte del listado 2026-07-31"
            },
            "passed": true
        },
        {
            "type": {
                "id": "sat.blacklist.69bbis",
                "description": "Busca el RFC del emisor en el listado del artículo 69-B Bis CFF (transmisión indebida del derecho a disminuir pérdidas fiscales) y devuelve la situación vigente. Relevante en operaciones con partes relacionadas y reestructuras."
            },
            "status": {
                "id": "NoListado",
                "description": "El RFC del emisor no figura en ninguna etapa del listado del artículo 69-B Bis al corte indicado.",
                "details": "RFC XAXX010101000; corte del listado 2026-06-05"
            },
            "passed": true
        }
    ],
    "succeeded": true,
    "message": "",
    "details": "",
    "httpStatusCode": 200
}

POST/api/v4/stamps

Transferir créditos de validación

Los créditos de validación se mueven por el endpoint de timbres, con el campo creditType en 2. Con 1 (el valor por omisión) se transfieren timbres. Los saldos nunca se mezclan.

Modelo

  • Name
    fromPersonId
    Type
    string
    required
    Description

    ID de la persona origen que envía los créditos. Debe tener saldo suficiente de validaciones.

  • Name
    toPersonId
    Type
    string
    required
    Description

    ID de la persona destino que recibe los créditos.

  • Name
    amount
    Type
    integer | number
    required
    Description

    Cantidad de créditos a transferir. Debe ser mayor que cero.

  • Name
    comments
    Type
    string?
    Description

    Comentarios opcionales sobre la transferencia. Máximo 100 caracteres.

  • Name
    creditType
    Type
    integer | number?
    expandible
    Description

    Tipo de crédito a transferir.

    Type
    enum:
    Values
    12
    Default:
    1

El saldo resultante se consulta en availableValidationBalance del recurso personas, independiente de availableBalance (timbres).

Request

POST
/api/v4/stamps
curl --location 'https://test.fiscalapi.com/api/v4/stamps' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api_key>' \
--data-raw '{
  "fromPersonId": "1",
  "toPersonId": "bef56254-0892-4558-95c3-f9c8729e4b0e",
  "amount": 10,
  "comments": "Créditos para validar CFDI",
  "creditType": 2
}'

Response

{
    "data": true,
    "succeeded": true,
    "message": "",
    "details": "",
    "httpStatusCode": 200
}

¿Le resultó útil esta página?