Skip to main content
Successful responses are wrapped in the standard envelope documented in the API Reference introduction. Errors are not wrapped; they use the shape below.

Error body

HTTP status codes

Common validation errors

Validation failures return 400 with message: "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 successful push-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 category 01 being titled “Exports (of Goods)“: Three cases are deliberately never warned about, because the annexure does not support the inference:
  • Any category on uploadType 102 (Softex). The category 01 descriptions name SOFTEX themselves — P0101 is “covered under GR/PP/SOFTEX/EC copy of shipping bills” and P0103 is “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.
A warning here does not mean the filing was rejected. It was accepted and forwarded; check the purpose code against the IRM your bank shared before DGFT’s status poll answers.

DGFT error codes

DGFT validates every record on its own side, hours after the filing is accepted. Its codes arrive in errorDetails 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:
If a DGFT_NO_DATA surprises you for an IRM you know exists, widen fromDate/toDate around the period the remittance was actually received, or drop them entirely to search three years.

DGFT credential error codes

Endpoints that operate on a customer’s DGFT connection return a structured error when that connection fails. Branch on errorCode, 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.