API overview
FIRMSapi looks up, searches and validates U.S. CBP FIRMS codes: the 4-character facility codes for piers, container freight stations, bonded warehouses, foreign trade zones and exam stations. The full parameter and schema reference is generated from the code: see the API reference.
Base URL
Section titled “Base URL”https://api.firmsapi.com/v1All requests and responses are JSON over HTTPS.
Authentication
Section titled “Authentication”Send your API key in the x-api-key header:
curl https://api.firmsapi.com/v1/firms/E430 -H "x-api-key: $FIRMSAPI_KEY"There are two kinds of key, both created in the portal:
| Key | Data | Counts toward your plan |
|---|---|---|
fapi_test_… |
Fixture data: a small sample of real FIRMS rows with approximate coordinates. Not for filing. | Never |
fapi_live_… |
The latest CBP FIRMS list | Yes, see Usage and quotas |
Test keys behave exactly like live keys, including plan limits on Pro and Enterprise endpoints, so you can build and test your integration before you go live. Keys are shown once when you create them; store them like passwords and never ship them in browser or mobile code.
Responses
Section titled “Responses”Every response has a meta object:
{ "data": { "code": "E430", "name": "MAHER TERMINAL", "status": "active", "...": "..." }, "meta": { "data_as_of": "2026-10-23", "source": "U.S. Customs and Border Protection (CBP) FIRMS code list", "mode": "live", "build_id": "20261023T060000Z-3f9a1c2e", "request_id": "Hc1x0jYxIAMEbXw=" }}data_as_of: the date of the CBP FIRMS list the answer comes from.source: where the data comes from. Test mode says it is fixture data.mode:liveortest, from the key you used.request_id: quote it when you contact support. It is also in thex-request-idheader.
Lists add meta.count, and paged lists add meta.next_cursor (pass it back as cursor; null means the last page).
Errors use one shape, described in Errors:
{ "error": { "code": "quota_exceeded", "message": "…", "links": { "docs": "…", "buy_pack": "…" } }, "meta": { … } }Endpoints
Section titled “Endpoints”| Endpoint | What it does | Plans |
|---|---|---|
GET /firms/{code} |
Look up a code, with the other codes at the same address | All |
GET /search |
Fuzzy search by name and/or address | All |
GET /autocomplete |
Prefix matches for type-ahead inputs | All |
GET /nearby |
Facilities near a point, another facility or an address | All |
POST /validate |
Pre-filing checks for a code | All |
POST /batch |
Up to 100 lookups, validations and searches | Pro, Enterprise |
GET /ports, GET /ports/{port} |
CBP ports and their facilities | All |
GET /changes |
Feed of FIRMS list changes | Pro, Enterprise |
/watchlists |
Codes you watch for changes | Enterprise |
Data you should know about
Section titled “Data you should know about”- Codes are not always a letter and three digits. About 31% are not, and some start with a digit. The only safe format check is four letters or digits.
- Deleted codes stay in the data with
status: "deleted", so you can tell why a filing was rejected. Search and nearby return active codes unless you passinclude_deleted=true. - Placeholders are flagged, not removed. CBP’s “DO NOT USE” rows and CBP test records have
junk: true. Lookups return them with a warning; search and nearby never do. - Many addresses carry several codes. A lookup lists the others in
same_address.
Limits
Section titled “Limits”Requests are rate limited across the API to protect the service (about 50 per second, bursts of 100). If you need more, contact us. Monthly call limits depend on your plan: see Usage and quotas.