Errors
The OneFinOps API returns a flat error body on every 4xx / 5xx response. The contract is additive-only — we won't break a code you depend on, and we'll only ever add fields.
The body
{
"code": "382",
"message": "NIC 382: You Cannot Extend as EWB can be Extended only 8 hour before or after w.r.t Validity of EWB",
"details": {
"382": [
"You Cannot Extend as EWB can be Extended only 8 hour before or after w.r.t Validity of EWB"
]
},
"requestId": "8c2b5…",
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-…-01",
"timestamp": "2026-05-21T10:32:18.000Z"
}| Field | Use |
|---|---|
code | Branch on this. Never on message. For NIC business errors this is the NIC numeric code (e.g. "382"); for OneFinOps-side errors it is a dotted identifier (e.g. einvoice.cancel_window_expired). |
message | Show to humans. Never to programmatic logic. |
details | Optional. Keys are error codes (or field paths on 422 validation failures); values are arrays of messages. For NIC errors the verbatim NIC text is preserved here under the NIC code key. |
requestId | Echo of the X-Request-Id you sent (or one OneFinOps generated). Quote it when filing a support ticket. |
traceId | Distributed-tracing id (W3C traceparent). Useful when escalating to support. |
timestamp | UTC time the error was generated. |
The HTTP status is the source of truth for the error category — there is no httpStatus field in the body. NIC and gateway names never appear on the wire; the public surface only ever mentions "NIC" and "GST".
Status families
| HTTP | What it means | Retry? |
|---|---|---|
| 400 | Request was malformed (bad JSON, syntactically invalid). | No — fix the body. |
| 401 | Token missing, expired, or for the wrong environment. | After re-auth. |
| 403 | Token is fine; plan / entitlement doesn't permit this call. | No — contact your account manager. |
| 404 | Resource doesn't belong to your tenant or doesn't exist. | No. |
| 409 | State conflict — cancel window expired, duplicate replay with different body, etc. | No (state-bound). |
| 422 | Body, query, or upstream NIC business rule failed. Inspect details. | No — fix the input or wait for the NIC condition to clear. |
| 429 | Rate limited. | Yes, with backoff. |
| 502 | Upstream gateway unreachable. | Yes, with backoff. |
| 503 | NIC briefly unavailable. | Yes, with backoff. |
| 504 | NIC timed out. | Yes, with backoff. |
| 5xx (other) | OneFinOps-side issue. | Yes, with backoff. Surface to support if persistent. |
Common codes (any endpoint)
| Code | HTTP | Meaning |
|---|---|---|
validation_error | 422 | Body or query failed validation. Inspect details. |
not_found | 404 | Resource doesn't exist or isn't visible to your tenant. |
conflict | 409 | State conflict. |
gstin.required | 400 | gstin header is required for this endpoint and was missing or empty. |
auth.invalid_token | 401 | Token missing, malformed, or expired. |
auth.entitlement_missing | 403 | Plan doesn't include the capability you called. |
request.rejected | 429 | Rate limited. |
GSP_GATEWAY_REJECT | 422 | Upstream gateway rejected the call for a non-NIC reason (e.g. credential cache miss). message carries the verbatim upstream text. |
E-Invoice codes
| Code | HTTP | Meaning |
|---|---|---|
irp_credentials.not_configured | 400 | No IRP credential uploaded for the seller GSTIN. |
einvoice.cancel_window_expired | 409 | IRN is past NIC's 24-hour cancellation window. |
einvoice.not_cancellable | 409 | IRN is in a state that doesn't permit cancellation. |
einvoice.invalid_id | 400 | irn is not a 64-character hex string. |
EInvoice.Signature.CertNotConfigured | 500 | Signed-JWS decode requested but the NIC IRP public certificate is not configured on the server. |
NIC IRP also returns its own numeric codes for business rejections — 2150 (Duplicate IRN), 2163 (Document date should not be a future date), etc. These come through as the top-level code directly, with the verbatim NIC message in details.
E-Way Bill codes
| Code | HTTP | Meaning |
|---|---|---|
ewb_credentials.not_configured | 400 | No EWB-portal credential uploaded for the supplier GSTIN. |
ewaybill.not_cancellable | 409 | EWB is past the 24-hour cancel window or NIC has marked movement as begun. |
ewaybill.validity_expired | 409 | Tried to extend or update Part-B on an EWB outside its extension window. |
ewaybill.invalid_number | 400 | ewbNumber is not a 12-digit number. |
NIC EWB also returns its own numeric codes — 382 (extend outside ±8h window), 328 (transporter details unavailable), 2230 (cannot cancel an EWB linked to an IRN), etc. These come through as the top-level code directly.
NIC business errors
When NIC rejects a call for a domain reason — duplicate IRN, expired cancel window, validity edge cases, suspended GSTIN, etc. — the response is HTTP 422 with the NIC code in the top-level code field and the verbatim NIC text in details["<code>"]. The message field combines "NIC <code>: <text>" for human display.
Branch on code. Surface message (or details["<code>"]) verbatim to the end user when helpful — it's the same text NIC's portals show.
{
"code": "2150",
"message": "NIC 2150: Duplicate IRN",
"details": { "2150": ["Duplicate IRN"] }
}Retry policy
429 / 502 / 503 / 504 → exponential backoff with jitter (1s → 2s → 4s → 8s, capped 30s).
422 (NIC code) → DO NOT retry blindly. Read the NIC code first; most
indicate a data problem that retrying won't fix.
Specific 422s like GSP_GATEWAY_REJECT "Invalid Token"
are transient and may be retried once.
4xx (other) → fix the input first; the request needs to change.
5xx (other, OneFinOps) → exponential backoff; escalate if persistent.NIC IRP is itself idempotent on (sellerGstin, documentType, documentNumber, financialYear). If you re-submit the same tuple, NIC returns the existing IRN with code 2150 and message "Duplicate IRN" — see Generate an IRN — duplicate detection.
Where to next
- Rate limits — for 429 specifics.
- Generate an IRN — IRN-specific failure modes.
- Generate an EWB — EWB-specific failure modes.
