Skip to main content
Every error is application/problem+json (RFC 9457) with agent-first extensions:
{
  "type": "https://errors.invoiceapi.mx/cfdi_invalid_rfc",
  "title": "Receptor RFC failed SAT validation",
  "status": 422,
  "detail": "RFC 'XAXX010101ABC' is not registered at the SAT (CFDI40**).",
  "code": "cfdi.receptor_rfc_not_registered",
  "remediation": "Ask the customer for their Constancia de Situación Fiscal and use the RFC exactly as printed.",
  "pac": { "provider": "pac", "codigo": "402", "mensaje": "..." },
  "request_id": "req_..."
}
Switch on code (stable across releases), show remediation to the user or feed it to an agent, and log request_id. When the failure came from the PAC, the pac object carries the raw PAC/SAT codigo/mensaje. Every problem body also carries a doc_url that deep-links to the matching row below (dots in the code become dashes in the anchor).

Complete error catalog (141 codes)

Every stable code the API can emit, generated by statically scanning the source (a build-time drift guard fails if any code is missing). HTTP is the status the code surfaces with. Anchor = code with dots replaced by dashes, matching the doc_url in every problem body.
codeHTTPTitleRemediation
auth.key_revoked401API key revokedMint a replacement key with POST /v1/api_keys and update your credentials.
auth.unauthorized401Authentication requiredSend Authorization: Bearer sk_test_... (or sk_live_…) with a valid API key.
cancel.already_cancelled422Previously cancelledThe CFDI was already cancelled. Treat as cancelled — no further action needed.
cancel.date_after_declaration422Request date after declaration dateThe cancellation request date is after the SAT declaration date for the period. Cancellation is no longer permitted for this CFDI.
cancel.global_invoice_deadline422Past the global-invoice deadlineThe deadline to cancel this factura global has passed. This CFDI can no longer be cancelled.
cancel.in_process422Cancellation in processThe cancellation is in process awaiting the receptor’s response. Keep polling the status; it resolves within 72 business hours.
cancel.motivo_invalid422Motivo not validThe motivo is not valid. Use one of 01-04 per the SAT catalog.
cancel.motivo_missing422Motivo not specified or invalidThe cancellation motivo is missing or invalid. Provide a valid motivo 01-04 (01 requires a substitute folio).
cancel.no_acuse422CFDI not cancelled — acuse unavailableThe acuse cannot be retrieved because the CFDI is not cancelled (or was not cancelled through this service). Confirm the cancellation completed before requesting the acuse.
cancel.not_applicable422Folio not applicable to cancellationThis folio cannot be cancelled (e.g. it is referenced by another live CFDI). Query related CFDIs to find the blocker before retrying.
cancel.not_cancellable422Not cancellableThe SAT reports this CFDI as “No Cancelable” (e.g. it is referenced by other live documents). Query related CFDIs to find and resolve the blocker.
cancel.not_primary_sector422UUID is not a Sector Primario CFDIThe requested cancellation flow requires a Sector Primario CFDI, which this is not. Use the standard cancellation motivo for this document type.
cancel.outside_annual_declaration422Outside the annual declaration windowThe cancellation falls outside the allowed annual declaration window and is no longer permitted.
cancel.relation_invalid422Relation invalidThe declared relation is invalid. Verify the related CFDI and relationship type.
cancel.request_received422Cancellation request receivedThe SAT received the cancellation request. If the CFDI is “cancelable con aceptación”, the receptor has 72 business hours to accept or reject; poll the status until it resolves.
cancel.rfc_mismatch422Emisor RFC does not matchThe emisor RFC on the request does not match the CFDI. Send the cancellation from the RFC that issued the CFDI, signed with that RFC’s CSD.
cancel.sat_service_unavailable502SAT error during queryThe SAT returned an error during the status query. Retry with backoff.
cancel.substitution_folio_invalid422Substitute folio not validThe substitute folio is not valid. For motivo 01, supply the UUID of a valid, already-stamped replacement CFDI.
cancel.substitution_folio_not_required422Substitute folio not requiredThis motivo does not require a substitute folio. Remove folioSustitucion.
cancel.user_invalid422User not valid for cancellationThe user is not authorized for this cancellation. Verify credentials and that the signing CSD belongs to the emisor RFC.
cancel.uuid_not_found422Folio fiscal does not existThe UUID does not exist at the SAT. Verify the folio fiscal is correct and that the CFDI was actually stamped in this environment (test vs live).
cfdi.csd_expired422Invalid invoiceRenew the CSD at the SAT portal; an expired/not-yet-valid certificate cannot stamp.
cfdi.csd_rfc_mismatch422Invalid invoiceUse the CSD (certificado de sello digital) issued to the emitter RFC.
cfdi.emisor_not_in_lco422Taxpayer not in LCO / obligations negativeThe emitter is not in the SAT’s Lista de Contribuyentes Obligados or its fiscal obligations validation is negative. The taxpayer must resolve their status with the SAT (e.g. active CSD, up-to-date obligations) before stamping.
cfdi.fecha_in_future422Invalid invoiceGenerate Fecha at stamp time; it must not be in the future.
cfdi.fecha_out_of_range422Fecha outside the allowed windowThe CFDI Fecha is outside the SAT-allowed window (must be within roughly the last 72 hours and not in the future, in Mexico time). Regenerate the CFDI with a fresh timestamp and re-sign it (the sello changes with Fecha).
cfdi.fecha_too_old422Invalid invoiceRe-issue the invoice; CFDI must be stamped within 72h of Fecha.
cfdi.invalid_expression422Invalid expressionThe status query expression is invalid. Check the Total formatting (decimals must match the CFDI exactly) and the RFCs.
cfdi.invalid_fecha422Invalid invoicePass date as ‘YYYY-MM-DDTHH:mm:ss’ (SAT forbids a timezone suffix).
cfdi.invalid_input422Invalid invoiceFix every field listed in errors and resubmit. See /openapi.json for the schema.
cfdi.malformed_sello422Malformed selloThe Sello attribute is not valid base64 or has the wrong length. Recompute the sello: RSA-SHA256 over the cadena original, base64-encoded, using the emitter CSD private key.
cfdi.malformed_xml422Malformed CFDI XMLThe CFDI XML is not well-formed or violates the SAT schema. Rebuild the XML — check element order, required attributes, and that special characters are escaped.
cfdi.missing_tax_rate422Invalid invoiceProvide rate (e.g. 0.16) for Tasa/Cuota taxes.
cfdi.missing_uso422Invalid invoiceSet use at invoice level or customer.use.
cfdi.no_tfd422Invalid invoiceOnly stamped CFDIs (with a TFD) have a TFD cadena.
cfdi.not_a_csd422Invalid invoiceSign CFDIs with the CSD; the FIEL is only for descarga masiva.
cfdi.not_comprobante422Invalid invoicePass a CFDI 4.0 Comprobante XML.
cfdi.not_found422Comprobante not foundThe comprobante was not found at the SAT. Verify the UUID and that emisor RFC, receptor RFC and Total exactly match the CFDI.
cfdi.objeto_imp_02_without_taxes422Invalid invoiceProvide at least one tax for this item, or set tax_object to ‘01’ (no objeto de impuesto).
cfdi.objeto_imp_dr_02_without_taxes422Invalid invoiceProvide at least one tax on the related document, or set its tax_object to ‘01’.
cfdi.parse_error422Invalid invoiceProvide a well-formed CFDI XML string.
cfdi.pdf_dependencies_missing422Invalid invoiceInstall the optional PDF peer dependencies (the CFDI PDF renderer and @xmldom/xmldom) on the server.
cfdi.pdf_requires_stamp422Invalid invoiceStamp the CFDI with the PAC first; the PDF shows the fiscal folio (UUID).
cfdi.retencion_exento422Invalid invoiceUse factor Tasa or Cuota for withholdings, or make it a traslado.
cfdi.sello_injection_failed422Invalid invoiceEnsure the XML is a well-formed CFDI 4.0 Comprobante.
cfdi.sello_mismatch422Sello does not matchThe sello does not correspond to the CFDI content or certificate. This means the cadena original was built incorrectly or a different key signed it. Regenerate the cadena original from the final XML and re-sign with the matching CSD private key.
cfdi.status_indeterminate502Indeterminate stateThe SAT could not determine the state. Retry the status query later.
cfdi.unknown_currency422Invalid invoiceUse a valid ISO 4217 currency code present in c_Moneda.
connect.account_disabled403Connected account disabledRe-enable the account via PATCH /v1/accounts/:id {“disabled”: false}.
connect.account_not_authorized403Not a connected account of this platformCreate the connected account with POST /v1/accounts (using your platform key, no Invoice-Account header), then pass its id as Invoice-Account.
connect.nesting_not_allowed403Connected accounts cannot own connected accountsCreate connected accounts from the top-level platform organization.
connect.not_supported_here400Acting as a connected account is not supported hereDrop the Invoice-Account header. Manage API keys with your platform key directly.
dashboard.email_in_use409Email already registeredSign in at /signin, or use a different email.
dashboard.invalid_credentials401Invalid email or passwordCheck your credentials and try again.
dashboard.pages_unavailable503Dashboard pages unavailableDeploy the web/ assets alongside the API, then retry.
dashboard.session_required401Sign in requiredSign in at /signin to obtain a session cookie.
dashboard.too_many_attempts429Too many sign-in attemptsWait 15 minutes before trying again.
download.fiel_required422Fiscal profile has no FIELUpload the FIEL to the profile via PATCH /v1/fiscal_profiles/:id (fiel.cer_base64, fiel.key_base64, fiel.password), or sign the carta manifiesto with an inline FIEL via POST /v1/fiscal_profiles/:id/manifest, then retry.
download.invalid_range422Invalid date rangeProvide date_from <= date_to.
download.no_request_idjobDownload has no SAT request idThe solicitud never registered with the PAC — create the download again.
download.poll_timeoutjobDownload gave up waiting for the PACThe SAT package was not ready within the polling window. Create a new download, and fragment very large date ranges.
download.request_failed502SAT descarga masiva request failed
download.unknown_errorjobDownload failed (unclassified)Read the download error.message; if it looks transient, create a new download for the same range.
fiscal_profile.csd_expired422CSD is expired or not yet validRenew the CSD at the SAT portal (Certificados de Sello Digital) and register the new pair. An expired certificate cannot stamp live CFDIs.
fiscal_profile.csd_is_fiel422FIEL supplied where a CSD is requiredRegister the CSD under csd (used to sign CFDIs). If you also have a FIEL for descarga masiva, send it under fiel.
fiscal_profile.csd_rfc_mismatch422Rotated CSD belongs to a different RFCRotate to a CSD issued to the same RFC. To register a different taxpayer, create a new fiscal_profile.
fiscal_profile.fiel_required422A FIEL is required to sign the manifiestoSend the FIEL under fiel: { cer_base64, key_base64, password } in this request, or register it on the profile first.
fiscal_profile.in_use409Fiscal profile is in useA fiscal profile with issued invoices is retained for tax-record integrity. Rotate its CSD instead of deleting, or delete dependent records first.
fiscal_profile.invalid_csd422Invalid CSD certificate or passwordVerify cer_base64 is the .cer, key_base64 is the .key, and password is the private-key passphrase (clave privada). Re-download the CSD from the SAT if unsure.
fiscal_profile.invalid_fiel422Invalid FIEL certificate or passwordVerify the FIEL (e.firma) files and password; it is only used for descarga masiva.
fiscal_profile.invalid_metadata_json422metadata is not valid JSONSend metadata as a JSON string, e.g. metadata={“order_id”:“123”}. Keys and values must be strings.
idempotency.key_processing409A request with this Idempotency-Key is still being processedRetry once the in-flight request with this Idempotency-Key completes.
idempotency.key_reuse409Idempotency-Key reused with a different request bodyReuse an Idempotency-Key only for byte-identical retries; use a fresh key for a new request.
internal.error500Internal server error
invoice.already_stamped409Invoice already stamped
invoice.cancellation_in_progress409Cancellation already requested
invoice.cancellation_rejected422Cancellation rejectedCheck the UUID is vigente and the motivo/substitute are correct; retrieve the acuse for details.
invoice.folio_contention409Could not assign a folioRetry the request; concurrent invoice creation on this serie is heavy.
invoice.folio_taken409Folio already used
invoice.no_xml422Invoice has no XML to stampRecreate the invoice; the signed XML is missing.
invoice.not_stampable409Invoice cannot be stamped
invoice.not_stamped409Only stamped invoices can be cancelled
invoice.pdf_requires_stamp409PDF is only available for stamped invoices
invoice.profile_missing_csd422Fiscal profile has no CSDUpload the CSD (.cer + .key + password) to the fiscal profile before issuing invoices.
invoice.substitute_not_stamped422Substitute invoice is not stampedStamp the replacement invoice before referencing it as a substitute.
invoice.substitute_required422Substitute invoice requiredPass substitute_invoice_id pointing to the stamped CFDI that replaces this one, or use motivo ‘02’.
invoice.xml_requires_stamp409XML is only available for stamped invoices
manifest.email_required422An email is required for the manifiestoProvide email in the request or set the MANIFEST_EMAIL config default.
manifiesto.already_signed422Contrato firmado previamenteThe carta manifiesto was already signed for this RFC — no action needed. The profile is authorized for CFDI certification.
manifiesto.bad_request422Petición inválida o parámetros incorrectosThe request was missing or had incorrect parameters (cert, key, keyPass, correo).
manifiesto.bad_sello422Sello del emisor mal formado o inválidoThe FIEL sello could not be validated. Re-download the FIEL (e.firma) from the SAT and try again.
manifiesto.certificate_error422Error en el certificadoThere was an error with the certificate. Verify the FIEL files and password, then retry.
manifiesto.certificate_not_sat422El certificado del emisor no fue emitido por el SATThe certificate was not issued by the SAT. Upload the taxpayer’s real FIEL/e.firma certificate.
manifiesto.certificate_not_valid422El certificado del emisor no es válidoThe FIEL certificate is not valid (expired or revoked). Renew the e.firma at the SAT and retry.
manifiesto.contract_not_valid422El contrato no es válidoThe signing service reports the signing contract is not valid. Contact support.
manifiesto.invalid_certificate422Certificado del emisor mal formado o inválidoThe FIEL certificate is malformed or invalid. Ensure cert is the .cer of a current SAT e.firma (not a CSD) and key is its matching .key.
manifiesto.invalid_credentials422Usuario, contraseña o contrato del asociado inválidoThe manifiesto signing service rejected the request credentials. Verify the FIEL password and that the account is provisioned for manifiesto signing.
manifiesto.invalid_response502Manifiesto SOAP response had no <return> payloadThe signing service returned an unexpected manifiesto response shape. Retry; if it persists, contact support.
manifiesto.malformed_contract422Contrato mal formadoThe manifiesto contract payload was malformed. Contact support.
manifiesto.malformed_xml422XML mal formadoThe signing service could not parse the request. Retry; if it persists, contact support.
manifiesto.network_error502Manifiesto signing request failedThe manifiesto signing request could not reach the signing service. Retry with backoff.
manifiesto.provider_error502Error al procesar la firma del contratoThe signing service hit an internal error signing the manifiesto. Retry with backoff; if it persists, contact support.
manifiesto.signed422Firma exitosa
manifiesto.xml_generation_error502Error al generar el xmlThe signing service failed to generate the signed XML. Retry with backoff; if it persists, contact support.
org.bootstrap_disabled403Organization bootstrap is disabledEnable ALLOW_ORG_BOOTSTRAP or provision organizations out-of-band.
pac.auth_failed422PAC credentials invalidThe stamping-service credentials were rejected. Do NOT retry — repeated failures can lock the account. This is a server-side configuration issue: contact support so the environment credentials can be verified (test and live credentials are separate).
pac.certificate_invalid422Certificate invalidThe certificate is invalid. Verify the emitter CSD is current and matches the emitter RFC, then re-register it.
pac.certificate_revoked422Certificate revoked or expiredThe emitter CSD is revoked or outside its validity window. The taxpayer must obtain a new Certificado de Sello Digital from the SAT and re-register it on the fiscal profile. Do not retry with the same certificate.
pac.contract_invalid422Contract invalid or expiredThe stamping account is not found, is expired, or has no available stamping credits. This is a server-side account issue: contact support to renew the account or top up stamp credits.
pac.duplicate422Comprobante already existsThis exact comprobante was already stamped (SAT forbids stamping identical CFDIs twice). Treat as a success-replay: use the previously stamped UUID/XML rather than re-stamping. This is the idempotency path — surface the prior stamp to the caller.
pac.internal_error502PAC internal errorThe stamping service reported a transient internal error. Retry with backoff. If it persists, the CFDI was almost certainly NOT stamped — safe to resubmit (idempotency guards against duplicates).
pac.invalid_parameter422Invalid or missing parameterA required parameter was missing or malformed (also returned for a malformed JSON body). Do not retry unchanged — inspect the request payload against the timbrarCfdi contract.
pac.maintenance502PAC offline for maintenanceThe stamping service is temporarily offline for maintenance. Retry with backoff after a short delay.
pac.no_default_certificate422No default certificate for cancellationNo CSD was available to sign the cancellation. Provide the emitter CSD (cerPem/keyPem/keyPassword) on the cancel request, since cancellations are signed.
pac.ok422Comprobante foundNo action needed — the comprobante was found.
pac.query_incomplete502General error, query not completedThe status query did not complete. Retry with backoff.
pac.unknown422Unmapped PAC/SAT codeThe stamping service returned a code not in our mapping. Inspect the pac message; treat as a definitive failure unless it is clearly transient.
rate_limit.exceeded429Too many requestsBack off and retry after the number of seconds in the Retry-After header; batch work or lower your request rate.
request.error500Request error
request.invalid_date422Invalid date filterPass ${field} as an ISO-8601 date or datetime, e.g. 2026-07-10 or 2026-07-10T00:00:00Z.
request.invalid_expand422Invalid expand parameterUse only the expand values the endpoint documents (e.g. fiscal_profile). Remove unsupported values.
request.invalid_pagination422Conflicting pagination cursorsPass only one cursor: starting_after for the next (older) page, or ending_before for the previous (newer) page.
request.invalid_version400Unknown API versionSend a supported version in the Invoice-Version header, or omit it to use the current version.
request.method_not_allowed405Method not allowed
request.validation_failed422Request validation failedFix the fields listed in errors and resubmit. See /openapi.json for the schema.
resource.not_found404Resource not foundVerify the id and that you are using the matching-mode key (a test id needs a test key, a live id needs a live key).
sat.download_accepted422Download request acceptedNo action needed — poll the request status until packages are ready.
sat.download_duplicate422Duplicate requestAn identical request already exists. Reuse the existing request’s id, or vary the date range to create a distinct request.
sat.download_expiredjobSAT marked the solicitud as expiredPackage URLs expire quickly — create a new download for the same range.
sat.download_generation_error503Request generation errorThe stamping service failed to generate the SAT request. Retry with backoff; if it persists, verify the FIEL, dates and RFC.
sat.download_no_data422No data for the filtersThe SAT found no CFDIs for these filters — this is a terminal, successful, empty result. Do not retry; the range simply has no documents.
sat.download_package_not_found422Package not foundThe requested package was not found — its download URL likely expired (URLs live ~5 minutes). Re-poll the request status to re-mint the package URLs and download immediately.
sat.download_packaging_error503Packaging errorThe SAT failed to package the result. Retry the status poll; if it persists, re-issue the request with a smaller date range.
sat.download_rejectedjobSAT rejected the solicitudVerify the FIEL matches the requesting RFC and role (issued/received); a mismatch yields a SAT “tercero no autorizado” rejection.
sat.download_request_limit422Lifetime request limit reachedSAT allows at most 2 lifetime requests with identical parameters. Do NOT retry the identical query — fragment or vary the date range (e.g. split the month into weeks) to make a distinct request.
sat.download_too_large422Result exceeds SAT size capThe request exceeds the SAT cap (200,000 XMLs / 1,000,000 metadata records). Fragment the date range into smaller windows and issue separate requests.
sat.download_unauthorized422Third party not authorizedSAT “tercero no autorizado”: the FIEL does not match the requested RFC. Ensure the FIEL PFX belongs to the RFC being downloaded and that side (issued/received) matches that RFC’s role.
sat.download_uncontrolled_error503Uncontrolled errorAn uncontrolled error occurred on the descarga masiva service. Retry with backoff; if it persists, contact support.
validation.empty_xml400Decoded XML is emptyProvide base64-encoded CFDI XML in xml_base64, or send raw XML with Content-Type application/xml.
webhook.event_type_not_enabled422Endpoint does not subscribe to this event typeSubscribe the endpoint to this event type (or a matching wildcard) via PATCH /v1/webhook_endpoints/:id.
webhook.https_required400Webhook URL must use https in live modeUse an https:// URL, or a sk_test_ key for http:// endpoints in development.

