Errors

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"
  }
}
FieldUse
codeBranch on this. Never on message.
messageShow to humans. Never to programmatic logic.
httpStatusMirrors the response status.
requestIdQuote this when filing a support ticket — we can find your call instantly.
traceIdOpenTelemetry trace id for full server-side stack.
detailsPer-field validation errors when applicable.
upstreamNIC / GSP error verbatim — useful when you need the raw vendor reason.

Status families

HTTPWhat it meansRetry?
400Request rejected before it touched NIC. Fix the body.No.
401Token missing, expired, or for the wrong environment.After re-auth.
403Token is fine; required scope is missing.After widening scope on the client.
404Resource id doesn't belong to your tenant or doesn't exist.No.
409State conflict — cancel window expired, duplicate, etc.No (state-bound).
422Body / query failed validation. Inspect details.No.
429Rate limited.Yes, with backoff.
5xxOur problem.Yes, with backoff. Surface to support if it persists past a few minutes.

Error codes

Common (any endpoint)

CodeHTTPMeaning
request.rejected400Generic rejection — see message for details.
validation_error422Body or query failed validation. See details[].
not_found404Resource doesn't exist or isn't yours.
conflict409State conflict.
idempotency.key_reused_mismatch409Same Idempotency-Key, different body.

E-Invoice

CodeHTTPMeaning
irp_credentials.not_configured400No IRP credential uploaded for the seller GSTIN.
irp_credentials.decrypt_failed500Server-side credential decryption failed — open a ticket.
einvoice.cancel_window_expired409IRN is past NIC's 24-hour cancellation window.
einvoice.not_cancellable409IRN is in a state that doesn't permit cancellation.
einvoice.invalid_id400EInvoiceId parameter doesn't match the einv_<hex> shape.

E-Way Bill

CodeHTTPMeaning
ewaybill.not_cancellable409EWB is past 24-hour cancel window or already in transit.
ewaybill.validity_expired409Tried 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 same Idempotency-Key and you cannot accidentally double-generate.