Bosco Labs

Tools › Government & procurement

Pentagon / DoD Contract Awards API: winners, amounts, tickers

Coming soon to the Store

Get every US Department of Defense contract award of $7.5M or more, the same evening it is announced, plus the full history since FY2008: who won, how much, which service (Army, Navy, Air Force, DLA, Missile Defense Agency, ...), and the winner's US stock ticker with its SEC-reported shares outstanding. History rows add the parent company and NAICS/PSC codes. Switch the history to any other federal agency, or all of them, with one input. For defense-sector investors, government sales teams and AI agents.

Price$0.005 per award row
DomainGovernment & procurement
Call itApify API or MCP

Pricing (pay per event): $0.005 per award row ($5 per 1,000 awards). No start fee. You only pay for rows delivered, a row is never charged twice in one run, scheduled runs can skip awards you already received, and the Actor stops at your max charge limit.

Coming soon to the Apify StoreAsk for early access

Questions agents ask

  • “Which Kratos contracts did the Pentagon award in 2019, and how large were they?”
  • “Who won the largest Navy shipbuilding contracts (NAICS 336611) in 2025?”
  • “Show Department of Homeland Security contracts over $10 million signed in the first half of 2026.”

Example

Input

{
  "dateFrom": "2019-01-01",
  "dateTo": "2019-12-31",
  "tickers": ["KTOS"],
  "maxResults": 1000
}

Output

{
  "award_id": "N0018923F3020",
  "parent_award_id": "N0017819D7295",
  "action_date": "2026-06-24",
  "amount_usd": 37046089.24,
  "action_count": 1,
  "new_award": false,
  "award_type": "DELIVERY ORDER",
  "awarding_agency": "Department of Defense",
  "awarding_sub_agency": "Department of the Navy",
  "recipient_name": "CACI, INC. - FEDERAL",
  "recipient_uei": "N3PBJAVNKF61",
  "parent_name": "CACI INTERNATIONAL INC",
  "recipient_city": "CHANTILLY",
  "recipient_state": "VA",
  "naics_code": "541330",
  "naics_description": "ENGINEERING SERVICES",
  "psc_code": "R706",
  "psc_description": "SUPPORT- MANAGEMENT: LOGISTICS SUPPORT",
  "description": "NAVAL FORCES LOGISTICS SUPPORT SERVICES-NFL",
  "ticker": "CACI",
  "matched_on": "parent",
  "sec_cik": 16058,
  "exchange": "NYSE",
  "shares_outstanding": 22091305,
  "shares_as_of": "2026-04-17",
  "usaspending_url": "https://www.usaspending.gov/award/CONT_AWD_N0018923F3020_9700_N0017819D7295_9700",
  "source": "usaspending",
  "award_kind": "option_exercise",
  "pricing_type": null,
  "amount_basis": "obligated",
  "obligated_at_award_usd": 37046089.24,
  "is_ceiling": false,
  "shared_award": false,
  "awardees_count": 1,
  "co_awardees": [],
  "award_group_id": "89a961337f18c579",
  "classification_evidence": "modification P00065 action type G (exercise an option)",
  "data_lag_note": "DoD contract actions reach FPDS/USAspending up to 90 days after signing ...",
  "retrieved_at": "2026-11-05T16:00:00+00:00"
}

What you get

