The OneFinOps API returns errors with a consistent envelope. The contract is additive-only — we will never break a code you depend on, and we'll only ever add fields.
The envelope
{
"object": "error",
"code": "einvoice.cancel_window_expired",
"message": "IRN can only be cancelled within 24 hours of generation.",
"httpStatus": 409,
"requestId": "8c2b5...",
"traceId": "abcd1234...",
"details": [
{ "field": "lines[0].hsnCode", "code": "hsn_invalid", "message": "HSN must be 4, 6 or 8 digits." }
],
"upstream": {
"provider": "nic-irp",
"code": "2150",
"message": "Duplicate IRN"
}
}
Field
Use
code
Branch on this. Never on message.
message
Show to humans. Never to programmatic logic.
httpStatus
Mirrors the response status.
requestId
Quote this when filing a support ticket — we can find your call instantly.
traceId
OpenTelemetry trace id for full server-side stack.
details
Per-field validation errors when applicable.
upstream
NIC / GSP error verbatim — useful when you need the raw vendor reason.
Status families
HTTP
What it means
Retry?
400
Request rejected before it touched NIC. Fix the body.
No.
401
Token missing, expired, or for the wrong environment.
After re-auth.
403
Token is fine; required scope is missing.
After widening scope on the client.
404
Resource id doesn't belong to your tenant or doesn't exist.
No.
409
State conflict — cancel window expired, duplicate, etc.
No (state-bound).
422
Body / query failed validation. Inspect details.
No.
429
Rate limited.
Yes, with backoff.
5xx
Our problem.
Yes, with backoff. Surface to support if it persists past a few minutes.
Error codes
Common (any endpoint)
Code
HTTP
Meaning
request.rejected
400
Generic rejection — see message for details.
validation_error
422
Body or query failed validation. See details[].
not_found
404
Resource doesn't exist or isn't yours.
conflict
409
State conflict.
idempotency.key_reused_mismatch
409
Same Idempotency-Key, different body.
E-Invoice
Code
HTTP
Meaning
irp_credentials.not_configured
400
No IRP credential uploaded for the seller GSTIN.
irp_credentials.decrypt_failed
500
Server-side credential decryption failed — open a ticket.
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
EInvoiceId parameter doesn't match the einv_<hex> shape.
E-Way Bill
Code
HTTP
Meaning
ewaybill.not_cancellable
409
EWB is past 24-hour cancel window or already in transit.
ewaybill.validity_expired
409
Tried to extend or update Part-B on an expired EWB.
Vendor passthrough
When NIC or the GSP rejects a call for a domain reason (duplicate IRN, invalid GSTIN, etc.), the relevant fields land in upstream. Treat upstream.code as informational — branch on our code and surface upstream.message to your end user when helpful.
Retry policy
- 429 / 503 → exponential backoff, jitter, give up after ~5 minutes
- 5xx (other) → same as above, but escalate to support if persistent
- 4xx (other) → do NOT retry blindly; the request needs to change first
Idempotent retries are safe: include the sameIdempotency-Key and you cannot accidentally double-generate.