Handling pending or failed IRN responses

The IRN generate call is synchronous. The response tells you immediately whether the IRP accepted or rejected the invoice.

What you get back

HTTPWhat it meansYour move
200IRN generated. The body has irn, signedQrCode, signedInvoice populated. Status is generated.Persist the IRN + signed payloads. Done.
502 upstream.failureThe IRP rejected the request — vendor's reason is in message. Common cases: duplicate IRN, invalid GSTIN, schema validation.Inspect message; fix the input; retry. Send the same Idempotency-Key only when the body is unchanged.
503 / 504Transient — IRP unreachable or timed out.Retry with the same Idempotency-Key after a backoff (1s → 2s → 4s, jittered).
422Your body failed our pre-flight validation. details lists each field.Fix the body; retry. Don't reuse the Idempotency-Key — the request changed.

Why there's no separate status-polling endpoint

NIC's IRP is itself synchronous and OneFinOps mirrors that. POST returns the terminal state; there's nothing to poll. For eventual delivery on top of unstable infrastructure, lean on:

  1. Idempotency-Key — a retry with the same key is safe. The first successful run wins; subsequent retries with the same key get the cached response and an Idempotency-Replayed: true header.
  2. Webhooks — subscribe to einvoice.generated for live updates if a downstream system (batch worker, queue) is producing IRNs in the background on your behalf.

Cancellations

Cancel is also synchronous: call POST /v1/einvoices/{irn}/cancel, get the updated record back. The cancellation window is 24 hours from generation; a cancel attempt past that returns 409 einvoice.cancel_window_expired.