PAC / SAT numeric code mapping

Source of truth: src/pac/error-map.ts. Every numeric PAC/SAT code below normalizes to a stable code. Retryable means a transient failure safe to retry with backoff (idempotency guards against duplicate stamps); non-retryable codes require a change before resubmitting.

Timbrado (stamping)

Returned by POST /v1/invoices and POST /v1/invoices/:id/stamp. Code 307 (duplicate) is NOT surfaced as an error — it is resolved as a success-replay of the prior stamp.
PAC/SAT codeOur codeRetryableRemediation
0pac.oknoNo action needed — the CFDI was stamped.
1pac.auth_failednoThe stamping-service credentials were rejected. Do NOT retry — repeated failures can lock the account. This is a server-side configuration issue: contact support so the environment credentials can be verified (test and live credentials are separate).
2pac.contract_invalidnoThe stamping account is not found, is expired, or has no available stamping credits. This is a server-side account issue: contact support to renew the account or top up stamp credits.
3pac.invalid_parameternoA required parameter was missing or malformed (also returned for a malformed JSON body). Do not retry unchanged — inspect the request payload against the timbrarCfdi contract.
4pac.internal_erroryesThe stamping service reported a transient internal error. Retry with backoff. If it persists, the CFDI was almost certainly NOT stamped — safe to resubmit (idempotency guards against duplicates).
5pac.maintenanceyesThe stamping service is temporarily offline for maintenance. Retry with backoff after a short delay.
20pac.no_default_certificatenoThe PAC has no default CSD for this user (only relevant when relying on CALCULAR_SELLO). This API signs locally and embeds the certificate, so this indicates a misconfiguration — ensure the CFDI carries a valid NoCertificado/Certificado and you are not sending CALCULAR_SELLO.
301cfdi.malformed_xmlnoThe CFDI XML is not well-formed or violates the SAT schema. Rebuild the XML — check element order, required attributes, and that special characters are escaped.
302cfdi.malformed_sellonoThe Sello attribute is not valid base64 or has the wrong length. Recompute the sello: RSA-SHA256 over the cadena original, base64-encoded, using the emitter CSD private key.
303cfdi.sello_mismatchnoThe sello does not correspond to the CFDI content or certificate. This means the cadena original was built incorrectly or a different key signed it. Regenerate the cadena original from the final XML and re-sign with the matching CSD private key.
304pac.certificate_revokednoThe emitter CSD is revoked or outside its validity window. The taxpayer must obtain a new Certificado de Sello Digital from the SAT and re-register it on the fiscal profile. Do not retry with the same certificate.
305pac.certificate_invalidnoThe certificate is invalid (wrong type, not a CSD, or does not belong to the emitter RFC). Ensure the fiscal profile holds the emitter’s CSD (not a FIEL) issued for the emitter RFC.
306pac.certificate_invalidnoThe certificate could not be validated. Re-upload the emitter CSD (.cer as delivered by the SAT) on the fiscal profile.
307pac.duplicatenoThis exact comprobante was already stamped (SAT forbids stamping identical CFDIs twice). Treat as a success-replay: use the previously stamped UUID/XML rather than re-stamping. This is the idempotency path — surface the prior stamp to the caller.
308pac.certificate_invalidnoThe certificate is invalid. Re-register a valid emitter CSD on the fiscal profile.
309pac.certificate_invalidnoThe certificate is invalid. Verify the emitter CSD is current and matches the emitter RFC, then re-register it.
401cfdi.fecha_out_of_rangenoThe CFDI Fecha is outside the SAT-allowed window (must be within roughly the last 72 hours and not in the future, in Mexico time). Regenerate the CFDI with a fresh timestamp and re-sign it (the sello changes with Fecha).
402cfdi.emisor_not_in_lconoThe emitter is not in the SAT’s Lista de Contribuyentes Obligados or its fiscal obligations validation is negative. The taxpayer must resolve their status with the SAT (e.g. active CSD, up-to-date obligations) before stamping.

