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
| Endpoint | Validator credits used |
|---|---|
| GET /validator/cfdi | None. |
| GET /validator/fiscalinfo | 1, only if the data passes the test. |
| GET /validator/lrfc | 1 for each RFC with a valid structure. |
| GET /validator/lco | 1 when the LCO service responds. |
| GET /validator/blacklist | 1 per query, whether or not the RFC is listed. |
| GET /validator/balance | None. 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
/validator/cfdiQueries 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)
uuid- The CFDI's fiscal folio.
rfcemisor- Issuer RFC. An
&goes as%26. rfcreceptor- Recipient RFC.
total- The CFDI total with a decimal point and no thousands separator:
2494.58, never2,494.58.
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"{
"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
estadoVigente,CanceladoorNo Encontrado. A UUID the SAT doesn't know also responds HTTP 200, withNo Encontrado.escancelableCancelable sin aceptación,Cancelable con aceptaciónorNo cancelable.estatuscancelacionEn proceso,Plazo vencido,Cancelado con aceptación,Cancelado sin aceptación,Solicitud rechazadaor empty.validacionefos- The SAT EFOS check result (200 and 201: the issuer isn't an EFOS).
fecha_cancelacion- When the CFDI got cancelled, only if the SAT cancelled it on receiving the request. See below.
fecha_solicitud_cancelacion- 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.
| estatuscancelacion | fecha_cancelacion | fecha_solicitud_cancelacion |
|---|---|---|
| Cancelado sin aceptación | The acknowledgment's: the SAT cancelled on receiving the request. | The acknowledgment's. |
| Cancelado con aceptación | null: it was cancelled when your customer accepted, and the SAT doesn't publish that moment. | The acknowledgment's. |
| Plazo vencido | null: it was cancelled when your customer's time to respond ran out. | The acknowledgment's. |
| En proceso or Solicitud rechazada | null: it isn't cancelled. | The acknowledgment's. |
A recipient's tax data
/validator/fiscalinfoTests 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
Rfc- Recipient RFC, uppercase.
Nombre- Name as it appears on their tax certificate, without the capital regime.
Codigopostal- Postal code of their tax address.
Regimen- Three-digit c_RegimenFiscal key.
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"
}{
"old_balance": 45,
"new_balance": 45,
"type": "RequestException",
"short": "Wrong Data",
"sat_code": "CFDI40145",
"message": "CFDI40145 - El campo Nombre del receptor, debe pertenecer al nombre asociado al RFC registrado en el campo Rfc del Receptor.",
"code": 400
}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 Datais free. - Call it from your server: the
Rfc,Nombre,CodigopostalandRegimenheaders aren't allowed from a browser.
RFC structure
/validator/lrfcChecks 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.
{
"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
/validator/lcoLooks 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:
{
"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
/validator/blacklistLooks 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.
{
"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
/validator/balanceResponds { "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.