Search
When a prime contractor awards a first-tier subcontract, FAR 52.204-10 obliges it to file a report naming the sub-vendor, the amount and the prime contract the money came from. Those reports are the only public record of who actually performs federal work below the prime, and this endpoint searches them.
It reads in both directions. Give it a prime's UEI and you get the sub-vendors that prime paid. Give it a sub-vendor's UEI and you get the primes paying it, which is the teaming question asked backwards. Give it a contract PIID and you get that one contract's whole subcontract flow.
Subawards are a base data layer, so every plan reaches this endpoint and there is no capability gate on it. Coverage begins with FY2025 on every plan, which is a data floor rather than a plan limit, and Search Window states what that floor means for date filters. For current row counts and freshness call /api/v1/status.
One call, nothing to set up beyond a key:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://govconapi.com/api/v1/subawards/search?prime_uei=H11HD5VHGHN3&limit=2&fields=subawardee_name,subaward_amount,subaward_action_date,prime_award_piid"
{
"data": [
{"subawardee_name": "ELECTROMET CORPORATION", "subaward_amount": 69029.02, "subaward_action_date": "2025-02-28", "prime_award_piid": "N0002424F6216", "subaward_sam_report_id": "CEE04968-FCBA-11EF-8E2A-E7034F2D18CD"},
{"subawardee_name": "MACOM TECHNOLOGY SOLUTIONS INC.", "subaward_amount": 84300.0, "subaward_action_date": "2025-02-28", "prime_award_piid": "FA821023F0009", "subaward_sam_report_id": "DFAF7D06-FCB8-11EF-8E2A-E7034F2D18CD"}
],
"pagination": {"limit": 2, "offset": 0, "total": 636, "total_is_estimate": false, "has_next": true}
}
Two of the 636 reports Lockheed Martin has filed as a paying prime, each naming the sub-vendor, the amount and the contract the money came from.
Endpoints
GET /api/v1/subawards/search, search the reports by prime, sub, contract, agency, NAICS or sub-vendor nameGET /api/v1/subawards/{subaward_sam_report_id}, one report by its ID, documented at Single FFATA reportGET /api/v1/companies/{uei}/subawards, the prime-side rollup with a summary block, documented at Subs paid by a primeGET /api/v1/companies/{uei}/prime-relationships, the sub-side rollup with a top-primes leaderboard, documented at Primes that paid a sub
One row is one report, not one subcontract
This is the trap that silently inflates every total built on this endpoint. The unit of the corpus is the FFATA report, keyed by subaward_sam_report_id, and a single subcontract produces a new report every time a reported data element changes. FAR 52.204-10(f) is explicit about the trigger: continued reporting on the same subcontract is not required unless one of the reported data elements changes. It sets when a fresh report is filed, not what that report's amount means, and the corpus answers that question for itself: where one purchase order carries several reports, most of those sets restate a different subaward_amount rather than repeating one.
So subaward_number, the prime's own purchase-order identifier, repeats across rows. The second example below shows one purchase order carrying twelve reports. Summing subaward_amount over rows counts that money twelve times. Group by subaward_number within a prime_award_piid and take the latest report when you want a subcontract-level figure.
prime_award_amount describes the prime contract as of the report, and it moves. It is USAspending's obligated-value view of the prime award at the moment that report was compiled, so reports filed months apart under one PIID carry different figures: most rows in the searchable window sit on a PIID where this field is not constant, and the contract in the second example carries nine distinct values across the twelve reports one piid call returns. Treat it as an attribute of the report, never of the contract. Do not lift it out of a group with MAX() or an arbitrary row, and do not multiply it across sub-vendors. When you want one prime figure per contract, take it from that contract's most recently modified report, or read the prime side from Contract detail.
It is also not a ceiling: a single subaward row can exceed it several times over, which the third example shows. A subcontracted-share ratio built on it is a useful signal rather than a percentage of a budget, and can legitimately land above 1.0. The ratio is computed for you, per contract, in the Pro subaward_rollup block on Contract detail.
subaward_amount can be negative. Downward adjustments are filed as reports carrying negative values, exactly as FPDS files deobligations, and 0.00 appears as well. They are real records and they belong in a net figure, so amount_min=0 is the switch that excludes them and sort_order=asc on subaward_amount is the fastest way to see them. A negative row can also be the newest report on its purchase order, so a "take the latest" rollup returns a negative subcontract value on a small share of purchase orders rather than an error.
What a clean search does not prove
Coverage is bounded by the reporting rule, so an empty or thin result is frequently a reporting-threshold fact rather than a business fact.
Only first-tier subcontracts are reported, and only above a dollar threshold. FAR 4.1403(a) sets that threshold at $40,000, raised in August 2025 from the $30,000 that applied earlier in the covered period, so a value floor applied across the whole corpus does not sit on one number. Second-tier and lower subcontracts are never reported by anyone. FAR 52.204-10(g) adds two more holes: a prime whose gross income in the previous tax year was under $300,000 is exempt from reporting subcontract awards at all, and no prime has to report a subcontractor whose previous-year gross income was under $300,000.
One firm can hold several UEIs, and sub_uei finds exactly one of them. Searching sub_name=crane electronics returns rows under three different UEIs in three states, each with its own spelling of the name. A UEI is a registration, not a company, so the reliable order is to discover the identities by name, read the distinct subawardee_uei values back, then query each one. The last example does this.
sub_name is a case-insensitive substring match on the whole name. It matches inside words, so crane reaches KONECRANES NUCLEAR EQUIPMENT & SERVICES, LLC and OVERHEAD HOIST & CRANE INC alongside the firm you meant. % and _ are matched literally rather than as wildcards. The same substring effect bites subawardee_business_types, which arrives as one comma-separated string rather than an array: the corpus spells the categories out in full, so VETERAN-OWNED BUSINESS is a substring of SERVICE-DISABLED VETERAN-OWNED BUSINESS, WOMEN-OWNED SMALL BUSINESS is a substring of the EDWOSB joint-venture label, and PROFIT ORGANIZATION catches non-profits. Split the cell on the comma and compare whole values.
The source spells one country two ways, so a client-side country filter loses rows. subawardee_country_code arrives as FFATA published it, and the same country appears under both its three-letter and its two-letter code. It is not a split between firms: GOODRICH LIMITED, one UEI, appears under contract N0001924F1885 as GB on the reports filed through January 2025 and as GBR on the reports filed after, and hundreds of sub-vendor UEIs carry both spellings somewhere in the searchable window. A filter written for GBR silently drops the GB rows and reads as a shrinking supplier. Match on both forms, or normalize to two letters before you compare. subaward_pop_country_code mixes the two spellings the same way, and subawardee_state_code carries whatever subdivision label the sub-vendor's country uses.
agency filters at FPDS agency-code grain, and a term below that grain resolves upward. The filter turns your term into FPDS agency and sub-agency codes, then matches the prime award's codes. A department term therefore carries its whole family: Department of Defense or DOD returns the Army, Navy, Air Force, DLA, MDA and the rest together. A component that holds its own code answers precisely, and DLA, DARPA, DISA, DTRA, MDA and SOCOM each return only their own rows.
A contracting command sits below that grain, so it resolves to the service that funds it. NAVSEA, NAVAIR, NAVFAC and NAVSUP each return the Navy's rows, matching Navy exactly; USACE returns the Army's rows, matching Army exactly. That is the resolution you want when you are asking who funds the work, and it is the wrong cut if you meant one command: the numbers will look like a command's and be a service's. Terms outside the resolver's vocabulary return 400 instead, which is where most spelled-out command names and many agency acronyms land, Naval Sea Systems Command and DCMA among them. prime_award_awarding_sub_agency_name on each row is the finest agency grain the response carries, so read it back to see which service you actually got, and plan a command-level cut off the prime contract rather than off this filter.
Parameters
| Parameter | Type | Description |
|---|---|---|
prime_uei |
string | The paying prime's 12-character UEI, matched exactly against prime_awardee_uei. Case-insensitive, so a lowercase UEI works. Anything that is not exactly 12 characters returns 422, including a value padded with spaces, so trim before you send. A selector. |
sub_uei |
string | The receiving sub-vendor's 12-character UEI, matched exactly against subawardee_uei. Same normalization and same 422. Matches a different column from prime_uei, so the two answer opposite questions. A selector. |
piid |
string | The prime award PIID, matched exactly against prime_award_piid after trimming and upper-casing, so a padded or lowercase contract number works. Not a prefix or substring match, so a partial contract number returns zero rows rather than a family. Over 80 characters returns 422. A selector. |
agency |
string | Awarding agency, given as a name (Department of Veterans Affairs), an acronym (DOD, GSA, NASA) or an FPDS agency code (097, 1700). Resolved to codes and matched against the prime award's awarding agency and sub-agency, so a department term also returns its sub-agencies and a command resolves to its parent service, see the trap above. A term that resolves to no agency returns 400; over 200 characters returns 422. A selector. |
naics |
string | Exactly 6 digits, matched exactly against prime_award_naics_code. This is the prime contract's NAICS, not the sub-vendor's line of work. Anything that is not 6 digits returns 400; a well-formed code with no rows returns 200 and total 0. A selector. |
sub_name |
string | Case-insensitive substring of subawardee_name. Matches inside words, and % and _ are literal. Under 3 characters or over 200 returns 422. A selector. |
date_from, date_to |
date | YYYY-MM-DD bounds on subaward_action_date, inclusive. Anything else returns 400. A date_from earlier than the coverage floor is clamped up rather than rejected, and the window block reports it. Optional. |
amount_min, amount_max |
number | Inclusive bounds on subaward_amount in dollars. 0 is honored as a bound, so amount_min=0 is how you drop the negative adjustment rows. value_min and value_max are accepted aliases; sending a canonical name and its alias together returns 400 rather than silently dropping one. A non-finite value such as inf or nan returns 400. Optional. |
sort_by |
string | See Ordering below. Optional. |
sort_order |
string | asc or desc, defaulting to desc. Optional. |
limit, offset |
integer | Page size and offset. limit defaults to 100 and is capped by your plan, see Plans and Limits. limit below 1 or offset below 0 returns 422. Optional. |
fields |
string | Comma-separated projection, supported on this endpoint, up to 50 names; more than that returns 400. subaward_sam_report_id is always returned whether or not you list it. Reaches only the fields in the Response table below. An unknown name returns 400 naming the valid set whenever the query matches at least one row; on a zero-row result there is no row to validate against and the call returns 200 with an empty data, so confirm a projection against a query you know matches. See Response Shaping for the syntax. Optional. |
At least one selector must be present. A call carrying only dates, amounts, sort or paging returns 400 naming all six, because the alternative is handing out the whole corpus one page at a time. Everything you do send is combined with AND, with no OR form, so a multi-value query is several requests.
Repeating a parameter is not an OR either, and it is not an error: the last value wins and the earlier one is discarded, so ?naics=334511&naics=332993 answers with the 332993 result set alone. filters_applied echoes what actually took effect, including the injected date_from and the value that survived a repeat, which is the cheapest way to confirm a filter was read the way you meant it.
Ordering
sort_by accepts subaward_action_date (the default), subaward_amount and subaward_sam_report_last_modified_date. Anything else returns 400 with the allowlist in the message, never a silent fallback. sort_order accepts asc or desc and defaults to desc.
All three sort columns are populated on every row, so ordering never has a null to place. Every result is tie-broken on subaward_sam_report_id, which matters on this corpus: a contract's reports routinely share one subaward_action_date, and the tie-break is what stops a row shifting between pages while you page through a result set.
Sorting by subaward_amount ascending leads with the negative revision rows described above, which makes it the quickest audit of a prime's downward adjustments.
Pagination
Offset-based, with limit and offset. The default page size and the per-plan cap are in the Parameters table and in Plans and Limits; a limit above your cap returns 402 rather than a silently shortened page.
total is counted behind a ceiling of 10,000. A query matching more rows reports total as 10,000 with total_is_estimate set to true, which is your signal that the real figure is higher. offset still pages past the ceiling, so a bulk read is not capped at 10,000 rows; it is the count that stops, not the data. has_next reports page fullness rather than a lookahead, so a final page that exactly fills limit reports true and the following page comes back empty. When total_is_estimate is false, page against total instead, or narrow by naics, agency or a date range until it is.
Response
One record, with the full envelope, untrimmed:
{
"data": [
{
"subaward_sam_report_id": "DFAF7D06-FCB8-11EF-8E2A-E7034F2D18CD",
"subaward_number": "4106601389",
"subaward_action_date": "2025-02-28",
"subaward_amount": 84300.0,
"subaward_description": "IC RF AMPLIFIER DC-15GHZ 15DB GAIN.",
"subaward_sam_report_last_modified_date": "2025-03-04T00:00:00+00:00",
"prime_award_piid": "FA821023F0009",
"prime_award_parent_piid": "FA865623DA017",
"prime_award_amount": 46913960.0,
"prime_award_project_title": null,
"prime_award_naics_code": "332993",
"prime_award_naics_description": "AMMUNITION (EXCEPT SMALL ARMS) MANUFACTURING",
"prime_award_awarding_agency_name": "Department of Defense (DOD)",
"prime_award_awarding_sub_agency_name": "DEPT OF THE AIR FORCE",
"prime_awardee_uei": "H11HD5VHGHN3",
"prime_awardee_name": "LOCKHEED MARTIN CORPORATION",
"prime_awardee_parent_uei": "H11HD5VHGHN3",
"prime_awardee_parent_name": "LOCKHEED MARTIN CORPORATION",
"prime_awardee_state_code": "NY",
"prime_awardee_country_code": "USA",
"subawardee_uei": "P7Z6EXT3R5M5",
"subawardee_name": "MACOM TECHNOLOGY SOLUTIONS INC.",
"subawardee_parent_uei": "P7Z6EXT3R5M5",
"subawardee_parent_name": "MACOM TECHNOLOGY SOLUTIONS INC.",
"subawardee_business_types": "FOR-PROFIT ORGANIZATION,MANUFACTURER OF GOODS",
"subawardee_state_code": "MA",
"subawardee_country_code": "USA",
"subaward_pop_state_code": null,
"subaward_pop_country_code": "USA",
"usaspending_permalink": "https://www.usaspending.gov/award/CONT_AWD_FA821023F0009_9700_FA865623DA017_9700/"
}
],
"pagination": {
"limit": 1,
"offset": 1,
"total": 636,
"total_is_estimate": false,
"has_next": true
},
"filters_applied": {
"prime_uei": "H11HD5VHGHN3",
"date_from": "2024-10-01",
"sort_by": "subaward_action_date",
"sort_order": "desc"
},
"window": {
"plan_window_days": 1825,
"earliest_searchable": "2024-10-01",
"clamped": true,
"reason": "Default search window is the earliest data we carry. This is a data coverage floor, not a plan limit."
},
"_sources": ["usaspending_ffata"]
}
| Field | Type | Meaning | Source |
|---|---|---|---|
data |
array | The matching reports, one object per report, fields below. | FFATA subaward reports |
subaward_sam_report_id |
string | The report's unique ID and the key for single-report lookup. Uppercase UUID. Always present, including in a fields= projection. |
FFATA subaward reports |
subaward_number |
string or null | The prime's own purchase-order or subcontract identifier. Not unique: the same value recurs across reports for one subcontract, and primes assign these independently of each other. | FFATA subaward reports |
subaward_action_date |
date | Date of the subaward action, YYYY-MM-DD. The axis date_from, date_to and the default sort all use. |
FFATA subaward reports |
subaward_amount |
number | Subaward value in dollars. Negative on a downward adjustment, and 0.00 occurs as a filed value. |
FFATA subaward reports |
subaward_description |
string or null | The prime's free-text description of what was subcontracted, often a part name or a line of scope. | FFATA subaward reports |
subaward_sam_report_last_modified_date |
timestamp | When the report itself was last modified, with a timezone offset. The only timestamp on the row; every other date field is a plain YYYY-MM-DD. |
FFATA subaward reports |
prime_award_piid |
string or null | PIID of the prime contract the money flows from. The join key to Contract detail, and the key to group subaward rows by contract. Grouping on it does not make prime_award_amount constant inside the group, see the trap above. |
FFATA subaward reports |
prime_award_parent_piid |
string or null | PIID of the parent vehicle when the prime award is a task or delivery order. Null when the prime award is a standalone contract rather than an order, which is a large part of the corpus. | FFATA subaward reports |
prime_award_amount |
number or null | USAspending's obligated-value view of the prime award, as of the moment this report was compiled. Reports filed at different times under one PIID carry different figures, so it is an attribute of the report rather than of the contract, and it is not a ceiling on the subawards beneath it. | FFATA subaward reports |
prime_award_project_title |
string or null | The prime award's project title. Null throughout the contract subawards this endpoint serves. | FFATA subaward reports |
prime_award_naics_code |
string or null | The prime contract's 6-digit NAICS. What naics filters on. |
FFATA subaward reports |
prime_award_naics_description |
string or null | Plain-language name of that NAICS code, upper-cased at source. | FFATA subaward reports |
prime_award_awarding_agency_name |
string or null | The awarding department, spelled at the top tier, so a Navy contract reads as Defense here. Read prime_award_awarding_sub_agency_name for the service. |
FFATA subaward reports |
prime_award_awarding_sub_agency_name |
string or null | The awarding sub-agency, for example DEPT OF THE NAVY or DEFENSE LOGISTICS AGENCY. The precise agency read on this row. |
FFATA subaward reports |
prime_awardee_uei |
string or null | The paying prime's UEI. What prime_uei filters on. |
FFATA subaward reports |
prime_awardee_name |
string or null | The paying prime's name as the report spells it. | FFATA subaward reports |
prime_awardee_parent_uei |
string or null | The prime's declared corporate parent. Repeats prime_awardee_uei on about a third of rows, so equality here is not evidence of a hierarchy. |
FFATA subaward reports |
prime_awardee_parent_name |
string or null | Name for that parent UEI. | FFATA subaward reports |
prime_awardee_state_code |
string or null | The prime's two-letter state code. | FFATA subaward reports |
prime_awardee_country_code |
string or null | The prime's country as the report spells it. Three letters on all but a handful of rows, which spell the country name out instead. | FFATA subaward reports |
subawardee_uei |
string or null | The receiving sub-vendor's UEI. What sub_uei filters on, and the key to pivot a name search onto. |
FFATA subaward reports |
subawardee_name |
string or null | The sub-vendor's name as the report spells it. What sub_name searches. Spelling varies between reports for one firm. |
FFATA subaward reports |
subawardee_parent_uei |
string or null | The sub-vendor's declared corporate parent. Null on close to half the rows; where it is present it repeats subawardee_uei about half the time, so equality here is not evidence of a hierarchy. |
FFATA subaward reports |
subawardee_parent_name |
string or null | Name for that parent UEI. | FFATA subaward reports |
subawardee_business_types |
string or null | The sub-vendor's socio-economic and organizational categories as one comma-separated string, spelled out in full rather than abbreviated. Split on the comma and compare whole values. | FFATA subaward reports |
subawardee_state_code |
string or null | Two letters on a US sub-vendor. On a foreign one it is usually null, but several hundred foreign rows carry the country's own subdivision code or a region name instead (GB-HAM, N.L., NEW SOUTH WALES, BAGHDAD), which can run well past two characters. Length-check it before you read it as a US state. |
FFATA subaward reports |
subawardee_country_code |
string or null | The sub-vendor's country as the report spells it. Predominantly USA, with a real foreign tail, and the source publishes both the three-letter and the two-letter form of the same country, sometimes for one firm under one contract. Match on both spellings, see the trap above. |
FFATA subaward reports |
subaward_pop_state_code |
string or null | Place-of-performance state for the subaward. Null on most reports, so it carries a place for a minority of rows rather than for the corpus. | FFATA subaward reports |
subaward_pop_country_code |
string or null | Place-of-performance country for the subaward. Mostly USA, with a real foreign tail spread over more than a hundred country codes, and it mixes the two-letter and three-letter spellings the same way subawardee_country_code does. Filtering to USA client-side drops the reports performed abroad. |
FFATA subaward reports |
usaspending_permalink |
string or null | Link to the prime award on USAspending, for verifying any row against the source. | FFATA subaward reports |
pagination |
object | limit, offset, total, total_is_estimate, has_next. See Pagination above. |
Derived |
filters_applied |
object | The filters that actually took effect, including the injected date_from and the resolved sort. |
Derived |
window |
object | plan_window_days, earliest_searchable, clamped, and when clamping happened a reason and the original date_from_requested. See Search Window. |
Derived |
_sources |
array | Upstream sources behind the response, always usaspending_ffata here. See Response Sources. |
Derived |
The row is a projection, not the whole report. These 30 fields are the supply-chain read, chosen so one call answers who paid whom, how much, under which contract and for which agency. The full FFATA report carries more than a hundred columns, and the ones deliberately not on this row are worth naming so you do not plan around them. There is no DUNS column, and nothing is out of reach without it: every row carries a 12-character UEI on both the prime and the sub side, with no null and no malformed value anywhere in the table, so prime_uei and sub_uei address the whole corpus and a DUNS lookup would add no coverage. There are no Treasury account symbols, which the source publishes as pipe-delimited text inside a single cell. And there are no highly-compensated-officer fields: FAR 52.204-10(d)(3) only requires them when the sub-vendor drew 80 percent or more of its annual gross revenue from federal awards and $25,000,000 or more of it, and its executive compensation is not already public through SEC or IRS filings, which excludes both the small vendors and the publicly listed primes and leaves a narrow band in between.
Errors
| Code | Trigger |
|---|---|
400 |
No selector sent. The message names all six. |
400 |
naics that is not exactly 6 digits. |
400 |
agency that resolves to no federal agency. Most spelled-out command names land here; a command acronym the resolver knows resolves to its parent service instead. |
400 |
sort_by or sort_order outside its allowlist, with the allowlist in the message. |
400 |
date_from or date_to that is not YYYY-MM-DD. |
400 |
amount_min sent with value_min, or amount_max with value_max, in one request. |
400 |
A money bound that is not a finite number, such as amount_min=inf. |
400 |
fields that is empty, or that carries more than 50 names. |
400 |
fields naming a field this endpoint does not return, on a query that matches at least one row. A zero-row query returns 200 instead, because the projection is checked against the rows it would filter. |
400 |
A query too broad for the database to evaluate inside its time budget. The message names the filters that narrow it. |
402 |
limit above your plan's page size. |
422 |
prime_uei or sub_uei that is not exactly 12 characters, piid over 80 characters, agency over 200, sub_name under 3 or over 200, limit below 1, or offset below 0. |
Shared codes and their meanings are in Error Codes.
Examples
A prime's largest sub-vendors. Sorting a prime's reports by value descending is the supply-chain map, most significant relationship first.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://govconapi.com/api/v1/subawards/search?prime_uei=H11HD5VHGHN3&sort_by=subaward_amount&sort_order=desc&limit=3"
{
"data": [
{"subawardee_name": "CAES SYSTEMS LLC", "subawardee_uei": "MMA7H4NEMCT9", "subaward_amount": 30788348.92, "subaward_action_date": "2024-11-12", "prime_award_piid": "N0002420C5503", "prime_awardee_name": "LOCKHEED MARTIN CORPORATION"},
{"subawardee_name": "CRYSTAL GROUP, INC", "subawardee_uei": "V73QNVKJWAJ9", "subaward_amount": 18849110.0, "subaward_action_date": "2025-02-27", "prime_award_piid": "N0002424F6216", "prime_awardee_name": "LOCKHEED MARTIN CORPORATION"},
{"subawardee_name": "MERCURY SYSTEMS INC", "subawardee_uei": "J51ULX3CNCZ4", "subaward_amount": 14397574.54, "subaward_action_date": "2024-11-12", "prime_award_piid": "N0002420C5503", "prime_awardee_name": "LOCKHEED MARTIN CORPORATION"}
],
"pagination": {"limit": 3, "offset": 0, "total": 636, "total_is_estimate": false, "has_next": true}
}
Lockheed Martin's three largest reported subawards run from $30.8M down to $14.4M, and two of the three sit on one contract, N0002420C5503, both dated 2024-11-12. Two suppliers taking $45.2M off the same contract on the same day reads as one subcontracting round rather than two independent relationships, and prime_award_piid is what tells you so. The other 633 reports are reachable by offset.
One purchase order, twelve reports. Filtering on piid returns every report under a contract, and sorting by report modification date walks them in filing order, which is where both the duplicate-report effect and the moving prime figure become visible. Trimmed to the fields those two effects live in, three reports per page:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://govconapi.com/api/v1/subawards/search?piid=693KA924F00033&sort_by=subaward_sam_report_last_modified_date&sort_order=desc&limit=3&fields=subaward_number,subawardee_name,subaward_amount,prime_award_amount,subaward_sam_report_last_modified_date"
{
"data": [
{"subaward_sam_report_id": "C9BC37E7-647F-41D9-923F-9641E97C7C78", "subaward_number": "P010284824", "subawardee_name": "NAS SCIENCES LLC", "subaward_amount": 123804.8, "prime_award_amount": 74873221.87, "subaward_sam_report_last_modified_date": "2026-05-21T00:00:00+00:00"},
{"subaward_sam_report_id": "AEE48121-EBDB-4DB1-984A-E7DA1639B777", "subaward_number": "P010284824", "subawardee_name": "NAS SCIENCES LLC", "subaward_amount": 30000.0, "prime_award_amount": 74582221.87, "subaward_sam_report_last_modified_date": "2026-04-15T00:00:00+00:00"},
{"subaward_sam_report_id": "080F1810-EC3B-4377-8CA5-E2F36E17F6CD", "subaward_number": "P010284824", "subawardee_name": "NAS SCIENCES LLC", "subaward_amount": 6000.0, "prime_award_amount": 68837158.51, "subaward_sam_report_last_modified_date": "2026-03-12T00:00:00+00:00"}
],
"pagination": {"limit": 3, "offset": 0, "total": 12, "total_is_estimate": false, "has_next": true}
}
All twelve of this contract's reports name one purchase order, P010284824, and one sub-vendor; these are the three most recently modified, and total tells you the other nine are an offset away. Each report restates a different subaward_amount, $123,804.80, $30,000.00 and $6,000.00 here, so adding the twelve together would charge one purchase order twelve times rather than measure it. prime_award_amount moves with them, $68,837,158.51 to $74,873,221.87 across these three alone: it reads the prime contract's obligated value at each filing, which is why it cannot be lifted out of a PIID group as a constant. Group by subaward_number before summing, and take the prime figure from the newest report rather than from whichever row you happened to read first.
Why prime_award_amount is not a ceiling. The prime figure comes from the prime award record, and the subaward figures come from the prime's own reports, so the two can disagree sharply.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://govconapi.com/api/v1/subawards/search?piid=N0001918F6034&sort_by=subaward_amount&sort_order=desc&limit=2"
{
"data": [
{"subawardee_name": "BAE SYSTEMS INFORMATION AND ELECTRONIC SYSTEMS INTEGRATION INC.", "subaward_amount": 28000000.0, "prime_award_amount": 950114.0, "prime_awardee_name": "BOEING COMPANY, THE", "prime_award_parent_piid": "N0001916G0001", "subaward_action_date": "2026-06-12"},
{"subawardee_name": "THE DANNER CORPORATION", "subaward_amount": 454826.84, "prime_award_amount": 950114.0, "prime_awardee_name": "BOEING COMPANY, THE", "prime_award_parent_piid": "N0001916G0001", "subaward_action_date": "2024-12-03"}
],
"pagination": {"limit": 2, "offset": 0, "total": 2, "total_is_estimate": false, "has_next": true}
}
Boeing reports a single $28,000,000.00 subaward to BAE against a prime_award_amount of $950,114.00, roughly 29 times the prime figure, on an order under parent vehicle N0001916G0001. One row alone breaks the ratio, so no amount of de-duplication explains it: the prime figure is the obligated value on that order, while the subaward reflects work scoped against the vehicle behind it. Treat a ratio above 1.0 as the signal that the order is a slice of something larger, and note has_next reading true here on a complete two-row result, which is page fullness rather than a further page.
The same lookup from the sub side. Swapping prime_uei for sub_uei turns a supply-chain map into a customer list.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://govconapi.com/api/v1/subawards/search?sub_uei=H11HD5VHGHN3&sort_by=subaward_amount&sort_order=desc&limit=2"
{
"data": [
{"subawardee_name": "LOCKHEED MARTIN CORPORATION", "subawardee_uei": "H11HD5VHGHN3", "prime_awardee_name": "NORTHROP GRUMMAN SYSTEMS CORPORATION", "prime_awardee_uei": "PK8PM2GNVMP8", "subaward_amount": 72342317.42, "subaward_action_date": "2026-01-12", "prime_award_awarding_sub_agency_name": "DEPT OF THE NAVY"},
{"subawardee_name": "LOCKHEED MARTIN CORPORATION", "subawardee_uei": "H11HD5VHGHN3", "prime_awardee_name": "ASRC FEDERAL FACILITIES LOGISTICS LLC", "prime_awardee_uei": "NENSLR2C1VH9", "subaward_amount": 17618333.0, "subaward_action_date": "2024-11-14", "prime_award_awarding_sub_agency_name": "DEFENSE LOGISTICS AGENCY"}
],
"pagination": {"limit": 2, "offset": 0, "total": 93, "total_is_estimate": false, "has_next": true}
}
H11HD5VHGHN3 is the same UEI the first example used as a prime, and here it sits in subawardee_uei on all 93 reports, taking $72.3M from Northrop Grumman on a Navy award and $17.6M from ASRC Federal on a DLA award. Primes are sub-vendors to each other constantly, so a firm's competitive picture needs both directions read, and the two filters never overlap: prime_uei and sub_uei match different columns on the row.
Name first, then UEI. When you have a company name rather than an identifier, search the name and read the identifiers back before you commit to one.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://govconapi.com/api/v1/subawards/search?sub_name=crane%20electronics&fields=subawardee_name,subawardee_uei,subawardee_state_code,subaward_amount,prime_awardee_name&sort_by=subaward_amount&sort_order=desc&limit=4"
{
"data": [
{"subaward_sam_report_id": "07E6433D-D7D7-4CB3-A6A9-FD6457130C12", "subawardee_name": "CRANE ELECTRONICS INC", "subawardee_uei": "XXJJAMTJ6C36", "subawardee_state_code": "WA", "subaward_amount": 8766988.0, "prime_awardee_name": "L3 TECHNOLOGIES, INC."},
{"subaward_sam_report_id": "A89DCBFF-F4AB-4305-AEAA-A7827DBAB7A6", "subawardee_name": "CRANE ELECTRONICS INC", "subawardee_uei": "XXJJAMTJ6C36", "subawardee_state_code": "WA", "subaward_amount": 5670148.0, "prime_awardee_name": "L3 TECHNOLOGIES, INC."},
{"subawardee_name": "CRANE ELECTRONICS, INC.", "subawardee_uei": "M3J1B3ML1CE5", "subawardee_state_code": "FL", "subaward_amount": 4901209.0, "prime_awardee_name": "LOCKHEED MARTIN CORPORATION", "subaward_sam_report_id": "DFAE4B70-FCB8-11EF-8E2A-E7034F2D18CD"},
{"subawardee_name": "CRANE ELECTRONICS, INC.", "subawardee_uei": "M3J1B3ML1CE5", "subawardee_state_code": "FL", "subaward_amount": 3035866.0, "prime_awardee_name": "RAYTHEON COMPANY", "subaward_sam_report_id": "E7EF6428-EDC6-4E6D-A508-77B3565517E0"}
],
"pagination": {"limit": 4, "offset": 0, "total": 79, "total_is_estimate": false, "has_next": true}
}
The first four of 79 reports already show two UEIs for the name, XXJJAMTJ6C36 in Washington and M3J1B3ML1CE5 in Florida, with the punctuation of the name differing between them. A query on either UEI alone would have returned a fraction of the 79 and looked complete. Note that subaward_sam_report_id appears in every row although the fields list does not ask for it, which is how you correlate a projected row back to its report.
Related
- Single FFATA report when you already hold a
subaward_sam_report_idand want the record without the search envelope or the coverage floor. - Subs paid by a prime and Primes that paid a sub when you want the same rows plus a computed summary, including a top-paying-primes leaderboard, instead of assembling one yourself.
- Contract detail for the prime side of any
prime_award_piidhere, including the subcontracted-share ratio computed per contract. - Search Window for what the coverage floor means, how clamping is reported, and why no plan reaches further back.
- Response Shaping for
fields=syntax, and Plans and Limits for page-size caps.