Cancellation — invocation/global codes

Global (non per-UUID) codes returned when submitting POST /v1/invoices/:id/cancel.
PAC/SAT codeOur codeRetryableRemediation
0pac.oknoNo action needed — poll the cancellation status to confirm the final SAT verdict.
1pac.auth_failednoThe stamping-service credentials were rejected. Do NOT retry — repeated failures can lock the account. This is a server-side configuration issue: contact support so the environment credentials can be verified (test and live credentials are separate).
2pac.contract_invalidnoThe stamping account is not found, is expired, or has no available stamping credits. This is a server-side account issue: contact support to renew the account or top up stamp credits.
3pac.invalid_parameternoA required parameter was missing or malformed (also returned for a malformed JSON body). Do not retry unchanged — inspect the request payload against the timbrarCfdi contract.
4pac.internal_erroryesThe stamping service reported a transient internal error. Retry with backoff. If it persists, the CFDI was almost certainly NOT stamped — safe to resubmit (idempotency guards against duplicates).
5pac.maintenanceyesThe stamping service is temporarily offline for maintenance. Retry with backoff after a short delay.
7cancel.sat_service_unavailableyesThe SAT cancellation web service is temporarily unavailable. Retry with backoff; SAT outages can last minutes to hours.
20pac.no_default_certificatenoNo CSD was available to sign the cancellation. Provide the emitter CSD (cerPem/keyPem/keyPassword) on the cancel request, since cancellations are signed.
21cancel.no_acusenoThe acuse cannot be retrieved because the CFDI is not cancelled (or was not cancelled through this service). Confirm the cancellation completed before requesting the acuse.

