Map any prime contractor's supply chain. See the real federal revenue of small businesses. Every FFATA subaward from FY2025 onward, refreshed daily.
Federal prime contractors above the FFATA reporting threshold must disclose every sub-vendor they pay more than $30K under any federal contract. That filing is public, but it lives in USAspending's bulk-download interface in 118-column CSV form, one fiscal year at a time. This API exposes the same records as queryable JSON keyed by prime UEI, sub UEI, prime contract PIID, agency, or NAICS, with stable identifiers and a daily refresh cadence. Coverage today is FY2025 + FY2026 (October 2024 onward); the plan window is sized for 5 years so older fiscal years drop in as we backfill, without breaking your integration. It also stitches subaward signals into the rest of the GovCon API surface so you can pull supply-chain context alongside the SAM data you already use.
The Federal Funding Accountability and Transparency Act of 2006 (FFATA), reinforced by the 2010 Section 2 amendments, requires every federal prime contractor receiving more than $25,000 in obligations under a single contract to report the first-tier sub-vendors it pays more than $30,000 from those funds. Reporting flows through the FFATA Subaward Reporting System (FSRS) and is republished by USAspending.gov as quarterly and annual bulk downloads (the public, machine-readable form).
Each row is one Section 2 report. Fields cover the sub-vendor (UEI, name, parent name, state, business types), the prime (UEI, name, parent, place of performance), the underlying prime contract (PIID, parent PIID, NAICS, awarding agency and sub-agency, ceiling amount), the subaward itself (action date, amount, description, treasury account funding source), and where reporting thresholds are met, the named Highly Compensated Officers of both the prime and the sub.
This is the only public dataset that maps prime-to-sub federal contract flow at the individual-payment level. SAM.gov has prime award notices. USAspending has prime obligations and outlays. Neither tells you who the primes actually paid downstream. FFATA does.
If you only have prime award data, three real questions go unanswered:
/companies/{uei}/awards alone you systematically undercount, sometimes by an order of magnitude. The sub side is where their real customer relationships sit.The dataset also lights up a small but high-value class of compliance signals: subaward payments to entities that are on the federal exclusion list (the smoking-gun pattern of "clean prime still paying a debarred sub"), and last-payment-to-debarment timing on the sub side. We surface both as enrichment blocks on the relevant SAM endpoints rather than as a separate product.
Pro tier on the GovCon API key. Same Authorization: Bearer <key> header as everything else.
Filter-based search (at least one of prime_uei, sub_uei, piid, agency, naics, sub_name is required):
GET https://govconapi.com/api/v1/subawards/search
Single FFATA report by SAM report ID (UUID, the natural primary key):
GET https://govconapi.com/api/v1/subawards/{subaward_sam_report_id}
Prime-side reverse lookup: every sub this UEI paid as a prime contractor:
GET https://govconapi.com/api/v1/companies/{uei}/subawards
Sub-side reverse lookup: every prime that paid this UEI as a sub-vendor:
GET https://govconapi.com/api/v1/companies/{uei}/prime-relationships
Search and both reverse lookups paginate the same way (limit 1-250, offset ≥ 0, exact total) and follow the same response envelope as the rest of the API (data, pagination, filters_applied, window). The 250-row cap is tighter than the 1,000-row cap on /opportunities/search because subaward rows are wider (29 fields with description text). Sort keys: subaward_action_date (default), subaward_amount, subaward_sam_report_last_modified_date. Full parameter and field reference in the API guide.
The dedicated endpoints above are for when you want the underlying records. For most working integrations you want subaward context stitched onto the SAM data you already pull. We do that on five existing surfaces; the additions are non-breaking and only appear when the caller has Pro, so existing integrations keep working unchanged. Each card below shows the concrete before / after from a live prod query.
The single-record award endpoint carries a subaward_rollup with sub count, total subcontracted, share of the prime ceiling, distinct sub-vendor count, first and last subaward dates, plus the top 5 named subs. PIID-based join, so the block is populated only when the SAM-noticed contract has FFATA-reported subawards filed against it; for vendor-wide subaward activity (which works across all of a UEI's contracts regardless of whether they ever appeared on SAM), use the UEI-keyed reverse lookup /companies/{uei}/subawards instead.
Live example. GET /api/v1/awards/N0001918C1037 (Navy IDIQ, $49.67M, Northrop Grumman). Before: 16 award fields. After: same 16 fields plus a subaward_rollup showing 570 sub-payments to 136 distinct sub-vendors, $226.73M subcontracted, top 5 including Lockheed Martin ($22.32M, $20.29M) and Triumph Actuation ($19.54M). The "who actually did the work" question goes from impossible-to-answer-from-this-endpoint to one HTTP call.
Three fields alongside the prime-award totals: sub_revenue_total, top_paying_primes (up to 10), and prime_revenue_share (the fraction of this UEI's combined federal revenue that came in as prime contracts vs subs). Often the more meaningful split for SMBs.
Live example. GET /api/v1/companies/E7XWKERHVVD9 (TVAR Solutions, LLC). Before: $247K won as a prime across 2 awards. The prime-only profile reads as "small player." After: same record now also carries sub_revenue_total: $4.24B with Raytheon as the top paying prime ($4.20B in one payment). prime_revenue_share = 0.0001. The prime-only view missed 99.99% of TVAR's federal revenue. Same shape would apply for most subs to the largest primes.
Two top-level fields, sub_revenue_total and top_paying_primes, on the entity response (sub side only). Lets you read federal scale alongside SAM registration data on the same Developer-tier endpoint your CRM is already calling. For the bidirectional view (as_prime + as_sub), use the subaward_exposure block on /vendor-risk/{uei}.
Live example. GET /api/v1/entities/E7XWKERHVVD9. Before: SAM registration only (legal name, NAICS 541519, CAGE 49JA8). Vendor-onboarding read: "they exist." After: same record plus sub_revenue_total: $4.24B and the top 10 paying primes. Vendor-onboarding read: "they exist, here's their federal scale, here's who their actual customers are."
An eighth top-level block, subaward_exposure, alongside the seven existing risk signals. Descriptive only (not part of the triage rules): both sides of the FFATA flow on this UEI.
Live example. GET /api/v1/vendor-risk/ZMXAHH8M8VL8 (OSHKOSH DEFENSE, LLC). Before: triage + 7 signals (exclusion, address cluster, name variants, wave membership, timing gap, dual CAGE, individual exclusions). After: same plus subaward_exposure showing OSHKOSH paid $413.36M to 264 distinct subs across 4,405 payments and received $68.76M from 7 primes as a sub themselves. Compliance teams investigating supply-chain blast radius read this alongside the existing signals.
A recent_sub_payments block summarizing FFATA subaward dollars this excluded UEI has received in the last 12 months: total received, prime count, most-recent paying prime (named, with date and amount), and a top-5 paying-primes list.
Live example. GET /api/v1/exclusions/SMFQMVEAJVM9 (HM 2 Mechanical & Specialty Contractors, on the NASA Voluntary Exclusion list since 2023-08-02, still Active). Before: just the exclusion record. After: same record plus recent_sub_payments showing $158K received from AMENTUM SPACEPORT LLC as recently as 2025-08-19, two years into the active exclusion. The compliance question goes from "are they debarred?" to "is anyone still paying them?" in one HTTP call.
One denormalized table, 118 columns from USAspending bulk_download. The search and reverse-lookup endpoints return a 29-field row by default (BD-intel focus); use ?fields= for a narrower projection or call the single-record endpoint for the full 118-column record. Full field-by-field reference in the API guide.
Default 29-field row (search response):
{
"subaward_sam_report_id": "01b6a2d8-3e02-44f7-9b8e-...",
"subaward_number": "1A4PZ-006-WTERX",
"subaward_action_date": "2026-04-22",
"subaward_amount": 487200.00,
"subaward_description": "Engineering analysis support for...",
"subaward_sam_report_last_modified_date": "2026-05-28",
"prime_award_piid": "FA8620-25-C-0012",
"prime_award_parent_piid":"FA8620-22-D-0001",
"prime_award_amount": 12500000.00,
"prime_award_project_title": null,
"prime_award_naics_code": "336411",
"prime_award_naics_description": "Aircraft Manufacturing",
"prime_award_awarding_agency_name": "DEPT OF DEFENSE",
"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": null,
"prime_awardee_parent_name": null,
"prime_awardee_state_code": "MD",
"prime_awardee_country_code":"USA",
"subawardee_uei": "XX2WFHJEFB45",
"subawardee_name": "KAMPI COMPONENTS CO INC",
"subawardee_parent_uei": null,
"subawardee_parent_name": null,
"subawardee_business_types": "FOR PROFIT ORGANIZATION,SUBCHAPTER S CORPORATION",
"subawardee_state_code": "PA",
"subawardee_country_code": "USA",
"subaward_pop_state_code": "FL",
"subaward_pop_country_code": "USA",
"usaspending_permalink": "https://www.usaspending.gov/award/..."
}
The reverse-lookup endpoints (/companies/{uei}/subawards and /companies/{uei}/prime-relationships) add a top-level summary block aggregating across the filtered set (totals, distinct-counterparty counts, first and last action dates, top primes / subs leaderboard).
Same passthrough philosophy as the rest of our SAM data: we don't sanitize source-data weirdness because the weirdness is sometimes the signal. Quirks that have surprised callers in testing:
subaward_amount divided by prime_award_amount can be greater than 1 on a multi-modification contract. FFATA reports each modification cumulatively (each modification re-reports the full subaward value, not just the delta), so aggregations across modifications can exceed the prime ceiling. Treat values >1.0 as a "heavily modified, multi-revision contract" signal, useful in itself.
subaward_number values collide across records (USAspending re-issues report numbers under modifications). The 32-character UUID subaward_sam_report_id is the only stable per-record key. Use it for joins, dedup, and direct lookup.
subawardee_duns / prime_awardee_duns but null _uei columns. Filtering by UEI silently excludes them. For full coverage, query both.
subawardee_business_types is a comma-separated TEXT field, not an array. Avoid LIKE '%SDVOSB%'-style queries (they also match NON-SDVOSB-tagged rows). treasury_accounts_funding_this_award and siblings carry their pipe-delimited structure inside the cell. Parse client-side as needed.
prime_award_amount. Aggregations like SUM(prime_award_amount) GROUP BY prime_awardee_uei will multi-count. Group by prime_award_piid if you want per-contract sums.
Each recipe is the actual workflow for one of the three customer use cases in Why this matters. Copy-paste ready; the Python uses plain requests with no custom client.
BD intel, M&A diligence, set-aside compliance. Two calls give you prime award profile + every sub they've paid + the leaderboard.
import requests
KEY = "gca_…"
H = {"Authorization": f"Bearer {KEY}"}
BASE = "https://govconapi.com/api/v1"
def supply_chain_map(prime_uei):
profile = requests.get(f"{BASE}/companies/{prime_uei}", headers=H).json()
# /subawards/* page cap is 250 (subaward rows are wider than awards).
# For a top prime with thousands of FFATA reports, page through with offset.
subs = requests.get(f"{BASE}/companies/{prime_uei}/subawards",
headers=H, params={"limit": 250}).json()
return {
"prime_name": profile["name"],
"won_as_prime_total": profile["total_value"],
"paid_to_subs_total": subs["summary"]["total_subaward_amount"],
"distinct_sub_vendors": subs["summary"]["distinct_sub_vendors"],
"distinct_contracts": subs["summary"]["distinct_prime_contracts"],
"subaward_date_range": (subs["summary"]["first_subaward_date"],
subs["summary"]["last_subaward_date"]),
"top_subs": subs["data"][:5],
}
# >>> supply_chain_map("ZMXAHH8M8VL8") # OSHKOSH DEFENSE
# {'prime_name': 'OSHKOSH DEFENSE, LLC',
# 'won_as_prime_total': 2.4e9, 'paid_to_subs_total': 413_361_154.08,
# 'distinct_sub_vendors': 264, 'distinct_contracts': 372, …}
To go contract-by-contract instead of UEI-wide, use /subawards/search?piid=<piid> — same row shape, scoped to one prime contract.
SMBs often earn the larger half of federal revenue as subs. Looking up /companies/{uei}/awards alone undercounts. One Pro response carries both sides:
def true_federal_revenue(uei):
p = requests.get(f"{BASE}/companies/{uei}", headers=H).json()
return {
"name": p["name"],
"prime_revenue": p["total_value"], # award notices, all-time
"sub_revenue": p["sub_revenue_total"], # FFATA, current coverage
"combined": p["total_value"] + p["sub_revenue_total"],
"prime_share": p["prime_revenue_share"], # 0..1 (or null)
"top_paying_primes": p["top_paying_primes"], # who their customers actually are
}
# Example output for a sub-heavy SMB:
# prime_revenue=$1.2M sub_revenue=$8.4M combined=$9.6M prime_share=0.13
# → 87% of their federal revenue is sub work; the prime-only view missed it.
The two totals come from different time windows (prime = all-time award notices; sub = current FFATA coverage, FY2025 + FY2026 today). The asymmetry shrinks as we extend subaward coverage backward; for now prime_revenue_share is approximate.
When a vendor hits the SAM exclusion list, the question that matters is whether clean primes are still paying them. One Pro call returns both the exclusion record and the recent-payments view:
def active_payment_screen(uei):
r = requests.get(f"{BASE}/exclusions/{uei}", headers=H)
if r.status_code == 404:
return None # no UEI-keyed exclusion. Pair with /exclusions/search?name=… for full coverage.
body = r.json()
rsp = body["recent_sub_payments"]
return {
"exclusion_type": body["exclusion_type"],
"excluding_agency": body["excluding_agency_code"],
"create_date": body["create_date"],
"active": body["record_status"] == "Active",
"still_being_paid": rsp["subaward_count"] > 0, # ← the compliance signal
"total_received_last_12mo": rsp["total_received"],
"most_recent_payment": rsp["most_recent_subaward_date"],
"most_recent_paying_prime": rsp["most_recent_paying_prime"],
"top_paying_primes": rsp["top_paying_primes"],
}
~80% of SAM exclusions are individuals or entities without a UEI, so a UEI lookup alone is not a full screen. Pair with /exclusions/search?entity_name=… for full screening coverage. For the broader risk surface (address clusters, name variants, coordinated waves), the same enrichment is also present on /vendor-risk/{uei} under subaward_exposure.
The recipes above use Python for clarity. For one-shot lookups, the same calls in curl:
What subs has Lockheed paid out as a prime, most recent first:
curl -H "Authorization: Bearer $KEY" \
"https://govconapi.com/api/v1/companies/H11HD5VHGHN3/subawards?limit=20"
Map a single prime contract's full supply chain:
curl -H "Authorization: Bearer $KEY" \
"https://govconapi.com/api/v1/subawards/search?piid=FA8620-25-C-0012&sort_by=subaward_amount&sort_order=desc"
True federal revenue for a small business (sub side):
curl -H "Authorization: Bearer $KEY" \
"https://govconapi.com/api/v1/companies/XX2WFHJEFB45/prime-relationships?limit=50"
Find every sub-vendor for one prime above $100K in the last year:
curl -H "Authorization: Bearer $KEY" \
"https://govconapi.com/api/v1/subawards/search?prime_uei=H11HD5VHGHN3&date_from=2025-05-31&amount_min=100000"
Get the subaward footprint of one specific prime contract:
# subaward_rollup block appears on /awards/{award_number} for Pro keys
curl -H "Authorization: Bearer $KEY" \
"https://govconapi.com/api/v1/awards/N0001918C1037"
Compliance: is this excluded UEI currently still being paid?
# recent_sub_payments block appears on /exclusions/{uei_sam} for Pro keys
curl -H "Authorization: Bearer $KEY" \
"https://govconapi.com/api/v1/exclusions/N2EDPB1SMN55"
USAspending publishes the same source data this API serves. Their bulk_download interface is fine if you want one fiscal year of CSVs and have a place to load 118 columns. Their per-record award API does not paginate sub-vendor lookups by UEI, and there is no "find all primes that paid this sub" cursor. Tango, HigherGov, and GovTribe all carry FFATA subaward data behind their paid tiers; pricing on those products typically starts above $500/month with seat-based licensing.
| Approach | Search by sub UEI | Search by prime UEI | Search by PIID | Subaward enrichment on awards / exclusions / vendor-risk | Daily refresh | Starting price |
|---|---|---|---|---|---|---|
| USAspending bulk_download | Manual: download CSV, load, query | Manual | Manual | No | Quarterly + annual | Free |
| USAspending per-record API | Partial: by award detail only | Partial | Partial | No | Yes | Free |
| Tango / HigherGov / GovTribe | Yes (web UI) | Yes (web UI) | Yes | Partial | Varies | $500+ / mo |
| GovCon API (Pro) | Yes (REST) | Yes (REST) | Yes (REST) | Yes, inline on existing endpoints | Yes (2-day lag) | $39 / mo |
The fit: developers and analysts who want subaward data programmatically alongside the rest of the SAM surface (opportunities, awards, entities, exclusions, vendor risk) without building five separate integrations. If you only need the bulk download once and have a warehouse to load it into, the USAspending CSV is the right tool. If you're building a product that needs sub-vendor relationships at request time and wants subaward context stitched into the rest of the federal contractor data automatically, this is the shortcut.
Subawards is included in Pro ($39/month) along with the rest of the Pro surface: Companies (search, profile, awards, peers), Vendor Risk (single and bulk), Entities multi-filter search and expiration radar, Contacts API resolver, and the GovCon Contacts web app. Same key, same Authorization: Bearer header. Rate limit: 1,000 requests/hour per key plus a 60/minute burst cap per IP.
Coverage today is FY2025 + FY2026 (October 2024 onward) on the search and reverse-lookup endpoints. Single-record lookup by subaward_sam_report_id is not gated by date. The plan window is sized for 5 years so older fiscal years drop in as we backfill, without breaking your integration. For the full historical depth back to FY2011 today, see /enterprise.
Where does this data come from?
USAspending.gov's bulk_download API, the public republication of FFATA Section 2 reports filed by federal prime contractors through FSRS. We refresh nightly with a 2-day source lag (slightly faster than sgs/ffata, which runs about a week behind).
How far back does the data go?
Coverage today is FY2025 + FY2026 (every FFATA subaward from October 2024 onward). The Pro plan window is sized for 5 years, so older fiscal years drop in transparently as we backfill from USAspending. Single-record lookup by SAM report ID is not gated. For the full historical depth (FY2011 onward) today, ask about Enterprise.
Why is the source lag 2 days?
USAspending publishes daily but the FSRS-to-USAspending pipeline runs once per day, so today's USAspending dataset reflects what FSRS held two business days ago. We pull from USAspending daily; there's no way to be fresher than the upstream.
Is FFATA the same as FPDS-style award history?
No. FPDS records prime obligations (the contract level). FFATA records the first-tier sub-vendor payments flowing from those primes. Two different layers of the same procurement; you usually want both.
Why is subcontract_share sometimes greater than 1?
FFATA reports modifications cumulatively. Each modification re-reports the full subaward value rather than the delta, so summing across modifications can exceed the prime contract ceiling. Treat values >1.0 as the "multi-revision contract" signal, not a parsing bug. See Data quirks.
What's the difference between subaward_number and subaward_sam_report_id?
subaward_number is a human-readable FFATA report identifier (e.g. 1A4PZ-006-WTERX); about 10% collide across records. subaward_sam_report_id is the UUID we use as the primary key. Use the UUID for joins and direct lookup; treat subaward_number as a display label.
Can I use this data for set-aside flow-down compliance reviews?
Yes; the agency-side enforcement teams use the same FFATA records. Cross-reference set-aside type on the prime contract (from opportunities search) with the subawardee_business_types field on each sub. Note the quirk under Data quirks: the field is a TEXT comma-separated string, not an array, so substring matching has false-positive edges.
Does this cover sub-vendor information for grants and assistance, or only procurement?
Our daily ingest pulls procurement subawards only (sub_award_types=["procurement"] on the USAspending side). Assistance / grant subawards have a different reporting workflow and currently fall outside our scope; ask if you need them.
What's the latency budget?
Single-record lookup ~50ms. Filter-based search ~100-300ms depending on filter selectivity. The reverse-lookup endpoints run ~150-400ms because they also aggregate a summary block. Enrichment blocks stitched onto existing endpoints add 5-60ms per request.
Can I redistribute the data?
The underlying data is public-record federal data. The Pro license covers internal use and product integration. For redistribution as a commercial product, contact us for a custom arrangement.
Ready to integrate? Pro is $39/month. Or read the full API reference. Questions about fit: [email protected].