The federal contracting data layer

CAGE Code Lookup API

5-character DoD identifier in, full federal contractor profile out. JSON, one HTTP call.

5 letters or digits. Returns the current SAM contractor record and its UEI. Free, no account.

Try one:

A Commercial and Government Entity (CAGE) code is the 5-character alphanumeric identifier the Defense Logistics Agency assigns to every federal contractor location. DoD contracting officers, NATO partners, and many legacy procurement systems still key transactions on CAGE rather than UEI. This endpoint takes a CAGE and returns the entity it identifies: legal name, UEI, address, NAICS, certifications, registration status.

CAGE is nearly universal in the registry, which is why it stays a practical join key even after the 2022 move to UEI. As of the July 5, 2026 SAM extract, 788,881 of the 885,266 registered entities (89%) carry a CAGE code, across 793,402 distinct codes. A UEI usually maps to exactly one CAGE; a multi-facility organization can carry several, but that is rare, only 3,481 entities (0.4%) have more than one, and the most on any single UEI is 81.

Who this page is for: developers integrating DoD/DLA workflows where CAGE is the primary key. Contract administrators, defense subcontract teams, NSCM-aware ERP integrators, anyone who has CAGE codes in their data and needs to resolve them to a current federal contractor record.

What this page is NOT: a CAGE issuance or modification tool. CAGE codes are issued by DLA. This endpoint reads the public registration data; it doesn't write to it.

On this page:

What one call returns

You pass a CAGE code. You get the same response shape as our UEI-keyed endpoint, plus a queried_cage field echoing your input so you can confirm the match. The response resolves a registration block (status, dates, freshness) and the full entity block: legal name, address, primary_naics plus the complete naics_codes[] and psc_codes[] arrays, business-type certifications, and every cage_codes[] registered to that UEI.

Real response for CAGE 53YC5, fetched 2026-07-08, trimmed to fit:

{
  "queried_cage": "53YC5",
  "uei": "C111ATT311C8",
  "registration": {
    "status": "A",
    "active": true,
    "registration_date": "2013-11-12",
    "activation_date": "2026-04-29",
    "expiration_date": "2027-04-27",
    "expiring_soon": false,
    "source_extract_date": "2026-07-05"
  },
  "entity": {
    "legal_business_name": "K & K CONSTRUCTION SUPPLY INC",
    "dba_name": null,
    "entity_structure_code": "2L",
    "entity_url": "www.kkconstructionsupply.com",
    "physical_address": {
      "street1": "11400 WHITE ROCK RD",
      "city": "RANCHO CORDOVA", "state": "CA", "zip": "95742", "country": "USA"
    },
    "primary_naics": "444110",
    "naics_codes": ["332312Y", "423310Y", "444110Y", "484220Y", "..."],
    "psc_codes": ["3940", "5510", "5975", "..."],
    "business_types": ["2X", "8W", "A2", "HQ", "XS"],
    "business_types_labels": [
      "For Profit Organization",
      "Women-Owned Small Business (WOSB)",
      "Woman-Owned Business", "DOT Certified DBE", "Subchapter S Corporation"
    ],
    "cage_codes": ["53YC5"]
  }
}

On the Pro tier the same call also carries an inline FPDS prime-contract and FFATA sub-vendor activity block (fpds_obligated_total, fpds_distinct_contracts, sub_revenue_total, top_paying_primes), so one CAGE-keyed lookup returns the resolved entity's registration and its full federal activity together.

The CAGE code format (verified against 793,403 codes)

A CAGE code is exactly 5 uppercase alphanumeric characters. We checked every CAGE in the current SAM registry: all 793,403 are 5 characters and all uppercase alphanumeric (100%).

The letters I and O never appear in positions 2 through 4, 0 of 793,403 codes, a DLA design choice so they are not confused with the digits 1 and 0.

The pattern usually quoted, "a digit, three alphanumerics, a digit", holds for about 96% of codes (95.88% have a numeric first and fifth position). It is not a strict rule: roughly 1 in 25 codes (4%) carries a letter in the first or last position. A validator that requires the first and last characters to be numeric will wrongly reject those valid codes.

