# Federal Award Monitor (USAspending) — New Contracts, No Login (`chimerical_quicklime/federal-award-monitor`) Actor

Watch recipients, agencies, NAICS, PSC or keywords on USAspending and get only NEW or modified federal contracts, grants, loans and IDVs since the last run, with amount, UEI, place of performance and parent award. Daily schedule. No login. MCP-ready. $10 per 1,000 alerts.

- **URL**: https://apify.com/chimerical\_quicklime/federal-award-monitor.md
- **Developed by:** [Khrystyna Skotte](https://apify.com/chimerical_quicklime) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 awards

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Federal Award Monitor — who won what, daily (USAspending.gov)

Get a **daily feed of only the new or modified federal awards that match your watchlist** — contracts, grants,
loans and IDVs from USAspending.gov, filtered by recipient, awarding agency, NAICS, PSC code and keyword.
The monitor remembers every award it has already reported, so a scheduled run emits just the delta (marked
`new` or `updated` when the obligated amount changed), posts a summary to your webhook, and costs you only
for what actually changed. No API key, no login.

SAM.gov tells you what is being solicited. This tells you **who won it** — the other half of a capture,
competitive-intelligence or subcontracting workflow.

### Use cases

- **Competitor watch** — `recipients: ["Booz Allen", "Leidos", "SAIC"]`: every new task order or modification
  they receive, with agency, NAICS, PSC, amount and period of performance.
- **Subcontracting leads** — `naicsCodes: ["236220"]`, `agencies: ["Department of Veterans Affairs"]`: primes
  that just won construction work in your lane, with their UEI and location so you can reach out.
- **Agency account intelligence** — `agencies: ["Department of Homeland Security"]`, `pscCodes: ["D"]`: all
  new IT-services awards at DHS, who got them and through which parent IDV.
- **Grant tracking** — `awardTypes: ["grants"]`, `keywords: ["opioid"]`: new project grants and cooperative
  agreements by topic, with the CFDA / assistance-listing number.
- **Sales-team alerts** — point `webhookUrl` at Slack, Zapier or Make and ship a morning "new awards" digest.

### How it works

1. Queries USAspending's award search for awards with a **transaction (new award or modification) dated within
   the last `lookbackDays`**, one query per watch item and award-type group, newest-modified first.
2. Compares each award against the monitor's saved state (`generatedInternalId → award amount`).
3. Emits a record when the award is unseen (`changeType: "new"`) or its obligated amount changed
   (`changeType: "updated"`, with `previousAmount`), optionally enriched from the award detail record
   (recipient UEI and location, total obligation, period of performance, parent IDV, funding agency).
4. Saves the updated state, then POSTs a run summary to `webhookUrl` if set.

State lives in a named key-value store `award-monitor-<hash of monitorId>` in your Apify account, capped at
50,000 awards (oldest recorded are dropped). Delete the store to reset a monitor.

### Watch items vs. global filters

`recipients`, `naicsCodes`, `pscCodes` and `keywords` are **watch items**: each entry is queried on its own and
a match is tagged with `matchedFilter` (`recipient:Lockheed`, `naics:541512`, `psc:D`, `keyword:radar`). An
award matching several watch items is emitted once, under the first one that found it.

`agencies`, `awardTypes`, `minAmount` and `lookbackDays` are **global** and apply to every watch item. With no
watch items the monitor emits everything that passes the global filters (`matchedFilter: "agency:…"` or `"all"`).

### Input

| Field | Default | Notes |
|---|---|---|
| `recipients` | `[]` | Partial recipient names (USAspending recipient search). `"Lockheed"` also matches Sikorsky, a Lockheed subsidiary |
| `agencies` | `["Department of Defense"]` | Top-tier awarding agency names or abbreviations (`DOD`, `VA`, `GSA`, `HHS`, `DHS`, `NASA`, `DOE`, `DOT`). Resolved against USAspending's agency list; `"Veterans"` → `Department of Veterans Affairs`. Empty = all agencies |
| `naicsCodes` | `[]` | 2–6 digit NAICS, prefixes allowed (`54` = all professional services) |
| `pscCodes` | `[]` | Product/Service Codes, prefixes allowed (`D` = IT services, `R4` = professional support, `70` = IT equipment) |
| `keywords` | `[]` | Terms matched in the award description |
| `awardTypes` | `["contracts"]` | Group names or raw codes, see below |
| `minAmount` | `0` | Skip awards obligated below this amount |
| `lookbackDays` | `7` | Awards with a transaction dated within N days |
| `includeDetails` | `true` | One extra request per emitted award for UEI, location, obligation, PoP, parent IDV |
| `maxNewPerFilter` | `10` | Cap per watch item and award group; the rest stays unseen for the next run |
| `maxItems` | `10` | Overall cap per run |
| `firstRunMode` | `emitAll` | `emitAll` reports every current match on the first run; `baseline` records them silently |
| `webhookUrl` | `""` | Optional POST target for the run summary |
| `monitorId` | `default` | One state store per ID — run several watchlists side by side |

#### Award type codes

USAspending only allows one group per query; the monitor runs each requested group separately.

| Group | Codes |
|---|---|
| `contracts` | `A` BPA call · `B` purchase order · `C` delivery order · `D` definitive contract |
| `grants` | `02` block grant · `03` formula grant · `04` project grant · `05` cooperative agreement |
| `loans` | `07` direct loan · `08` guaranteed / insured loan |
| `idvs` | `IDV_A` GWAC · `IDV_B` IDC (multi-agency / other) · `IDV_B_A` requirements · `IDV_B_B` IDIQ · `IDV_B_C` definite quantity · `IDV_C` FSS · `IDV_D` BOA · `IDV_E` BPA |

#### Reporting lag

Agencies report to USAspending after the fact. Civilian agencies usually appear within a few days to 30 days;
**the Department of Defense delays contract data by about 90 days**, so a 7-day DoD window shows only a trickle
(mostly modifications). For DoD watchlists use `lookbackDays: 30–120`; the seen-state keeps the feed free of
duplicates regardless of how wide the window is.

### Recommended setup for a daily feed

1. Create a task with your filters and set `monitorId` to something meaningful (`competitors-it`).
2. **First run: set `firstRunMode` to `baseline`** and `lookbackDays` to 90. This records everything currently
   matching, emits nothing, and stops your first day from being a 2,000-row backlog.
3. Switch `firstRunMode` back to `emitAll` (it only matters when the state is empty anyway), keep `lookbackDays`
   wide (30 civilian, 120 DoD) and raise `maxNewPerFilter` / `maxItems` to 200+.
4. **Schedule the task daily.** USAspending loads new agency submissions overnight (US time), so a run at
   06:00–08:00 America/New\_York catches the previous day's load.
5. Point `webhookUrl` at Slack (incoming webhook), Zapier, Make, or your own endpoint.

The default settings (`{}`) run in `emitAll` mode on Department of Defense contracts so you see real output on
the first try.

### Example: competitor and NAICS watch for an IT services firm

```json
{
  "recipients": ["Booz Allen", "Leidos", "Guidehouse"],
  "naicsCodes": ["541512", "541519"],
  "pscCodes": ["D"],
  "agencies": ["HHS", "VA", "DHS"],
  "awardTypes": ["contracts", "idvs"],
  "minAmount": 250000,
  "lookbackDays": 30,
  "maxNewPerFilter": 100,
  "maxItems": 500,
  "firstRunMode": "baseline",
  "webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
  "monitorId": "it-competitors-civilian"
}
```

Other quick profiles:

- **Construction subcontracting in one agency**: `naicsCodes: ["236220", "237310"]`, `agencies: ["Department of Veterans Affairs", "General Services Administration"]`
- **Research grants by topic**: `awardTypes: ["grants"]`, `keywords: ["quantum", "photonics"]`, `agencies: []`
- **New IDIQ vehicles government-wide**: `awardTypes: ["idvs"]`, `agencies: []`, `minAmount: 10000000`

### Output

One record per new or modified award:

```json
{
  "awardId": "N0002424F8580",
  "piid": "N0002424F8580",
  "fain": null,
  "generatedInternalId": "CONT_AWD_N0002424F8580_9700_N0002417D6421_9700",
  "awardCategory": "contracts",
  "awardType": "DELIVERY ORDER",
  "recipientName": "UNIVERSITY OF TEXAS AT AUSTIN",
  "recipientUei": "MG1PPMPNS9G3",
  "recipientLocation": { "city": "AUSTIN", "state": "TX", "zip": "78758", "country": "UNITED STATES" },
  "awardAmount": 146250,
  "totalObligation": 146250,
  "description": "TIME FREQUENCY ENHANCEMENT OF GNSS MONITOR STATIONS",
  "naicsCode": "541712",
  "naicsDescription": "RESEARCH AND DEVELOPMENT IN THE PHYSICAL, ENGINEERING, AND LIFE SCIENCES (EXCEPT BIOTECHNOLOGY)",
  "pscCode": "AC32",
  "pscDescription": "NATIONAL DEFENSE R&D SERVICES; DEFENSE-RELATED ACTIVITIES; APPLIED RESEARCH",
  "cfdaNumber": null,
  "awardingAgency": "Department of Defense",
  "awardingSubAgency": "Department of the Navy",
  "fundingAgency": "Department of Transportation",
  "fundingSubAgency": "Immediate Office of the Secretary of Transportation",
  "dateSigned": "2024-09-12",
  "startDate": "2024-09-12",
  "endDate": "2027-09-30",
  "periodOfPerformanceEnd": "2027-09-30",
  "lastModifiedDate": "2026-09-25 14:33:49",
  "placeOfPerformanceState": "TX",
  "placeOfPerformanceCity": "AUSTIN",
  "parentAwardId": "N0002417D6421",
  "usaspendingUrl": "https://www.usaspending.gov/award/CONT_AWD_N0002424F8580_9700_N0002417D6421_9700",
  "matchedFilter": "agency:Department of Defense",
  "changeType": "new",
  "previousAmount": null,
  "firstSeenAt": "2026-09-28T21:47:59.037Z",
  "monitorId": "default"
}
```

`awardId` is the PIID for contracts and IDVs and the FAIN for grants and loans. `awardAmount` is the obligated
amount (loan value for loans). `firstSeenAt` is set on `new` records; `updated` records carry `previousAmount`
instead. Grants and loans have no NAICS/PSC but carry `cfdaNumber`. With `includeDetails: false` the
detail-only fields (`recipientUei`, `recipientLocation`, `totalObligation`, `dateSigned`,
`periodOfPerformanceEnd`, `placeOfPerformanceCity`, `parentAwardId`) are `null`.

### Webhook payload

POSTed once per run as `application/json`, also saved as the `SUMMARY` record in the run's key-value store:

```json
{
  "monitorId": "it-competitors-civilian",
  "runAt": "2026-09-29T11:00:03.118Z",
  "newCount": 7,
  "updatedCount": 2,
  "scanned": 412,
  "seenTotal": 1830,
  "baseline": false,
  "awards": [ { "...first 50 records, same shape as the dataset..." } ]
}
```

The full list is always in the run's dataset; use the Apify API or an integration to pull it if a run
produces more than 50.

### Pricing

Pay per event: a small start fee plus a per-award fee **only for records emitted**. A daily monitor that finds
nothing new costs just the start fee.

### Notes

- A watch item scans at most 3,000 awards per group per run (newest-modified first). Narrow the filters or
  shorten the lookback if a profile exceeds that.
- Agency names must be top-tier departments; sub-agencies (Navy, NIH, FEMA) are not accepted as filters but
  appear in `awardingSubAgency` on every record.
- Recipient search is USAspending's own name search, so it also returns subsidiaries and DBAs.
- Data comes from USAspending.gov's public API and is limited to transactions since FY2008.

# Actor input Schema

## `recipients` (type: `array`):

Watch these recipients, e.g. "Lockheed", "Booz Allen", "University of Texas". Partial names match (USAspending recipient search). Each name is its own watch item; a match is tagged matchedFilter: "recipient:<name>". Empty = no recipient restriction.

## `agencies` (type: `array`):

Top-tier awarding agency names, e.g. "Department of Defense", "Department of Veterans Affairs", "General Services Administration", "Department of Health and Human Services". Sub-tier agencies (e.g. NIH, Navy) are not accepted; use their department. Abbreviations like DOD, VA, GSA, HHS, DHS, NASA are resolved automatically. Applies to every watch item. Empty = all agencies.

## `naicsCodes` (type: `array`):

Watch these NAICS codes, e.g. 541512, 541519, 236220. 2-6 digit prefixes are accepted (54 = all professional services). Each code is its own watch item (matchedFilter: "naics:<code>").

## `pscCodes` (type: `array`):

Watch these Product/Service Codes, e.g. R425, D302, 7030. A 1-2 character prefix matches the whole family (D = all IT services). Each code is its own watch item (matchedFilter: "psc:<code>").

## `keywords` (type: `array`):

Watch these terms in award descriptions, e.g. "radar", "cloud migration", "zero trust". Each keyword is its own watch item (matchedFilter: "keyword:<term>").

## `awardTypes` (type: `array`):

Groups: contracts (A BPA call, B purchase order, C delivery order, D definitive contract), grants (02 block, 03 formula, 04 project, 05 cooperative agreement), loans (07 direct, 08 guaranteed), idvs (IDV\_A GWAC, IDV\_B IDC, IDV\_C FSS, IDV\_D BOA, IDV\_E BPA). Group names or raw codes are accepted.

## `minAmount` (type: `integer`):

Ignore awards below this obligated amount. 0 = no minimum.

## `lookbackDays` (type: `integer`):

Only consider awards with a transaction (new award or modification) dated within this many days. Agencies report to USAspending with a delay (most within 30 days; Department of Defense up to 90 days), so keep the window wide; the seen-state prevents duplicates.

## `includeDetails` (type: `boolean`):

Fetch each emitted award's detail record (recipient UEI and location, total obligation, period of performance, parent IDV, funding agency). One extra request per emitted award.

## `maxNewPerFilter` (type: `integer`):

Stop scanning a watch item (one recipient, NAICS, PSC or keyword) after emitting this many awards. Awards beyond the cap stay unseen and come out on the next run.

## `maxItems` (type: `integer`):

Overall cap on emitted awards per run across all watch items.

## `firstRunMode` (type: `string`):

What to do when the monitor has no saved state yet. emitAll: treat every current match as new and emit it (good for a one-off pull or a first test). baseline: silently record every current match as seen and emit nothing, so the next scheduled run reports only what changed since.

## `webhookUrl` (type: `string`):

Optional. After each run a JSON summary {monitorId, runAt, newCount, updatedCount, awards\[first 50]} is POSTed here (Slack/Zapier/Make/your API).

## `monitorId` (type: `string`):

Name of this watchlist. Each monitor ID keeps its own seen-state in a key-value store named award-monitor-<hash>, so you can run several profiles (e.g. "competitors-dod", "it-naics-civilian") side by side.

## Actor input object example

```json
{
  "recipients": [],
  "agencies": [
    "Department of Defense"
  ],
  "naicsCodes": [],
  "pscCodes": [],
  "keywords": [],
  "awardTypes": [
    "contracts"
  ],
  "minAmount": 0,
  "lookbackDays": 7,
  "includeDetails": true,
  "maxNewPerFilter": 10,
  "maxItems": 10,
  "firstRunMode": "emitAll",
  "webhookUrl": "",
  "monitorId": "default"
}
```

# Actor output Schema

## `records` (type: `string`):

Dataset of new or modified federal awards found in this run (JSON).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "agencies": [
        "Department of Defense"
    ],
    "awardTypes": [
        "contracts"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("chimerical_quicklime/federal-award-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "agencies": ["Department of Defense"],
    "awardTypes": ["contracts"],
}

# Run the Actor and wait for it to finish
run = client.actor("chimerical_quicklime/federal-award-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "agencies": [
    "Department of Defense"
  ],
  "awardTypes": [
    "contracts"
  ]
}' |
apify call chimerical_quicklime/federal-award-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chimerical_quicklime/federal-award-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/6NwjmMQclvlam1Gaa/builds/2UdPTBGb8HrBIuhTA/openapi.json
