Error body
HTTP status codes
Common validation errors
Validation failures return 400 withmessage: "Validation failed" and an errors array. Each entry is field: constraint. The exact messages you will see most often:
Bulk Excel uploads return row-level errors instead, each with
row, field and message. See Bulk Upload via Excel.
Warnings on an accepted filing
A successfulpush-irm response may carry a warnings array. These are not failures — the
filing was accepted and forwarded to DGFT — but each one is something DGFT is likely to reject
later, surfaced now so you can act before the status poll rather than after it.
They come from comparing your filing against the IRM records we hold for that exporter:
These are warnings rather than errors because our IRM records are a snapshot of what DGFT
last shared, and DGFT’s copy is authoritative. Refusing a filing on a disagreement would let
a stale or incomplete local copy block a correct submission. A clean filing carries no
warnings key at all.Purpose code and export type
DGFT maps purpose codes to export types by its own published rules, and answers ERR39 when a filing does not follow them. Those rules are not reproduced in the technical specification, so this check is inferred from the categories in Purpose Codes rather than read from the rulebook — which is why it warns and never refuses. Two cases are flagged, both drawn from category01 being titled “Exports (of Goods)“:
Three cases are deliberately never warned about, because the annexure does not support the
inference:
- Any category on
uploadType102(Softex). The category01descriptions name SOFTEX themselves —P0101is “covered under GR/PP/SOFTEX/EC copy of shipping bills” andP0103is “to be covered later by GR/PP/SOFTEX/SDF”. - Category
15(Others) — ambiguous by name. - Category
17(Manufacturing) — manufacturing services on physical inputs owned by someone else, where which export type applies is exactly what DGFT’s rules page decides.
DGFT error codes
DGFT validates every record on its own side, hours after the filing is accepted. Its codes arrive inerrorDetails on the status response, per record.
The codes we can prevent at submission are listed under common validation
errors above; the rest are DGFT’s own.
Two of these describe things this API does not send.
ERR24 refers to a paymentDate field
that appears in no request we make, and ERR12 / ERR13 refer to a clubID that DGFT’s own
field tables do not document. They are listed for completeness.
DGFT upstream error codes
fetchIRMDetails, fetchEBRCDetails and getRequestStatus all reach DGFT’s GenEBRC API. DGFT
does not use HTTP status the way you would expect: an empty result set, a malformed request and
a genuine outage all arrive from them as HTTP 500, distinguished only by a message in the body.
We classify them so you can branch on errorCode instead:
DGFT_NO_DATA is not an error in your integration. It is DGFT’s way of saying “nothing
matched”. The most common cause is a date range that does not cover the IRM you asked for.Fetching IRMs by number and date
POST /irm/refresh accepts an irmNumber, a fromDate/toDate range, or both. DGFT applies
both filters together — it does not look an IRM up by number alone — so an IRM issued outside
the requested period comes back as DGFT_NO_DATA even though the number is perfectly valid.
A range wider than 36 months is refused locally with 400 before any DGFT call:
DGFT credential error codes
Endpoints that operate on a customer’s DGFT connection return a structured error when that connection fails. Branch onerrorCode, never on message:
The 24-hour activation, and retryAfter
Most exporters have never generated DGFT API credentials. Validation creates a fresh
registration with our IP on it, DGFT enables it immediately, and the first IRM refresh
seconds later works.
An exporter who already held DGFT API credentials takes a different path. We reuse those
credentials rather than rotate them, and add our IP to the existing registration. DGFT enables
an IP added to an already-enabled account after 24 hours, and until then every call that needs
an access token answers:
retryAfter is an ISO 8601 UTC timestamp. Schedule the retry for then instead of polling.
You do not have to: an IRM refresh refused this way is remembered and runs automatically once
DGFT opens access, and the client’s dgftApiStatus
tells you in advance whether a client is in this window.
Related
- Authentication for auth failures and rate limits.
- Download eBRC PDF shows credential error recovery end to end.
- Push IRM Request Fields for every field’s format and constraints.