Cancellation — per-UUID SAT codes

SAT verdicts on the specific CFDI being cancelled (polled asynchronously).
PAC/SAT codeOur codeRetryableRemediation
94cancel.not_cancellablenoThe SAT reports this CFDI as “No Cancelable” (e.g. it is referenced by other live documents). Query related CFDIs to find and resolve the blocker.
96cancel.in_processnoThe cancellation is in process awaiting the receptor’s response. Keep polling the status; it resolves within 72 business hours.
201cancel.request_receivednoThe SAT received the cancellation request. If the CFDI is “cancelable con aceptación”, the receptor has 72 business hours to accept or reject; poll the status until it resolves.
202cancel.already_cancellednoThe CFDI was already cancelled. Treat as cancelled — no further action needed.
203cancel.rfc_mismatchnoThe emisor RFC on the request does not match the CFDI. Send the cancellation from the RFC that issued the CFDI, signed with that RFC’s CSD.
204cancel.not_applicablenoThis folio cannot be cancelled (e.g. it is referenced by another live CFDI). Query related CFDIs to find the blocker before retrying.
205cancel.uuid_not_foundnoThe UUID does not exist at the SAT. Verify the folio fiscal is correct and that the CFDI was actually stamped in this environment (test vs live).
206cancel.not_primary_sectornoThe requested cancellation flow requires a Sector Primario CFDI, which this is not. Use the standard cancellation motivo for this document type.
207cancel.motivo_missingnoThe cancellation motivo is missing or invalid. Provide a valid motivo 01-04 (01 requires a substitute folio).
208cancel.substitution_folio_invalidnoThe substitute folio (folioSustitucion) is invalid. For motivo 01 it must be the UUID of an already-stamped replacement CFDI.
209cancel.substitution_folio_not_requirednoA substitute folio was supplied but this motivo does not require one. Omit folioSustitucion for motivos 02/03/04.
210cancel.date_after_declarationnoThe cancellation request date is after the SAT declaration date for the period. Cancellation is no longer permitted for this CFDI.
211cancel.global_invoice_deadlinenoThe deadline to cancel this factura global has passed. This CFDI can no longer be cancelled.
212cancel.relation_invalidnoThe declared relation is invalid or does not exist. Verify the related/substitute CFDI exists and is correctly related.
300cancel.user_invalidnoThe user is not authorized for this cancellation. Verify credentials and that the signing CSD belongs to the emisor RFC.
310cancel.motivo_invalidnoThe motivo is not valid. Use one of 01-04 per the SAT catalog.
311cancel.substitution_folio_invalidnoThe substitute folio is not valid. For motivo 01, supply the UUID of a valid, already-stamped replacement CFDI.
312cancel.substitution_folio_not_requirednoThis motivo does not require a substitute folio. Remove folioSustitucion.
313cancel.outside_annual_declarationnoThe cancellation falls outside the allowed annual declaration window and is no longer permitted.
314cancel.relation_invalidnoThe declared relation is invalid. Verify the related CFDI and relationship type.