Validate on the reliable rule, not the strict one. To accept every real CAGE, match 5 uppercase alphanumerics. To also encode the I/O rule, exclude I and O from the middle three positions.
# accepts 100% of real CAGE codes
^[0-9A-Z]{5}$

# stricter: encodes the DLA I/O rule (still matches 100%)
^[0-9A-Z][0-9A-HJ-NP-Z]{3}[0-9A-Z]$

# DO NOT use this: rejects ~4% of valid codes
^[0-9][0-9A-Z]{3}[0-9]$

Sample real codes from the dataset: 141S8, 59NT1, 83QT3, 9BXU3, 5UE58.

Use cases this enables

Defense subcontract validation. Your prime contract names sub-tier suppliers by CAGE. Validate each one is currently active in SAM before order release. Combine with /api/v1/exclusions/search to check debarment status by UEI.
Legacy ERP enrichment. Your procurement system stores CAGE codes from 2005-era data when CAGE was the de facto primary key. Bulk-resolve them to current legal names, addresses, NAICS, and (especially valuable) modern UEIs. The uei field in the response gives you the bridge.
NATO supplier verification. NATO uses an extended CAGE system (NCAGE for non-US suppliers). This endpoint covers the US CAGE space. Useful when checking US-side counterparties on a NATO purchase order.
Receiving-dock reverse lookup. The packing slip has a CAGE; you need to know if it's still a valid supplier and where they're headquartered. One call, full record.
FAR-clause flow-down audit. Federal prime contractors must verify each subcontractor's small-business and socio-economic status. CAGE → entity → business_types array tells you what self-certifications the supplier has on file with SAM at the moment you check.

How to call the API (curl, Python, JavaScript)

A single authenticated GET. Auth via Authorization: Bearer <api_key>.

curl -H "Authorization: Bearer $API_KEY" \
     https://govconapi.com/api/v1/entities/by-cage/53YC5

Python (requests):

import requests

r = requests.get(
    "https://govconapi.com/api/v1/entities/by-cage/53YC5",
    headers={"Authorization": f"Bearer {API_KEY}"},
    timeout=15,
)
r.raise_for_status()
data = r.json()
print(data["entity"]["legal_business_name"], data["uei"])
# K & K CONSTRUCTION SUPPLY INC C111ATT311C8

JavaScript (fetch):

