Error codes
Every fiscaliacore error returns a stable code plus a human-readable message. Branch on code — never on message.
Envelope
json
{
"timestamp": "2026-04-23T20:00:00Z",
"status": 401,
"code": "SESSION_EVICTED",
"message": "no active signing session — open one via POST /api/v1/sessions",
"details": [],
"path": "/api/v1/acecf/issue"
}Codes
| Code | HTTP | When it fires | What to do |
|---|---|---|---|
SESSION_EVICTED | 401 | Your bearer has expired, the process restarted, or someone closed the session. | Open a fresh session + retry the request once. If the second attempt also 401s, stop retrying and surface the error — something's wrong beyond a stale session. |
INVALID_PASSWORD | 401 | The .p12 password you sent didn't unlock the keystore. | Double-check the password; try unlocking the .p12 with openssl pkcs12 -in file.p12 -info to confirm it's right. |
MALFORMED_P12 | 401 | Base64 didn't decode to a PKCS#12 keystore, or the keystore has no key-bearing alias. | Check you're sending raw .p12 bytes (not a PEM or cert-only export) and standard base64 (no URL-safe variant). |
VALIDATION_FAILED | 400 | Your request body failed bean validation (wrong RNC length, bad date format, missing required field). | details[] carries per-field error strings; fix the payload. |
BAD_REQUEST | 400 | Generic malformed payload (e.g. estado = 3 which isn't 1 or 2). | Inspect message + fix the payload. |
XML_BUILD_FAILED | 422 | The payload parsed fine but the DGII-shape XML couldn't be built. Usually a business-rule violation — e.g. E47 requires Retencion per line and yours is missing. | Inspect message, correct the business data, retry. |
SIGNING_FAILED | 500 | The in-memory signer raised. Rare; usually a structurally weird cert (non-RSA key, damaged chain). | Contact support with the timestamp + path. |
INBOUND_REJECTED | 400 | A DGII-originated call to {rnc}.ecf.fiscaliacore.com/fe/* couldn't be routed (no registered receiver for that RNC, or the inbound XAdES signature didn't verify). | Register the RNC's callback URL via POST /api/v1/receivers. |
INVALID_STATE | 409 | You're trying to transition a document out of its allowed state machine (e.g. annul something already annulled). | Check your local state model; the server's is authoritative per DGII semantics. |
INTERNAL_ERROR | 500 | Unexpected server-side exception. We log the stack trace with the request path. | Paste the timestamp + path into a support ticket. |
DGII-reject envelopes
DGII-business-rejections (valid submission, but DGII says no on business grounds) have a slightly different shape — the outer HTTP is 400 but the response body mirrors the business response:
json
{
"trackId": "",
"dgiiEstado": "Rechazada",
"signedXml": "<ACECF>...</ACECF>",
"submittedAt": "2026-04-23T17:02:14Z",
"success": false,
"statusMessage": "La propiedad TotalITBIS no coincide con el valor del conjunto de datos..."
}success: false + the statusMessage from DGII. Surface the message to your end-customer — they'll want to correct and retry.
DGII 5xx and timeouts
If DGII itself is down or times out, we return HTTP 502 (Bad Gateway) with code INTERNAL_ERROR and a message containing DGII submission failed. Retry is your responsibility — fiscaliacore doesn't queue for later, by design. Exponential backoff in your product; stop after some threshold and surface the outage to the user.