Independence Day offer · ₹52/employee/moClaim offer
INDPayroll
Payroll Engine API

Errors

Every failure returns the same envelope: a broad type that matches the HTTP status, a specific code stable enough to branch on, a message written for the developer reading the log, and a request id to quote at support.

422 Unprocessable Entity
{
  "error": {
    "type": "unprocessable_entity",
    "code": "salary_structure_missing",
    "message": "ext:emp-1044 has no salary structure effective on 2026-09-01.",
    "doc_url": "https://www.indpayroll.com/docs/api/errors",
    "request_id": "req_01J9K7YR4H"
  }
}

Validation failures carry field_errors as well, one entry per rejected field, with a dotted path you can map straight onto your own form.

Status codes

StatusTypeWhat it means
400validation_errorThe request was malformed, or a field failed validation.
401authentication_errorNo key, an unknown key, or a signature that did not verify.
403permission_errorThe key is valid but lacks the scope, or cannot reach that organization.
404not_foundNo such resource - or it belongs to an organization the key cannot reach.
409conflict_errorThe resource's state forbids the change: a locked run, a duplicate external_id.
422unprocessable_entityWell-formed, but the engine cannot compute it. A missing structure, no PT state, an empty period.
429rate_limit_errorToo many requests. Wait for Retry-After.
5xxserver_errorOur fault. Safe to retry with backoff.

Codes worth handling

CodeUsually means
invalid_signatureThe canonical string was assembled differently. Check the path and the body hash.
signature_expiredMore than 300 seconds between signing and sending.
missing_scopeAsk for a key with the scope named in the message.
run_lockedUnlock the run, or recalculate before locking it.
salary_structure_missingThe employee has no structure effective in the period.
pt_state_missingThe employee has no professional tax state mapped.
duplicate_external_idTwo employees in one organization claim the same external_id.
period_overlaps_runAnother run already covers part of this period for these employees.

Retrying

  • Retry on 429 and 5xx, with exponential backoff and jitter.
  • Do not retry 400, 403, 404, 409 or 422 unchanged - the same request will fail the same way.
  • Send an Idempotency-Key on every mutating call so a retry after a timeout cannot pay twice. See Idempotency.
Quote the request idEvery response carries X-Request-Id, and every error repeats it in the body. It is the fastest way for us to find what happened.