Status query (consultarEstatusComprobante)

Codes from the SAT status query used during cancellation polling and validation enrichment.
PAC/SAT codeOur codeRetryableRemediation
0pac.oknoNo action needed.
1pac.auth_failednoThe stamping-service credentials were rejected. Do NOT retry — repeated failures can lock the account. This is a server-side configuration issue: contact support so the environment credentials can be verified (test and live credentials are separate).
2pac.contract_invalidnoThe stamping account is not found, is expired, or has no available stamping credits. This is a server-side account issue: contact support to renew the account or top up stamp credits.
3pac.invalid_parameternoA required parameter was missing or malformed (also returned for a malformed JSON body). Do not retry unchanged — inspect the request payload against the timbrarCfdi contract.
4pac.internal_erroryesThe stamping service reported a transient internal error. Retry with backoff. If it persists, the CFDI was almost certainly NOT stamped — safe to resubmit (idempotency guards against duplicates).
5pac.maintenanceyesThe stamping service is temporarily offline for maintenance. Retry with backoff after a short delay.
6pac.query_incompleteyesThe status query did not complete. Retry with backoff.
7cancel.sat_service_unavailableyesThe SAT returned an error during the status query. Retry with backoff.
90cfdi.not_foundnoThe comprobante was not found at the SAT. Verify the UUID and that emisor RFC, receptor RFC and Total exactly match the CFDI.
91pac.oknoNo action needed — the comprobante was found.
92cfdi.invalid_expressionnoThe status query expression is invalid. Check the Total formatting (decimals must match the CFDI exactly) and the RFCs.
93cfdi.status_indeterminateyesThe SAT could not determine the state. Retry the status query later.

