Skip to main content

Overview

Shipping bill extraction turns an ICEGATE PDF into structured JSON: the summary fields you need to file, the full parsed document, and a verification report saying whether the bill’s own totals reconcile. It is deterministic. The PDF’s text layer is read and fields are located by their printed labels. There is no model, so the same document always returns the same answer.

Base URL

The same base URL as every other eBRC endpoint:

Authentication

Use your eBRC API key. Extraction has no separate credential: the key you already send with filing requests authenticates it, and there is nothing to provision:
Create and manage keys in the console under API keys → eBRC.
Build against your dev_ key. The parse is identical either way (no DGFT sandbox is involved and nothing is filed), but the two keys draw on separate budgets, so anything you extract while integrating leaves your plan’s volume untouched. Switch to prod_ when you go to production. See Allowances.

Endpoints

Verification documents the checks run on every extraction.

Request format

  • multipart/form-data, one file per request, field name file
  • PDF only. The magic bytes are checked, not the filename or the declared type
  • Maximum 10 MB

Response format

Responses use the standard eBRC envelope, with the extraction under data:

Why scans are rejected

Only the text layer is read; pages are never rasterised or OCR’d. That is a deliberate limit, not a gap. A shipping bill downloaded from ICEGATE always carries text. A file without one is a scan or a phone photo, both unreadable to us and the easiest kind of document to alter. Rejecting it with a clear instruction is better than reading a picture of unknown provenance and returning figures you would then file against.

Allowances

Extraction is free for general use, and the two key types draw on separate budgets, so integrating never spends volume you paid for. Both counters reset on the 1st, IST. Higher volume is available on a paid plan. Plans, what each one includes, and your usage for the month sit together in the console under Billing. A plan’s extraction volume is a total, not an increment: it replaces the free 250 rather than stacking on it, and every rung’s total sits well above it.
Why test is capped at all, when test filings are unlimited: a sandbox filing produces no real certificate, so it is worthless and free. A sandbox extraction returns byte-identical, production-usable JSON. There is no degraded sandbox version of a parsed shipping bill. An uncapped test mode would simply be the product for free, so it is capped, just against its own budget.
GET /shipping-bills/usage reports the current period. It authenticates with your console session rather than an API key, because it is an account-level billing figure rather than a per-key counter:
planSlug and the two cap figures are whatever your account is actually on, so read them rather than hard-coding the free numbers above. live and test are independent budgets. total is only there for “how many bills did we process this month”. cap: null means unlimited. verified is how many of those passed every error-level verification check. The gap is documents that extracted cleanly but did not agree with their own totals.
enforced tells you whether the ceilings actually refuse work. It is true by default: an over-cap request is refused with 402 and the code below. Read the field rather than assuming, because an account can be set to record-only, in which case usage is counted and nothing is refused.

When the allowance runs out

Branch on errorCode, never on the message. There are two, and which one you get tells you which budget is exhausted: A document that fails to parse does not consume the allowance: the unit is claimed before the parse so concurrent requests cannot both take the last one, and handed back if the PDF turns out to be unreadable.

Getting started

  1. Create a dev_ key in the console under API keys → eBRC.
  2. POST a shipping bill PDF to /shipping-bills/platform/extract.
  3. Read data.fields for the summary, data.sections for the whole parsed document, and data.verification to see whether the bill reconciled with itself.
  4. Switch the key to prod_ when you go live.
One call returns all three, so there is never a reason to send the same PDF twice.