Skip to content
Documentation sections

Validator

Six queries to check a CFDI, a recipient's data and a certificate. They use validator module credits, separate from your stamping folios; validator/cfdi uses none.

Credits

EndpointValidator credits used
GET /validator/cfdiNone.
GET /validator/fiscalinfo1, only if the data passes the test.
GET /validator/lrfc1 for each RFC with a valid structure.
GET /validator/lco1 when the LCO service responds.
GET /validator/blacklist1 per query, whether or not the RFC is listed.
GET /validator/balanceNone. Returns your validator credit balance.

With no credits, the four paid ones respond HTTP 400 with code 601 and a message that says (VALIDATOR-MODULE).

A CFDI's status with the SAT

GET/validator/cfdi

Queries the SAT service with the same data as the CFDI's QR code. It tells you whether it's active or cancelled, whether it can be cancelled and where its cancellation stands.

Parameters (query)

uuidstringrequired
The CFDI's fiscal folio.
rfcemisorstringrequired
Issuer RFC. An & goes as %26.
rfcreceptorstringrequired
Recipient RFC.
totalnumberrequired
The CFDI total with a decimal point and no thousands separator: 2494.58, never 2,494.58.
curl
curl -sS -G "$FD_API/validator/cfdi" \
  -H "X-Api-Key: $FD_API_KEY" \
  --data-urlencode "uuid=6FA90F39-2D7A-4F1C-9B3E-5C1D8A0E7B42" \
  --data-urlencode "rfcemisor=EKU9003173C9" \
  --data-urlencode "rfcreceptor=XIA190128J61" \
  --data-urlencode "total=2494.58"
200
{
  "message": "La consulta se realizó exitosamente en el SAT",
  "code": "200",
  "sat_response": {
    "codigoestatus": "S - Comprobante obtenido satisfactoriamente.",
    "escancelable": "Cancelable con aceptación",
    "estado": "Cancelado",
    "estatuscancelacion": "Plazo vencido",
    "validacionefos": "200",
    "fecha_consulta": "2026-11-03 10:15:42",
    "fecha_cancelacion": null,
    "fecha_solicitud_cancelacion": "2026-10-28 09:34:50"
  }
}

sat_response

estadostring
Vigente, Cancelado or No Encontrado. A UUID the SAT doesn't know also responds HTTP 200, with No Encontrado.
escancelablestring
Cancelable sin aceptación, Cancelable con aceptación or No cancelable.
estatuscancelacionstring
En proceso, Plazo vencido, Cancelado con aceptación, Cancelado sin aceptación, Solicitud rechazada or empty.
validacionefosstring
The SAT EFOS check result (200 and 201: the issuer isn't an EFOS).
fecha_cancelacionstring | null
When the CFDI got cancelled, only if the SAT cancelled it on receiving the request. See below.
fecha_solicitud_cancelacionstring | null
When the cancellation was requested through the API, from the SAT acknowledgment.

Where the cancellation dates come from

The SAT status service returns no dates. Both come from the acknowledgment the SAT issued when the key's account cancelled the CFDI through the platform, and they're in central Mexico time.

estatuscancelacionfecha_cancelacionfecha_solicitud_cancelacion
Cancelado sin aceptaciónThe acknowledgment's: the SAT cancelled on receiving the request.The acknowledgment's.
Cancelado con aceptaciónnull: it was cancelled when your customer accepted, and the SAT doesn't publish that moment.The acknowledgment's.
Plazo vencidonull: it was cancelled when your customer's time to respond ran out.The acknowledgment's.
En proceso or Solicitud rechazadanull: it isn't cancelled.The acknowledgment's.

A recipient's tax data

GET/validator/fiscalinfo

Tests whether an RFC, its name, postal code and regime match the SAT before you invoice. To find out, it stamps a test CFDI with that data in a separate test environment: it uses neither your folios nor your CSD. The data goes in headers, with these exact names.

Headers

Rfcstringrequired
Recipient RFC, uppercase.
Nombrestringrequired
Name as it appears on their tax certificate, without the capital regime.
Codigopostalstringrequired
Postal code of their tax address.
Regimenstringrequired
Three-digit c_RegimenFiscal key.
curl
curl -sS "$FD_API/validator/fiscalinfo" \
  -H "X-Api-Key: $FD_API_KEY" \
  -H "Rfc: XIA190128J61" \
  -H "Nombre: XENON INDUSTRIAL ARTICLES" \
  -H "Codigopostal: 76343" \
  -H "Regimen: 601"
{
  "old_balance": 46,
  "new_balance": 45,
  "code": 200,
  "short": "OK",
  "message": "The fiscal information provided is correct.",
  "query_date": "2026-11-03 10:15:42"
}

When something doesn't match, short is Wrong Data and sat_code carries the SAT key (CFDI40143, CFDI40145, CFDI40147…), the same one you'd see when stamping. It's in the error matrix.

  • It can take up to 60 seconds: set that timeout in your client.
  • It only uses a credit when the data passes. A Wrong Data is free.
  • Call it from your server: the Rfc, Nombre, Codigopostal and Regimen headers aren't allowed from a browser.

RFC structure

GET/validator/lrfc

Checks that the rfc parameter has an RFC's structure (letters, a real date and the homoclave) and tells you whether it's generic, foreign, a company (12 characters) or an individual (13). It doesn't query the SAT: it doesn't confirm the RFC is registered. Use fiscalinfo for that, or let the SAT validate it when stamping.

200
{
  "code": 200,
  "data": {
    "contribuyenteRFC": "XIA190128J61",
    "sncf": false,
    "subcontratacion": false,
    "generico": false,
    "extranjero": false,
    "moral": true,
    "fisica": false
  },
  "query_date": "2026-11-03 10:15:42"
}

sncf and subcontratacion are kept for compatibility and are always false. This endpoint returns its errors with code as text: "400" for a malformed RFC and "401" for everything else (key, missing parameter or no credits).

Certificate in the LCO

GET/validator/lco

Looks up a digital seal certificate in the LCO, the certificate list the SAT publishes. Send the certificate number's 20 digits in nocertificado. data carries what the list publishes for that certificate; for example:

200
{
  "code": 200,
  "data": {
    "noCertificado": "30001000000500003416",
    "rfc": "EKU9003173C9",
    "validezObligaciones": "1",
    "estatusCertificado": "A",
    "fechaInicio": "2023-05-18T11:43:51",
    "fechaFinal": "2027-05-18T11:43:51"
  },
  "query_date": "2026-11-03 10:15:42"
}

This query depends on an external service and has no timeout of its own: set one in your client.

SAT 69-B list

GET/validator/blacklist

Looks up the rfc parameter in the article 69-B list of the CFF (taxpayers issuing vouchers for simulated transactions). If it's not there, it responds codestr: "whitelisted" and data: null. If it is, it responds codestr: "blacklisted" with the list row in data.

200
{
  "code": "201",
  "codestr": "blacklisted",
  "message": "WARNING! This RFC is BLACKLISTED",
  "data": {
    "rfc": "AAA010101AAA",
    "contribuyente": "EMPRESA DE EJEMPLO SA DE CV",
    "situacion": "Desvirtuado",
    "estado": "desvirtuado",
    "pub_sat_presuntos": "01/01/2025",
    "pub_sat_desvirtuados": "01/06/2025",
    "actualizado_en": "2026-11-03 03:15:00"
  },
  "query_date": "2026-11-03 10:15:42"
}

Validator balance

GET/validator/balance

Responds { "code": 200, "balance": 354, "query_date": "…" }. That's the validator credit balance; your stamping folios are in GET /account/balance.

Checked against the production API v5 on 2026-11-03.