auth.key_revoked | 401 | API key revoked | Mint a replacement key with POST /v1/api_keys and update your credentials. |
auth.unauthorized | 401 | Authentication required | Send Authorization: Bearer sk_test_... (or sk_live_…) with a valid API key. |
cancel.already_cancelled | 422 | Previously cancelled | The CFDI was already cancelled. Treat as cancelled — no further action needed. |
cancel.date_after_declaration | 422 | Request date after declaration date | The cancellation request date is after the SAT declaration date for the period. Cancellation is no longer permitted for this CFDI. |
cancel.global_invoice_deadline | 422 | Past the global-invoice deadline | The deadline to cancel this factura global has passed. This CFDI can no longer be cancelled. |
cancel.in_process | 422 | Cancellation in process | The cancellation is in process awaiting the receptor’s response. Keep polling the status; it resolves within 72 business hours. |
cancel.motivo_invalid | 422 | Motivo not valid | The motivo is not valid. Use one of 01-04 per the SAT catalog. |
cancel.motivo_missing | 422 | Motivo not specified or invalid | The cancellation motivo is missing or invalid. Provide a valid motivo 01-04 (01 requires a substitute folio). |
cancel.no_acuse | 422 | CFDI not cancelled — acuse unavailable | The 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_applicable | 422 | Folio not applicable to cancellation | This folio cannot be cancelled (e.g. it is referenced by another live CFDI). Query related CFDIs to find the blocker before retrying. |
cancel.not_cancellable | 422 | Not cancellable | The 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_sector | 422 | UUID is not a Sector Primario CFDI | The requested cancellation flow requires a Sector Primario CFDI, which this is not. Use the standard cancellation motivo for this document type. |
cancel.outside_annual_declaration | 422 | Outside the annual declaration window | The cancellation falls outside the allowed annual declaration window and is no longer permitted. |
cancel.relation_invalid | 422 | Relation invalid | The declared relation is invalid. Verify the related CFDI and relationship type. |
cancel.request_received | 422 | Cancellation request received | The 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_mismatch | 422 | Emisor RFC does not match | The 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_unavailable | 502 | SAT error during query | The SAT returned an error during the status query. Retry with backoff. |
cancel.substitution_folio_invalid | 422 | Substitute folio not valid | The substitute folio is not valid. For motivo 01, supply the UUID of a valid, already-stamped replacement CFDI. |
cancel.substitution_folio_not_required | 422 | Substitute folio not required | This motivo does not require a substitute folio. Remove folioSustitucion. |
cancel.user_invalid | 422 | User not valid for cancellation | The user is not authorized for this cancellation. Verify credentials and that the signing CSD belongs to the emisor RFC. |
cancel.uuid_not_found | 422 | Folio fiscal does not exist | The 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_expired | 422 | Invalid invoice | Renew the CSD at the SAT portal; an expired/not-yet-valid certificate cannot stamp. |
cfdi.csd_rfc_mismatch | 422 | Invalid invoice | Use the CSD (certificado de sello digital) issued to the emitter RFC. |
cfdi.emisor_not_in_lco | 422 | Taxpayer not in LCO / obligations negative | The 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_future | 422 | Invalid invoice | Generate Fecha at stamp time; it must not be in the future. |
cfdi.fecha_out_of_range | 422 | Fecha outside the allowed window | The 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_old | 422 | Invalid invoice | Re-issue the invoice; CFDI must be stamped within 72h of Fecha. |
cfdi.invalid_expression | 422 | Invalid expression | The status query expression is invalid. Check the Total formatting (decimals must match the CFDI exactly) and the RFCs. |
cfdi.invalid_fecha | 422 | Invalid invoice | Pass date as ‘YYYY-MM-DDTHH:mm:ss’ (SAT forbids a timezone suffix). |
cfdi.invalid_input | 422 | Invalid invoice | Fix every field listed in errors and resubmit. See /openapi.json for the schema. |
cfdi.malformed_sello | 422 | Malformed sello | The 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_xml | 422 | Malformed CFDI XML | The 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_rate | 422 | Invalid invoice | Provide rate (e.g. 0.16) for Tasa/Cuota taxes. |
cfdi.missing_uso | 422 | Invalid invoice | Set use at invoice level or customer.use. |
cfdi.no_tfd | 422 | Invalid invoice | Only stamped CFDIs (with a TFD) have a TFD cadena. |
cfdi.not_a_csd | 422 | Invalid invoice | Sign CFDIs with the CSD; the FIEL is only for descarga masiva. |
cfdi.not_comprobante | 422 | Invalid invoice | Pass a CFDI 4.0 Comprobante XML. |
cfdi.not_found | 422 | Comprobante not found | The 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_taxes | 422 | Invalid invoice | Provide at least one tax for this item, or set tax_object to ‘01’ (no objeto de impuesto). |
cfdi.objeto_imp_dr_02_without_taxes | 422 | Invalid invoice | Provide at least one tax on the related document, or set its tax_object to ‘01’. |
cfdi.parse_error | 422 | Invalid invoice | Provide a well-formed CFDI XML string. |
cfdi.pdf_dependencies_missing | 422 | Invalid invoice | Install the optional PDF peer dependencies (the CFDI PDF renderer and @xmldom/xmldom) on the server. |
cfdi.pdf_requires_stamp | 422 | Invalid invoice | Stamp the CFDI with the PAC first; the PDF shows the fiscal folio (UUID). |
cfdi.retencion_exento | 422 | Invalid invoice | Use factor Tasa or Cuota for withholdings, or make it a traslado. |
cfdi.sello_injection_failed | 422 | Invalid invoice | Ensure the XML is a well-formed CFDI 4.0 Comprobante. |
cfdi.sello_mismatch | 422 | Sello does not match | The 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_indeterminate | 502 | Indeterminate state | The SAT could not determine the state. Retry the status query later. |
cfdi.unknown_currency | 422 | Invalid invoice | Use a valid ISO 4217 currency code present in c_Moneda. |
connect.account_disabled | 403 | Connected account disabled | Re-enable the account via PATCH /v1/accounts/:id {“disabled”: false}. |
connect.account_not_authorized | 403 | Not a connected account of this platform | Create 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_allowed | 403 | Connected accounts cannot own connected accounts | Create connected accounts from the top-level platform organization. |
connect.not_supported_here | 400 | Acting as a connected account is not supported here | Drop the Invoice-Account header. Manage API keys with your platform key directly. |
dashboard.email_in_use | 409 | Email already registered | Sign in at /signin, or use a different email. |
dashboard.invalid_credentials | 401 | Invalid email or password | Check your credentials and try again. |
dashboard.pages_unavailable | 503 | Dashboard pages unavailable | Deploy the web/ assets alongside the API, then retry. |
dashboard.session_required | 401 | Sign in required | Sign in at /signin to obtain a session cookie. |
dashboard.too_many_attempts | 429 | Too many sign-in attempts | Wait 15 minutes before trying again. |
download.fiel_required | 422 | Fiscal profile has no FIEL | Upload 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_range | 422 | Invalid date range | Provide date_from <= date_to. |
download.no_request_id | job | Download has no SAT request id | The solicitud never registered with the PAC — create the download again. |
download.poll_timeout | job | Download gave up waiting for the PAC | The SAT package was not ready within the polling window. Create a new download, and fragment very large date ranges. |
download.request_failed | 502 | SAT descarga masiva request failed | — |
download.unknown_error | job | Download failed (unclassified) | Read the download error.message; if it looks transient, create a new download for the same range. |
fiscal_profile.csd_expired | 422 | CSD is expired or not yet valid | Renew 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_fiel | 422 | FIEL supplied where a CSD is required | Register 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_mismatch | 422 | Rotated CSD belongs to a different RFC | Rotate to a CSD issued to the same RFC. To register a different taxpayer, create a new fiscal_profile. |
fiscal_profile.fiel_required | 422 | A FIEL is required to sign the manifiesto | Send the FIEL under fiel: { cer_base64, key_base64, password } in this request, or register it on the profile first. |
fiscal_profile.in_use | 409 | Fiscal profile is in use | A 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_csd | 422 | Invalid CSD certificate or password | Verify 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_fiel | 422 | Invalid FIEL certificate or password | Verify the FIEL (e.firma) files and password; it is only used for descarga masiva. |
fiscal_profile.invalid_metadata_json | 422 | metadata is not valid JSON | Send metadata as a JSON string, e.g. metadata={“order_id”:“123”}. Keys and values must be strings. |
idempotency.key_processing | 409 | A request with this Idempotency-Key is still being processed | Retry once the in-flight request with this Idempotency-Key completes. |
idempotency.key_reuse | 409 | Idempotency-Key reused with a different request body | Reuse an Idempotency-Key only for byte-identical retries; use a fresh key for a new request. |
internal.error | 500 | Internal server error | — |
invoice.already_stamped | 409 | Invoice already stamped | — |
invoice.cancellation_in_progress | 409 | Cancellation already requested | — |
invoice.cancellation_rejected | 422 | Cancellation rejected | Check the UUID is vigente and the motivo/substitute are correct; retrieve the acuse for details. |
invoice.folio_contention | 409 | Could not assign a folio | Retry the request; concurrent invoice creation on this serie is heavy. |
invoice.folio_taken | 409 | Folio already used | — |
invoice.no_xml | 422 | Invoice has no XML to stamp | Recreate the invoice; the signed XML is missing. |
invoice.not_stampable | 409 | Invoice cannot be stamped | — |
invoice.not_stamped | 409 | Only stamped invoices can be cancelled | — |
invoice.pdf_requires_stamp | 409 | PDF is only available for stamped invoices | — |
invoice.profile_missing_csd | 422 | Fiscal profile has no CSD | Upload the CSD (.cer + .key + password) to the fiscal profile before issuing invoices. |
invoice.substitute_not_stamped | 422 | Substitute invoice is not stamped | Stamp the replacement invoice before referencing it as a substitute. |
invoice.substitute_required | 422 | Substitute invoice required | Pass substitute_invoice_id pointing to the stamped CFDI that replaces this one, or use motivo ‘02’. |
invoice.xml_requires_stamp | 409 | XML is only available for stamped invoices | — |
manifest.email_required | 422 | An email is required for the manifiesto | Provide email in the request or set the MANIFEST_EMAIL config default. |
manifiesto.already_signed | 422 | Contrato firmado previamente | The carta manifiesto was already signed for this RFC — no action needed. The profile is authorized for CFDI certification. |
manifiesto.bad_request | 422 | Petición inválida o parámetros incorrectos | The request was missing or had incorrect parameters (cert, key, keyPass, correo). |
manifiesto.bad_sello | 422 | Sello del emisor mal formado o inválido | The FIEL sello could not be validated. Re-download the FIEL (e.firma) from the SAT and try again. |
manifiesto.certificate_error | 422 | Error en el certificado | There was an error with the certificate. Verify the FIEL files and password, then retry. |
manifiesto.certificate_not_sat | 422 | El certificado del emisor no fue emitido por el SAT | The certificate was not issued by the SAT. Upload the taxpayer’s real FIEL/e.firma certificate. |
manifiesto.certificate_not_valid | 422 | El certificado del emisor no es válido | The FIEL certificate is not valid (expired or revoked). Renew the e.firma at the SAT and retry. |
manifiesto.contract_not_valid | 422 | El contrato no es válido | The signing service reports the signing contract is not valid. Contact support. |
manifiesto.invalid_certificate | 422 | Certificado del emisor mal formado o inválido | The 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_credentials | 422 | Usuario, contraseña o contrato del asociado inválido | The manifiesto signing service rejected the request credentials. Verify the FIEL password and that the account is provisioned for manifiesto signing. |
manifiesto.invalid_response | 502 | Manifiesto SOAP response had no <return> payload | The signing service returned an unexpected manifiesto response shape. Retry; if it persists, contact support. |
manifiesto.malformed_contract | 422 | Contrato mal formado | The manifiesto contract payload was malformed. Contact support. |
manifiesto.malformed_xml | 422 | XML mal formado | The signing service could not parse the request. Retry; if it persists, contact support. |
manifiesto.network_error | 502 | Manifiesto signing request failed | The manifiesto signing request could not reach the signing service. Retry with backoff. |
manifiesto.provider_error | 502 | Error al procesar la firma del contrato | The signing service hit an internal error signing the manifiesto. Retry with backoff; if it persists, contact support. |
manifiesto.signed | 422 | Firma exitosa | — |
manifiesto.xml_generation_error | 502 | Error al generar el xml | The signing service failed to generate the signed XML. Retry with backoff; if it persists, contact support. |
org.bootstrap_disabled | 403 | Organization bootstrap is disabled | Enable ALLOW_ORG_BOOTSTRAP or provision organizations out-of-band. |
pac.auth_failed | 422 | PAC credentials invalid | The 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_invalid | 422 | Certificate invalid | The certificate is invalid. Verify the emitter CSD is current and matches the emitter RFC, then re-register it. |
pac.certificate_revoked | 422 | Certificate revoked or expired | The 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_invalid | 422 | Contract invalid or expired | The 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.duplicate | 422 | Comprobante already exists | This 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_error | 502 | PAC internal error | The 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_parameter | 422 | Invalid or missing parameter | A 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.maintenance | 502 | PAC offline for maintenance | The stamping service is temporarily offline for maintenance. Retry with backoff after a short delay. |
pac.no_default_certificate | 422 | No default certificate for cancellation | No CSD was available to sign the cancellation. Provide the emitter CSD (cerPem/keyPem/keyPassword) on the cancel request, since cancellations are signed. |
pac.ok | 422 | Comprobante found | No action needed — the comprobante was found. |
pac.query_incomplete | 502 | General error, query not completed | The status query did not complete. Retry with backoff. |
pac.unknown | 422 | Unmapped PAC/SAT code | The 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.exceeded | 429 | Too many requests | Back off and retry after the number of seconds in the Retry-After header; batch work or lower your request rate. |
request.error | 500 | Request error | — |
request.invalid_date | 422 | Invalid date filter | Pass ${field} as an ISO-8601 date or datetime, e.g. 2026-07-10 or 2026-07-10T00:00:00Z. |
request.invalid_expand | 422 | Invalid expand parameter | Use only the expand values the endpoint documents (e.g. fiscal_profile). Remove unsupported values. |
request.invalid_pagination | 422 | Conflicting pagination cursors | Pass only one cursor: starting_after for the next (older) page, or ending_before for the previous (newer) page. |
request.invalid_version | 400 | Unknown API version | Send a supported version in the Invoice-Version header, or omit it to use the current version. |
request.method_not_allowed | 405 | Method not allowed | — |
request.validation_failed | 422 | Request validation failed | Fix the fields listed in errors and resubmit. See /openapi.json for the schema. |
resource.not_found | 404 | Resource not found | Verify 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_accepted | 422 | Download request accepted | No action needed — poll the request status until packages are ready. |
sat.download_duplicate | 422 | Duplicate request | An identical request already exists. Reuse the existing request’s id, or vary the date range to create a distinct request. |
sat.download_expired | job | SAT marked the solicitud as expired | Package URLs expire quickly — create a new download for the same range. |
sat.download_generation_error | 503 | Request generation error | The stamping service failed to generate the SAT request. Retry with backoff; if it persists, verify the FIEL, dates and RFC. |
sat.download_no_data | 422 | No data for the filters | The 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_found | 422 | Package not found | The 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_error | 503 | Packaging error | The SAT failed to package the result. Retry the status poll; if it persists, re-issue the request with a smaller date range. |
sat.download_rejected | job | SAT rejected the solicitud | Verify the FIEL matches the requesting RFC and role (issued/received); a mismatch yields a SAT “tercero no autorizado” rejection. |
sat.download_request_limit | 422 | Lifetime request limit reached | SAT 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_large | 422 | Result exceeds SAT size cap | The 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_unauthorized | 422 | Third party not authorized | SAT “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_error | 503 | Uncontrolled error | An uncontrolled error occurred on the descarga masiva service. Retry with backoff; if it persists, contact support. |
validation.empty_xml | 400 | Decoded XML is empty | Provide base64-encoded CFDI XML in xml_base64, or send raw XML with Content-Type application/xml. |
webhook.event_type_not_enabled | 422 | Endpoint does not subscribe to this event type | Subscribe the endpoint to this event type (or a matching wildcard) via PATCH /v1/webhook_endpoints/:id. |
webhook.https_required | 400 | Webhook URL must use https in live mode | Use an https:// URL, or a sk_test_ key for http:// endpoints in development. |