Overview
Errors of a request carry an HTTP status; outcomes in a webhook carry only a code.
heru reports problems in two places, and they are read differently:
| Request errors | Webhook event codes | |
|---|---|---|
| When | The request itself cannot run: a field, the token, the state of the resource, or the SAT rejected the invoice. | A fiscal or social security validation finished in the background without a full profile or NSS. |
| Where | The answer of the request, with an HTTP status 4xx or 5xx. | The code of the validation, in its webhook and in GET. The request had answered 202. |
| Shape | JSON with code, status, message and link. | The resource, with status, code and message. |
| Pages | General, Validation, Invoices and certificates, CSD, State conflicts | Validation results |
In both, branch on code: it is stable, UPPER_SNAKE and starts with its family. The text in message can change.
Request errors
Every error answer has code, status, message, link and request_id; validation errors add the fields that failed, and SAT rejections the SAT rule in sat_code. link is the docs page that explains the error. Each operation of the API reference lists the errors it can answer, with an example of each.
{
"code": "VALIDATION_FAILED",
"status": 422,
"message": "Fix the fields listed in `fields` and retry.",
"link": "https://developers.heru.app/errors/validation",
"fields": [
{ "field": "curp", "reason": "must have 18 characters" }
],
"request_id": "req_01m4ra8x59ehp870crwjcypejt"
}Quote the request_id when you contact your account team about a specific call. It also comes in the X-Request-Id response header.
| HTTP status | What to do |
|---|---|
| 400, 413, 422 | Fix the request. Do not retry it unchanged. Nothing was created. |
| 401 | Request a new token and retry once. |
| 403 | Ask your account team to add the scope. |
| 404 | Check the id. A resource of another company also answers 404. |
| 409, 410 | Read the resource to see its state. For IDEMPOTENCY_KEY_REUSED, use a new key. |
| 429 | Wait for Retry-After seconds, then retry. |
| 500, 503 | Retry with the same Idempotency-Key. See retries. |
Catalog
General
Details and what to do: General.
| Code | HTTP status | Meaning |
|---|---|---|
IDEMPOTENCY_KEY_REQUIRED | 400 | Idempotency-Key header is required. |
MALFORMED_REQUEST | 400 | The request body is not valid JSON. |
TOKEN_EXPIRED | 401 | The access token expired. |
UNAUTHORIZED | 401 | Missing or invalid access token. |
INSUFFICIENT_SCOPE | 403 | Your credential lacks the scope for this operation. |
NOT_FOUND | 404 | Not found. |
IDEMPOTENCY_KEY_REUSED | 409 | Idempotency-Key was used with a different request. |
PAYLOAD_TOO_LARGE | 413 | The request body is too large. |
RATE_LIMITED | 429 | Too many requests. |
INTERNAL_ERROR | 500 | Something failed on our side. |
Validation
Details and what to do: Validation.
| Code | HTTP status | Meaning |
|---|---|---|
VALIDATION_FAILED | 422 | Some fields are not valid. |
Invoices and certificates
Details and what to do: Invoices and certificates.
| Code | HTTP status | Meaning |
|---|---|---|
COMPANY_CSD_NOT_ACTIVE | 422 | The CSD heru keeps for the issuing company expired or was revoked. |
COMPANY_NOT_ALLOWED | 422 | The company is not one your credential can use. |
COMPANY_REQUIRED | 422 | Your credential covers several companies and the request does not say which one. |
INVOICE_TYPE_NOT_AVAILABLE | 422 | This invoice type is not available yet. |
MERCHANT_NOT_ACTIVE | 422 | The merchant cannot invoice yet. |
SAT_REJECTED | 422 | The SAT rejected the document. |
WORKER_NOT_ELIGIBLE | 422 | The worker is not eligible for invoicing on their behalf. |
WORKER_NO_CONSENT | 422 | The worker has not given consent. |
WORKER_NO_CSD | 422 | The worker has no valid CSD. |
WORKER_NO_EFIRMA | 422 | The worker has no active e.firma. |
STAMP_UNAVAILABLE | 503 | Stamping is unavailable. |
CSD
Details and what to do: CSD.
| Code | HTTP status | Meaning |
|---|---|---|
CSD_EXPIRED | 422 | The certificate expired. |
CSD_INVALID_CERTIFICATE | 422 | The certificate is not a valid .cer file. |
CSD_INVALID_KEY | 422 | The private key is not a valid .key file. |
CSD_IS_EFIRMA | 422 | The certificate is an e.firma, not a CSD. |
CSD_KEY_MISMATCH | 422 | The key does not belong to the certificate. |
CSD_RFC_MISMATCH | 422 | The certificate belongs to another RFC. |
CSD_WRONG_PASSWORD | 422 | The password does not open the private key. |
State conflicts
Details and what to do: State conflicts.
| Code | HTTP status | Meaning |
|---|---|---|
BATCH_INVALID_STATE | 409 | The status of the batch does not allow pausing, resuming or cancelling it. |
BATCH_NOT_READY | 409 | The batch is not ready to process. |
BATCH_EXCEEDS_CAPACITY | 409 | The batch is estimated not to finish in its 20 days. |
CHARGE_ALREADY_INVOICED | 409 | The charge was already invoiced. |
INVOICE_ALREADY_CANCELLED | 409 | The invoice is already cancelled. |
INVOICE_CANCELLATION_IN_PROGRESS | 409 | A cancellation is already in progress. |
MERCHANT_ONBOARDING_NOT_NEEDED | 409 | The merchant does not need a new onboarding link. |
MERCHANT_SLUG_TAKEN | 409 | The slug is taken. |
EXTERNAL_ID_ALREADY_USED | 409 | A retention certificate of this issuer already has this external_id. |
RETENTION_CERTIFICATE_CANCELLATION_IN_PROGRESS | 409 | The cancellation was already sent to the SAT. |
RETENTION_CERTIFICATE_ALREADY_CANCELLED | 409 | The retention certificate is already cancelled. |
WORKER_CSD_ALREADY_ACTIVE | 409 | The worker already has an active CSD. |
WORKER_CSD_IN_PROGRESS | 409 | The CSD is already being requested. |
WORKER_REMOVED | 409 | The worker was removed. |
CHARGE_EXPIRED | 410 | The charge expired. |
CHARGE_VOIDED | 410 | The charge was voided. |
Webhook event codes
They have no HTTP status: the validation was accepted with 202, and its outcome comes later in the code of the resource. A .completed event with a code is the authority's answer, final until the person fixes it; a .failed event means heru could not finish the query. See validation results for what to do with each.
| Code | Event | Meaning |
|---|---|---|
CURP_NOT_FOUND | fiscal_validation.completed | The CURP is not registered with RENAPO. |
RFC_NOT_FOUND | fiscal_validation.completed | The RFC is not registered with the SAT. |
NAME_MISMATCH | fiscal_validation.completed | The name sent does not match the RFC. |
SAT_SOURCES_PENDING | fiscal_validation.completed | Some SAT sources did not answer; heru retries and sends another webhook. |
RETRIES_EXHAUSTED | fiscal_validation.failed | Every retry with the SAT failed. |
IN_PERSON_VALIDATION_REQUIRED | social_security_validation.completed | The IMSS asks the person to go in person. |
REGISTRATION_REQUIRED | social_security_validation.completed | The person has no NSS. |
CURP_NOT_FOUND | social_security_validation.completed | The CURP is not registered with RENAPO. |
RETRIES_EXHAUSTED | social_security_validation.failed | The IMSS did not answer after every retry. |
Event notificationEVENT
We POST every event to the URL you register. Verify the `Heru-Signature` header (HMAC-SHA256 of `timestamp.body` with your webhook secret) and reply 2xx within 10 seconds. We retry with backoff for 24 hours.
General errors
Authentication, scopes, unknown ids, idempotency and rate limits, in every operation.