CFDI lifecycle status (estatusCfdi)

These are states, not errors. The SAT reports one of these when you query a CFDI; we map it to a normalized cancel_status bucket surfaced on the invoice cancellation object and on POST /v1/validations.
SAT codeMeaningNormalized cancel_status
0Desconocidounknown
1CFDI no existeunknown
2Vigente (aceptación indeterminada)none
3Vigente con aceptaciónnone
4Vigente sin aceptaciónnone
5Vigente no cancelablenone
6Cancelado (medio no especificado)cancelled
7Cancelación en proceso (espera respuesta receptor)pending
8Cancelado con aceptacióncancelled
9Cancelado sin aceptacióncancelled
10Cancelado por plazo vencidocancelled
99Indeterminado (SAT no disponible)unknown

Descarga masiva (massive download)

Codes from the SAT descarga masiva service (POST /v1/downloads). Note the lifetime/size limits — see /guides/massive-download.
PAC/SAT codeOur codeRetryableRemediation
404sat.download_uncontrolled_erroryesAn uncontrolled error occurred on the descarga masiva service. Retry with backoff; if it persists, contact support.
5000sat.download_acceptednoNo action needed — poll the request status until packages are ready.
5001sat.download_unauthorizednoSAT “tercero no autorizado”: the FIEL does not match the requested RFC. Ensure the FIEL PFX belongs to the RFC being downloaded and that side (issued/received) matches that RFC’s role.
5002sat.download_request_limitnoSAT allows at most 2 lifetime requests with identical parameters. Do NOT retry the identical query — fragment or vary the date range (e.g. split the month into weeks) to make a distinct request.
5003sat.download_too_largenoThe request exceeds the SAT cap (200,000 XMLs / 1,000,000 metadata records). Fragment the date range into smaller windows and issue separate requests.
5004sat.download_no_datanoThe SAT found no CFDIs for these filters — this is a terminal, successful, empty result. Do not retry; the range simply has no documents.
5005sat.download_duplicatenoAn identical request already exists. Reuse the existing request’s id, or vary the date range to create a distinct request.
5007sat.download_package_not_foundnoThe requested package was not found — its download URL likely expired (URLs live ~5 minutes). Re-poll the request status to re-mint the package URLs and download immediately.
5010sat.download_packaging_erroryesThe SAT failed to package the result. Retry the status poll; if it persists, re-issue the request with a smaller date range.
8000sat.download_generation_erroryesThe stamping service failed to generate the SAT request. Retry with backoff; if it persists, verify the FIEL, dates and RFC.

Descarga masiva lifecycle (estado)

SAT download-request lifecycle states, mapped to our public download.status.
SAT estadoMeaningOur status
1Aceptadapending
2En procesopending
3Terminada / listapending
4Descargando paquetespending
5Rechazadarejected
6Vencida / expiradaexpired
7Paquetes listosready

Regenerate this file with pnpm openapi.