# FIRMSapi Docs (full text) Source: https://docs.firmsapi.com/ --- # FIRMS codes explained URL: https://docs.firmsapi.com/concepts/firms-codes/ A **FIRMS code** (Facilities Information and Resources Management System) is the 4-character identifier U.S. Customs and Border Protection assigns to a place where imported goods can be unladen, stored or examined. Filers use it on entries, in-bond movements and location-of-goods data so CBP knows where the cargo is. ## Format A code is exactly four uppercase letters or digits. The only safe format check is: ```text ^[A-Z0-9]{4}$ ``` About a third of real codes are **not** a letter followed by three digits, and at least one starts with a digit. A stricter pattern rejects valid codes. To know whether a code is real, look it up. ## Facility types | Type | Meaning | | --- | --- | | `01` | Container freight station (CFS) | | `02` | Foreign trade zone (FTZ) | | `03` | Pier or terminal | | `04` | Bonded warehouse | | `05` | Inspection facility | | `06` | Importer's premises | | `07` | DP site | | `08` | CBP administrative site | | `09` | Centralized examination station (CES) | | `10` | Rail or air terminal (meaning inferred; CBP publishes no label) | | `11` | CBP test facility (flagged as junk) | Some codes have no type in CBP's list; the API returns `type: null` for those. ## Status: active and deleted CBP marks codes active or deleted. FIRMSapi keeps deleted codes: a lookup returns them with `status: "deleted"` and a warning instead of a 404, so old paperwork still resolves. Don't use a deleted code on a new filing; validation fails it (the reject ACE returns as 159). ## Junk rows The CBP list contains placeholders ("DO NOT USE") and CBP test facilities (type `11`). FIRMSapi flags these as junk: lookups return them with `junk: true` and a warning, and search and nearby leave them out. ## One address, many codes A single building often carries several codes, for example a bonded warehouse and a CFS run by the same operator, or codes for successive operators. Search results and the public code pages group codes at the same address. ## Ports Each code belongs to a CBP port, a 4-digit code such as `4601` (New York/Newark). Validation checks that the code is in the port on your filing. Browse codes by port at [firmsapi.com/ports](https://firmsapi.com/ports/). ## Freshness Every response includes `meta.data_as_of`, the date of the CBP list the answer came from. When CBP publishes an update, FIRMSapi diffs it into the changes feed. --- # FIRMSapi docs URL: https://docs.firmsapi.com/ FIRMSapi is a REST API for U.S. Customs and Border Protection FIRMS codes, the 4-character codes that identify piers, container freight stations (CFS), bonded warehouses, foreign trade zones (FTZ) and exam sites. Its core job is catching a wrong FIRMS code before ACE rejects the filing. It answers four questions: Pre-filing validation against the port and intended use, with the ACE reject each check prevents and a list of what still needs checking in ACE. Look up any code, active or deleted, with address, facility type, port and status. Fuzzy search and autocomplete over names, addresses and aliases. Facilities near a latitude and longitude, filtered by type. Get a key from the developer portal. Questions or a missing code? Every code also has a public page at {new URL(urls.site).host}/codes. --- # Plans and limits URL: https://docs.firmsapi.com/plans/ {PLAN_ORDER.map((k) => ( ))}
Plan Price Live calls / month Adds
{PLAN_NAMES[k]} {usd(plans.plans[k].price_usd)} / month {plans.plans[k].monthly_calls.toLocaleString('en-US')} {plans.plans[k].features.map((f) => FEATURE_LABELS[f] ?? f).join(', ') || 'Core endpoints'}
Every plan includes lookup, search, autocomplete, nearby and validation, and unlimited test-key calls. Compare plans on the pricing page. ## What counts as a call - Each **live-key** request that gets an answer counts once: a result, a failed validation (`valid: false`), or a code that isn't on the list (`404 not_found`). - In a batch, each request in it counts once. - **Never counted:** test keys, malformed requests (`400`), auth and plan errors, `429`, server errors (`5xx`), autocomplete, and adding or removing watchlist codes. Quotas run per calendar month in UTC and reset on the 1st. Full rules: usage and quotas. ## When you reach your quota Live calls draw from three sources, in order: 1. Your plan's monthly quota. 2. Your **call-pack** balance. A pack of {Object.values(plans.packs).map((p) => `${p.calls} calls costs ${usd(p.price_usd)}`).join('; ')}, bought once from the portal. When the balance runs low, the portal prompts you to buy another. 3. **Metered overage**, if you opted in: {usd(plans.overage.unit_price_usd)} per call up to a monthly cap you set, billed with your subscription. When all three are used up, requests return `429` with `error.code` `quota_exceeded` until the next month. ## Usage The developer portal shows calls this month by source (plan, pack, overage) and per day. --- # Quickstart URL: https://docs.firmsapi.com/quickstart/ export const base = `${urls.api}/v1`; 1. **Get a key.** Sign up at the developer portal. Your account starts on the Free plan with a test key (`fapi_test_…`). Copy it when it's shown: keys are displayed once. 2. **Set two environment variables.** 3. **Look up a code.** E430 is Maher Terminal in Elizabeth, NJ. ```bash curl "$FIRMSAPI_URL/firms/E430" -H "x-api-key: $FIRMSAPI_KEY" ``` ```js const res = await fetch(`${process.env.FIRMSAPI_URL}/firms/E430`, { headers: { 'x-api-key': process.env.FIRMSAPI_KEY }, }); const body = await res.json(); if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`); console.log(body.data.name, body.meta.data_as_of); ``` ```python import os import requests res = requests.get( f"{os.environ['FIRMSAPI_URL']}/firms/E430", headers={"x-api-key": os.environ["FIRMSAPI_KEY"]}, timeout=10, ) body = res.json() res.raise_for_status() print(body["data"]["name"], body["meta"]["data_as_of"]) ``` 4. **Search by name.** Paperwork rarely has the code. Search takes free text: ```bash curl -G "$FIRMSAPI_URL/search" --data-urlencode "q=maher terminal elizabeth" \ -H "x-api-key: $FIRMSAPI_KEY" ``` 5. **Validate before you file.** Check a code against the port on your filing and what you're using it for: ```bash curl "$FIRMSAPI_URL/validate" -H "x-api-key: $FIRMSAPI_KEY" \ -H "content-type: application/json" \ -d '{"code": "E430", "port": "4601", "use": "location_of_goods"}' ``` The response says whether the code is `valid` and lists `checks_passed`, `checks_failed` and `checks_not_possible`: things public data can't settle, such as bond status. See Validate before you file. 6. **Go live.** Create a live key (`fapi_live_…`) in the portal and swap it in. Nothing else changes. ## Every response - JSON, under `/v1`, authenticated with the `x-api-key` header. - `meta.data_as_of`: the date of the CBP list the answer came from. - `meta.source` and `meta.mode` (`live` or `test`). - Errors use one shape: `{"error": {"code": "...", "message": "...", "links": {...}}}`. See errors. ## Next - [FIRMS codes explained](/concepts/firms-codes/): facility types, deleted codes and why a regex is the wrong check. - API overview and the [API reference](/reference/): every endpoint and parameter. - [Plans and limits](/plans/): prices, quotas and what counts as a call. --- # Changelog ## 2026-10-23: firmsapi.com and the docs are live - Every active and deleted FIRMS code has a page at [firmsapi.com/codes](https://firmsapi.com/codes/), with its address, type, port, the other codes at the same address and nearby facilities. Placeholder and CBP test codes are left out. - Every CBP port has a page listing its codes at [firmsapi.com/ports](https://firmsapi.com/ports/). - The docs have a quickstart with curl, JavaScript and Python samples, and an API reference generated from the OpenAPI spec. - Pricing is on [firmsapi.com/pricing](https://firmsapi.com/pricing/), with a calculator for what FIRMS code errors cost you.