const res = await fetch(
  "https://govconapi.com/api/v1/entities/by-cage/53YC5",
  { headers: { Authorization: `Bearer ${API_KEY}` } }
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { entity, uei } = await res.json();
console.log(entity.legal_business_name, uei);

Resolving a batch of CAGE codes (the legacy-ERP enrichment case). One lookup per code; skip 404s and back off on 429:

import requests, time

def resolve(cage):
    r = requests.get(f"https://govconapi.com/api/v1/entities/by-cage/{cage}",
                     headers={"Authorization": f"Bearer {API_KEY}"}, timeout=15)
    if r.status_code == 404:            # superseded / NCAGE / not in current SAM data
        return None
    if r.status_code == 429:            # rate limited: honor Retry-After, then retry
        time.sleep(int(r.headers.get("Retry-After", 2)))
        return resolve(cage)
    r.raise_for_status()
    return r.json()

# Developer tier allows 1,000 requests/hour across the API
resolved = {cage: resolve(cage) for cage in my_cage_codes}

The CAGE in the path is normalized: lowercase and surrounding whitespace are accepted and converted to canonical uppercase.

Error shapes:

CAGE vs UEI: when to use which

Both identify the same underlying entity. Pick by what you have on hand:

One entity can have multiple CAGE codes (one per registered facility), though as noted above that is uncommon: 3,481 entities carry more than one, and the largest carries 81. Most have exactly one. The cage_codes[] array in any entity response lists all CAGE codes registered to that UEI.

Combining with other endpoints

What this doesn't do (data caveats)

Near-real-time, not real-time. We track SAM and refresh as upstream data publishes. In rare cases there can be up to ~30 days of latency between a registration changing on sam.gov and the change appearing here. The source_extract_date field tells you the freshness of any given record. For time-sensitive compliance decisions, verify directly with sam.gov as the system of record.
NCAGE codes for non-US suppliers ARE covered, with one gap. A CAGE code for an entity located outside the US and its territories is an NCAGE, assigned through the NATO Codification System rather than by DLA. Any foreign entity registered in SAM carries its NCAGE in the same field, so this endpoint resolves it: as of the current extract we hold 32,925 NCAGE codes across 37,305 non-US registered entities (88.3%), led by Canada, the UK, South Korea, Japan and Germany. The genuine gap is a foreign supplier that holds an NCAGE but has never registered in SAM , that one will not resolve here.
A 404 usually means the code was never in SAM, or the registration was deactivated. A CAGE can be obtained from DLA without a SAM registration at all , for a facility security clearance, to get a DODAAC, or to satisfy the FAR 4.18 ownership-of-offeror requirement , and those never appear in the public registration data. Separately, when a registration is deactivated the CAGE is released back to DLA the next business day. For an entity that is not required to register in SAM, FAR 4.1803(b) directs the contracting officer to validate the code at cage.dla.mil instead.

Sources

This endpoint reads the public entity-registration data that federal contractors file; it does not issue or modify CAGE codes. The authoritative sources for the CAGE system itself:

The figures on this page, 793,403 CAGE codes, 788,881 entities carrying a CAGE (89% of 885,266), and the positional-format checks, were computed 2026-07-08 from the July 5, 2026 SAM entity extract this API serves. Every response carries a source_extract_date so you can see the freshness of the underlying record.

Pricing

This endpoint is on the Developer tier ($19/mo): 1,000 requests/hour across the whole API surface, single CAGE lookup, single UEI lookup, name search, exclusions search, FPDS prime contract + SAM Award Notice endpoints, opportunities. Pro ($39/mo) adds award-history merge, multi-filter entity search, expiration radar, seven-signal vendor-risk screening, and the Federal Subawards (FFATA) API. Pro responses on this endpoint also include inline fpds_obligated_total + fpds_distinct_contracts (FPDS prime contract activity) and sub_revenue_total + top_paying_primes (FFATA sub-vendor income) so a single CAGE-keyed lookup surfaces the resolved entity's full federal activity alongside its registration data.

No annual contracts, no setup fees, monthly billing via Stripe. Cancel anytime.

FAQ

Can one CAGE belong to multiple entities?

No. DLA assigns each CAGE to one entity (one specific facility of one company). The reverse, multiple CAGEs per entity, is common for organizations with multiple registered locations.

What if I have a 6-character or 7-character "CAGE"?

It is not an NCAGE: those are also five characters, alphanumeric, uppercase, no spaces, exactly like a US CAGE. A longer string is usually a DODAAC, a DUNS fragment, or a 12-character UEI. Anything other than five characters is out of spec for this endpoint and will 404.

What's the difference between CAGE and DUNS?

CAGE is DoD-issued (DLA, since the 1950s). DUNS was D&B-issued and used in non-DoD federal procurement until 2022, when it was replaced by UEI. CAGE survived the transition; DUNS didn't. CAGE is still in active use across DoD and FAR-regulated procurement.

How fresh is the data?

We refresh as upstream data publishes. In rare cases there can be up to ~30 days of latency between a CAGE record updating on sam.gov and the change appearing here. The source_extract_date field tells you which snapshot the record came from.

Can I look up entities by other identifiers (DUNS, EIN, FEIN)?

No. UEI and CAGE are the only public-key lookups we support. EIN/FEIN are not in the public SAM dataset (taxpayer identification is restricted). DUNS is retired.

Is the response shape identical to the UEI-lookup endpoint?

Almost. We add a queried_cage field to the top of the response so callers can confirm which CAGE was used to resolve the entity. Everything else (registration block, entity block) is identical.