FieldTypeMeaning
schema_versionstringOutput schema version.
sourcestringWhere the row comes from: "usaspending" (obligation records, ~3 months late for DoD) or "dod_daily_list" (the Pentagon's same-evening contract list, parsed by AI with checks). The two are separate records of an award and are never summed or deduped.
award_idstring | nullContract PIID (USAspending 'Award ID'); for daily-list rows the contract number in the text, null when none is stated.
parent_award_idstring | nullPIID of the parent IDV (IDIQ, BPA, GSA schedule) for task and delivery orders; null for standalone contracts.
award_keystringUSAspending generated_internal_id: unique award key (PIID + agency + parent IDV).
action_datestringSigning (action) date, YYYY-MM-DD; for daily-list rows the announcement date.
amount_usdnumberUSAspending rows: obligated amount in USD, that day's actions on this award summed (modifications can be negative). Daily-list rows: the amount as stated (see amount_basis); for a multiple-award contract the full shared ceiling on every awardee's row (see shared_award).
is_ceilingbooleanTrue when amount_usd is a ceiling, not money committed (amount_basis is "ceiling"): an IDIQ maximum or a multiple-award ceiling. Kept for compatibility; use amount_basis and shared_award. Only daily-list rows can be true.
contract_numberstring | nullContract number (PIID) as stated: for USAspending rows the same as award_id; for daily-list rows the number in the announcement paragraph, null when that paragraph states none.
award_kindstring | nullWhat kind of award the row is. Daily list: from the announcement wording ("has been awarded a ... contract" = new_contract, "modification (P00012) to previously awarded contract" = modification, "exercises an option" = option_exercise, "task order", "delivery order" or an order under an ordering agreement, "multiple award" or "will compete for each order" = multiple_award_idiq, "single award" = single_award_idiq; an IDIQ that says neither is new_contract), kept only when such a keyword is in the paragraph. USAspending: award type A BPA CALL = bpa_call, B PURCHASE ORDER = new_contract, C DELIVERY ORDER = delivery_order (FPDS files task orders as delivery orders), D DEFINITIVE CONTRACT = new_contract; a day without the base award is option_exercise (action type G) or modification. Null when unknown.
pricing_typestring | nullContract pricing from the announcement wording ("firm-fixed-price", "cost-plus-fixed-fee", ...; hybrid = two or more named). Daily-list rows only; null for USAspending rows (the transaction search does not return it) and when the text names none.
amount_basisstring | nullWhat amount_usd measures: ceiling (a maximum or multiple-award ceiling, not money committed; shared when shared_award is true), face_value (a definitive contract's or order's value), modification_value (the value of a modification), obligated (money obligated: every USAspending row), estimated. Null when the text does not say.
obligated_at_award_usdnumber | nullDaily list: the amount the announcement says is obligated at the time of award (0 for "no funds are obligated"), only when that figure is in a sentence about obligation; else null. USAspending: the obligated amount (same as amount_usd).
shared_awardboolean | nullTrue when several companies share this one amount (a multiple-award contract: every awardee gets a row with the full ceiling). Never sum amount_usd over such rows: count each award_group_id once. False for USAspending rows; null for daily-list days read before schema 2.
awardees_countinteger | nullNumber of companies sharing this award_group_id (1 = not shared).
award_group_idstring | nullStable id shared by all rows of one award: daily list = one announcement paragraph and amount; USAspending = one award and signing day. To total money without double counting, take amount_usd once per award_group_id.
co_awardeesarray | nullThe other companies in the same award_group_id (at most 20); empty when not shared.
completion_datestring | nullEstimated completion date stated in the announcement, YYYY-MM-DD (a month alone: its last day); null when not stated and for USAspending rows.
classification_evidencestring | nullThe words that support award_kind, pricing_type and amount_basis, e.g. "multiple award; firm-fixed-price; maximum" (daily list) or "award type DELIVERY ORDER" (USAspending).
action_countintegerNumber of contract actions summed into this row.
modification_numbersarrayModification numbers of those actions ('0' = the base award).
new_awardbooleanTrue when the day includes the base award (modification 0), false for modifications only.
award_typestring | nullDEFINITIVE CONTRACT, DELIVERY ORDER, PURCHASE ORDER or BPA CALL.
awarding_agencystring | nullTop-tier awarding agency, e.g. Department of Defense.
awarding_sub_agencystring | nullAwarding sub-agency, e.g. Department of the Navy, Department of the Army, Department of the Air Force, Defense Logistics Agency, Missile Defense Agency.
recipient_namestring | nullContractor (recipient) name as reported.
recipient_ueistring | nullRecipient Unique Entity ID (SAM.gov).
parent_namestring | nullParent company name from the USAspending award record.
parent_ueistring | nullParent company UEI.
recipient_citystring | nullRecipient city.
recipient_statestring | nullRecipient state code (daily-list rows: the state as written, e.g. Virginia).
recipient_countrystring | nullRecipient country.
performance_statestring | nullPlace of performance state code.
performance_countrystring | nullPlace of performance country.
naics_codestring | nullNAICS industry code.
naics_descriptionstring | nullNAICS description.
psc_codestring | nullProduct and Service Code.
psc_descriptionstring | nullPSC description.
descriptionstring | nullDescription of the day's largest action (max 300 characters).
tickerstring | nullUS-listed ticker (NYSE, Nasdaq, CBOE) of the recipient or its parent, by exact cleaned-name match; null when not matched.
matched_onstring | nullWhich name matched the ticker: the recipient itself or its parent company.
sec_cikinteger | nullSEC Central Index Key of the matched company.
sec_company_namestring | nullCompany name in SEC's ticker list.
exchangestring | nullExchange of the ticker in SEC's list.
shares_outstandinginteger | nullShares outstanding from the SEC cover page (dei:EntityCommonStockSharesOutstanding), the count of the action date (latest on or before it, else the earliest). Multiply by your own price for a market cap.
shares_as_ofstring | nullDate of that share count, YYYY-MM-DD.
usaspending_urlstringAward page on USAspending.gov.
source_urlstring | nullUSAspending API record of the award; for daily-list rows the war.gov article, null when the e-mail did not link it.
data_lag_notestringReporting lag of the source: DoD actions appear up to 90 days after signing.
retrieved_atstringUTC time the row was built.

Coverage

Same evening: the Pentagon's daily contract list (weekdays, rows in by about 7 p.m. New York). History: the USAspending.gov API from 2007-10-01, for the Department of Defense or any other federal agency. DoD contract actions reach USAspending up to 90 days after signing, so the default window is the last 135 days.

Use with AI agents (MCP)

Add this URL to your MCP client (Claude, Cursor, VS Code, ...) to load the Actor as a tool through the Apify hosted MCP server. It signs you in with OAuth or accepts Authorization: Bearer <APIFY_TOKEN>. It works once the Actor is live on the Apify Store.

https://mcp.apify.com?tools=bosco_labs/dod-contract-awards

For “Which Kratos contracts did the Pentagon award in 2019, and how large were they?” the agent passes:

{"tickers": ["KTOS"], "dateFrom": "2019-01-01", "dateTo": "2019-12-31"}

stable, typed JSON, one row per award per signing day, newest first. Every row has schema_version, source (dod_daily_list: the same-evening announcement; usaspending: the history, up to 90 days late for DoD) and a source_url (the war.gov article or the USAspending API record), so the agent can cite its source. Rows with is_ceiling: true are contract ceilings, not money committed. Rows with shared_award: true share one amount with co_awardees: to total money, count amount_usd once per award_group_id.

Or call the Apify API: POST https://api.apify.com/v2/acts/bosco_labs~dod-contract-awards/run-sync-get-dataset-items with the input as JSON body. Cost: $0.005 per award row.

Input fields

FieldTypeMeaning
sourcestring"both" (default) = the Pentagon's same-evening contract list (published around 5 p.m. New York on the signing day, face values, DoD only) plus the USAspending history (obligations, ~3 months behind for DoD). "dailyList" = only the same-evening list rows. "history" = only USAspending. The list has no NAICS/PSC codes, so it is skipped when naicsCodes or pscCodes are set, and when agencies excludes the Department of Defense.
dateFromstringEarliest action (signing) date, or announcement date for same-evening list rows, YYYY-MM-DD, e.g. "2019-01-01". History from 2007-10-01 (FY2008). Empty = 135 days before dateTo, because DoD data is published up to 90 days late (about 105 days observed).
dateTostringLatest action (signing) date, YYYY-MM-DD, e.g. "2019-12-31". Empty = today. The last ~3 months of DoD data are incomplete.
agenciesarrayTop-tier awarding agency names as USAspending spells them, e.g. ["Department of Defense"], ["Department of Homeland Security"], ["National Aeronautics and Space Administration"]. Default ["Department of Defense"]. Pass [] for ALL federal agencies.
minAmountUsdintegerMinimum summed obligations per award and day, in USD, e.g. 1000000. Default 7500000, the DoD's public announcement threshold (the daily 5 p.m. contracts list). 0 = every award-day except net de-obligations (negative sums).
recipientsarrayWinning company search terms, matched by USAspending against recipient and parent names, e.g. ["kratos", "huntington ingalls"]. Empty = all recipients.
tickersarrayOnly awards matched to these US-listed tickers (NYSE, Nasdaq, CBOE), e.g. ["LMT", "KTOS", "AVAV"]. Turns ticker matching on. Empty = no ticker filter.
naicsCodesarrayNAICS industry codes, 2 to 6 digits, e.g. ["336414"] (guided missiles and space vehicles) or ["3364"]. Empty = all.
pscCodesarrayProduct and Service Codes, e.g. ["1410"] (guided missiles), ["R425"] (engineering support). Empty = all.
matchTickersbooleantrue (default) = match the recipient or its parent company to a US-listed ticker by exact cleaned name (SEC company list) and add the SEC-reported shares outstanding. Unmatched awards are still returned, with ticker = null.
maxResultsintegerMaximum award rows, newest signing dates first, then largest amounts, e.g. 20. Default 100. Each row is one charged event.
onlyNewSinceLastRunbooleantrue = skip (and don't charge for) award-days (including old-dated actions the DoD publishes late) an earlier run with the same filters already delivered. For scheduled runs. Default false. Remembered in a named key-value store in your account.

Sources, licence and limits

How fresh is the data? Same-evening rows are in by about 7 p.m. New York on the day the Pentagon announces them (weekdays). The USAspending history is months behind for DoD: contract actions are published in FPDS, and so on USAspending, with a delay of up to 90 days (a DoD rule for operational security). On 2026-11-05 the DoD data was complete up to 2026-07-23, a lag of about 105 days; later dates only held a few hundred actions (mainly Army Corps of Engineers civil works). That is why the default window is the last 135 days, and why every row carries a data_lag_note. Civilian agencies report within days. Old dates keep filling in, so use onlyNewSinceLastRun on a schedule instead of re-reading the same window.

How does the same-evening list get in? The Pentagon e-mails its daily contract list around 5 p.m. New York. Each weekday evening we read that e-mail, turn every awardee in it into a row and store it; your run reads the stored rows (no e-mail or AI call happens in your run). Rows are matched to tickers the same strict way as the history.

The list is parsed by AI. Can I trust it? The prose is turned into rows by Claude (Haiku), with checks around it: the model has no tools and is told the text is data, not instructions; its answer must be exactly a JSON list in a fixed schema with valid types, or that part of the day is rejected and read again; every row's company name and dollar amount must literally appear in one announcement paragraph, or the row is dropped; and its contract number, completion date, obligated amount and labels must be backed by that paragraph, or they are null. That stops made-up rows, but the model can still occasionally pick the wrong one of two amounts in a paragraph, or the wrong city. For anything you act on, open source_url (the war.gov article) and check.

Why do several companies show the same amount? It is one multiple-award contract. When eleven firms "are awarded a $975,000,000 contract", they compete for orders up to $975M together: $975M is a shared ceiling, not $975M each, and nobody knows yet how it will be split (so we don't pro-rate it). Each firm still gets its own row with the full amount, marked shared_award: true, awardees_count: 11, amount_basis: "ceiling", the other ten in co_awardees, and one award_group_id for all eleven. Never sum amount_usd over these rows: keep one row per award_group_id (eleven rows summed would claim $10.7B). Even then a ceiling is a maximum, not money committed; obligated_at_award_usd says what was actually obligated when the announcement states it.

What do award_kind, pricing_type and amount_basis mean? award_kind says what the row is: new_contract, modification, option_exercise, task_order, delivery_order, multiple_award_idiq, single_award_idiq, bpa_call or other. pricing_type is the contract type (firm_fixed_price, cost_plus_fixed_fee, cost_plus_award_fee, cost_plus_incentive_fee, fixed_price_incentive, time_and_materials, cost_reimbursable, hybrid for several, other). amount_basis says what amount_usd measures: ceiling, face_value, modification_value, obligated or estimated; is_ceiling is kept and is true exactly when it is ceiling. For the daily list the AI's label is only kept when a word that supports it ("multiple award", "exercises an option", "firm-fixed-price", ...) is in the announcement paragraph, and that word is shown in classification_evidence; otherwise the field is null, never guessed. For USAspending rows they come from the official codes:

USAspending`award_kind`
Award type D, DEFINITIVE CONTRACT (day with the base award)new_contract
Award type B, PURCHASE ORDER (base award)new_contract
Award type C, DELIVERY ORDER (base award; FPDS files task orders here too)delivery_order
Award type A, BPA CALL (base award)bpa_call
Modification with action type G (exercise an option)option_exercise
Any other modificationmodification

USAspending rows are always amount_basis: "obligated", shared_award: false and pricing_type: null (the search the Actor uses does not return the pricing type). IDIQ and BPA vehicles themselves carry no obligations, so the *_idiq kinds come from the daily list only; orders under them show the vehicle in parent_award_id.

Is this the same as the DoD's daily 5 p.m. contract announcements? Same contract actions, two records. dod_daily_list rows come from the announcement itself, the same evening, with face values. usaspending rows arrive months later with the obligated amount of that day (often lower than the face value), UEI, parent company, NAICS and PSC. The Actor does not merge them: the same award can appear once from each source.

Why do amounts differ from the press release? For USAspending rows: obligations vs. face value (see above). Also, one row sums all actions on that contract that day, and modifications can be negative.

Why is my company's ticker missing? The recipient name and its parent must match the SEC name exactly after cleaning (the daily list names no parent, so only the awardee's own name counts there). Joint ventures, foreign parents and renamed subsidiaries are missed on purpose. Search by recipients (name contains) to see them anyway.

Why is shares_outstanding empty for a matched ticker? Companies with several share classes (e.g. Palantir) or that don't report the cover-page count as a single number, and counts older than 400 days from the signing date, are left empty rather than guessed.

Is the ticker the company that was listed at the time? Matching uses today's SEC list and today's parent company from USAspending. A subsidiary sold since then may show its current owner's ticker; companies that are no longer listed are not matched.

Is this investment advice? No. It is a data product: public contract records joined to public SEC identifiers. No prices, no market caps, no signals.

Legal basis? US federal government data is public domain. See LEGAL.md in the source.

Coming soon to the Apify StoreAsk for early access