# SAM.gov & Grants.gov Scraper: Government Contracts & Grants (`yourevenings/us-gov-opportunities`) Actor

SAM.gov contract opportunities and Grants.gov federal grants in one feed, no API key needed. Contract filters (keyword, NAICS, agency, set-aside, notice type, due date) are applied to every row. Daily alerts and next-day amendment alerts.

- **URL**: https://apify.com/yourevenings/us-gov-opportunities.md
- **Developed by:** [Your Evenings](https://apify.com/yourevenings) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 opportunity returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## SAM.gov & Grants.gov Scraper: Government Contracts & Grants

**SAM.gov Contract & Grants.gov Opportunities API** gives you new US federal **contract opportunities** (from SAM.gov) and **grant opportunities** (from Grants.gov) in one clean, filterable dataset, with **no API key needed**. Filter by keyword, NAICS code, agency, set-aside type, posted date and due date. Turn on **monitor mode** and schedule it daily to get a feed of only the new matches, or **track solicitation numbers** to get a row when one of them is amended or changes.

> **Not an official government product.** This Actor is independent and is not affiliated with or endorsed by GSA, SAM.gov or Grants.gov. It uses data those services publish for the public.

### Why this one

- **No SAM.gov API key needed.** Contracts come from SAM.gov's public daily extract, so there's no key to register, rotate or rate-limit.
- **Filters are applied in code before you're charged, and you see how much matched.** On SAM.gov contracts, notice type, NAICS, PSC code, place-of-performance state, set-aside, agency, due date and keywords (as whole phrases, listed in `matchedKeywords`) are checked on every row. On Grants.gov, agency and due date are checked in code and keywords use Grants.gov's own search. Each run reports how many opportunities matched out of how many were posted in the window, even when `maxResults` stops it returning more.
- **Saved dates roll forward.** `postedWithinDays` counts back from each run, so a scheduled run always covers the latest days.
- **Contracts and grants in one schema,** with `monitorMode` for new-only daily alerts.
- **Know when a solicitation you're bidding on changes.** Add its number to `trackSolicitationNumbers` and get a row for each new amendment or notice, deadline move, notice type change or notice leaving the active list, with before and after values. Alerts are next-day, because SAM.gov's extract is refreshed daily.
- **You're told when the data is stale or a source fails.** Every row has `source_updated_at`. If SAM.gov's extract is more than 36 hours old or empty, or either source fails, the run adds a free warning row and says so in its status message, so a quiet day isn't mistaken for a broken feed.

### Quick start

Paste this into the **JSON** view of the Input tab and press **Start**. It returns up to 10 SAM.gov contract opportunities and up to 10 Grants.gov grants posted in the last 7 days that match "cybersecurity", newest first.

```json
{
  "opportunityType": "both",
  "keywords": [
    "cybersecurity"
  ],
  "postedWithinDays": 7,
  "maxResults": 10
}
```

For more ready-made inputs, see the [example tasks](https://apify.com/yourevenings/us-gov-opportunities/examples).

**Works with:** SAM.gov (contract opportunities) · Grants.gov (grants)

**Runs on** <img src="https://yourevenings.com/logos/apify-logo-dark.svg" alt="Apify" height="20"> Apify. Use it from Make, Zapier, <img src="https://yourevenings.com/logos/n8n-logo-black.svg" alt="n8n" height="16"> n8n or the Apify API.

<sub>Product names and logos belong to their owners. Your Evenings Ltd is not affiliated with or endorsed by them. This product uses the Grants.gov API but is not endorsed or certified by the U.S. Department of Health and Human Services.</sub>

Use it as a **SAM.gov scraper**, a **SAM.gov opportunities API** without registering for a key, a **Grants.gov API** client, or a **government contract alert** for your bid team.

### Where the data comes from

| Source | What | How |
|---|---|---|
| SAM.gov Contract Opportunities | Solicitations, combined synopsis/solicitations, presolicitations, sources sought, special notices, justifications (and award notices if you ask) | SAM.gov's **public daily data extract** (Contract Opportunities CSV from SAM.gov Data Services), refreshed by SAM.gov once a day |
| Grants.gov | Posted and forecasted federal grant opportunities | The **public Grants.gov REST API** (`search2` and `fetchOpportunity`) |

No login, API key or browser is used. The SAM.gov extract lists notices newest first, so the Actor reads only the part that covers your date window and stops. In a test on 21 Oct 2026, a 7-day window meant reading about 23 MB (8,104 rows) of the extract, in under 2 seconds.

**Freshness:** SAM.gov contract notices come from SAM.gov's **public daily extract**, which SAM.gov regenerates once a day, so they **can be up to about a day old** (a notice posted today usually appears tomorrow). **Grants.gov results are live**, read from the Grants.gov API during the run. Every row has a `source_updated_at` timestamp (ISO 8601, UTC) and a `source_updated_at_basis` saying what it means:

- `sam_extract_last_modified`: SAM.gov rows. The time SAM.gov last refreshed the extract file the row came from.
- `grants_opportunity_last_updated`: Grants.gov rows. The opportunity's own last-updated time on Grants.gov.
- `grants_api_fetched_at`: Grants.gov rows where Grants.gov gives no update time. The time the Actor fetched it from the live API.

### What you can use it for

- **Daily bid alerts.** Save your NAICS codes, set-asides and agencies, turn on monitor mode and schedule a daily run. You get only the notices you haven't seen before (see Pricing for what each run is charged).
- **Amendment alerts on bids you're working.** Track the solicitation numbers your team is bidding on and see deadline moves, new amendments and notices that leave the active list the next morning.
- **Grant prospecting.** Track new NIH, NSF, USDA or other agency funding opportunities by keyword, with award ceiling and floor, expected number of awards and eligible applicant types.
- **Market research.** Pull every notice for an agency or NAICS code over a period and analyse it in a spreadsheet or BI tool.
- **Feeds for AI agents and CRMs.** One normalised schema across both sources.

### Example tasks (ready-made inputs)

- [IT services contract opportunities on SAM.gov (NAICS 541511, 541512, 541519)](https://apify.com/yourevenings/us-gov-opportunities/examples/it-services-contracts)
- [Small business set-aside contracts posted this week](https://apify.com/yourevenings/us-gov-opportunities/examples/small-business-set-aside-contracts)
- [NIH and NSF research grants on Grants.gov](https://apify.com/yourevenings/us-gov-opportunities/examples/nih-nsf-research-grants)
- [Construction contract opportunities on SAM.gov](https://apify.com/yourevenings/us-gov-opportunities/examples/construction-contracts)
- [Daily federal bid alerts for your keywords](https://apify.com/yourevenings/us-gov-opportunities/examples/daily-federal-bid-alerts)
- [SAM.gov contracts by place-of-performance state](https://apify.com/yourevenings/us-gov-opportunities/examples/sam-gov-contracts-by-state)
- [SAM.gov contracts by PSC code](https://apify.com/yourevenings/us-gov-opportunities/examples/sam-gov-contracts-by-psc-code)

### Input

| Field | What it does | Default |
|---|---|---|
| `opportunityType` | `both`, `contracts` (SAM.gov) or `grants` (Grants.gov) | `both` |
| `keywords` | Any of these words or phrases | none |
| `naicsCodes` | NAICS code prefixes, e.g. `541511` or `5415` (contracts only) | none |
| `agencies` | Text that the department, sub-agency, office or agency code contains | none |
| `setAsideTypes` | SAM.gov set-aside codes (`SBA`, `8A`, `HZC`, `SDVOSBC`, `WOSB`, ... or `ANY`) (contracts only) | none |
| `postedWithinDays` / `postedSince` | Date window (N days back, or an exact YYYY-MM-DD start) | last 7 days |
| `dueAfter` | Response deadline / close date on or after YYYY-MM-DD | none |
| `maxResults` | Max opportunities per source, newest first (0 = all matches in the window) | 10 |
| `monitorMode` | Return only opportunities not returned by an earlier monitor run | off |
| `emitBaselineOnFirstRun` | In monitor mode, return all matches on the very first run | on |
| `trackSolicitationNumbers` | SAM.gov solicitation numbers to watch for changes (up to 500). When set, the run is a tracking run: see below | none |
| `stateStoreName` | Named key-value store holding seen IDs and tracked-solicitation state | `us-gov-opportunities-state` |
| `includeDescription` | Short plain-text description snippet | on |
| `includeContacts` | Point-of-contact fields exactly as published on each notice | off |
| `includeAwardNotices` | Include SAM.gov award notices | off |
| `pscCodes` | Product/service code (PSC) prefixes, e.g. `R4`, `D` or `J059` (contracts only) | none |
| `placeOfPerformanceStates` | Place-of-performance states: 2-letter codes or names, e.g. `VA`, `Maryland`, `DC` (contracts only) | none |
| `samNoticeTypes` | Keep only these SAM.gov notice types | all |
| `grantStatuses` | `posted` and/or `forecasted` | both |
| `activeOnly` | Skip inactive SAM.gov notices | on |

NAICS, set-aside, PSC and place-of-performance filters exist only on contract notices, so setting any of them skips Grants.gov (the run summary says so).

**Place-of-performance state.** The filter uses the state SAM.gov lists as the notice's place of performance. Many notices list none (about 3 in 4 in the extract on 22 Oct 2026, often services that can be performed anywhere or overseas), and those never match a state filter. The run summary says how many matching notices were excluded for that reason.

Example: small-business IT contracts from the VA plus related grants, due at least a week out:

```json
{
  "opportunityType": "both",
  "keywords": ["software", "cybersecurity"],
  "agencies": ["VETERANS AFFAIRS"],
  "postedWithinDays": 7,
  "dueAfter": "2026-10-28",
  "maxResults": 100
}
```

Example: professional-support and IT services contracts (PSC R4 and D) performed in Virginia, Maryland or DC:

```json
{
  "opportunityType": "contracts",
  "pscCodes": ["R4", "D"],
  "placeOfPerformanceStates": ["VA", "MD", "DC"],
  "postedWithinDays": 7,
  "maxResults": 100
}
```

Example: daily alert for NAICS 5415 small-business set-asides:

```json
{
  "opportunityType": "contracts",
  "naicsCodes": ["5415"],
  "setAsideTypes": ["SBA", "SDVOSBC", "WOSB", "8A"],
  "postedWithinDays": 2,
  "maxResults": 0,
  "monitorMode": true,
  "stateStoreName": "it-set-aside-alerts"
}
```

### Output

One row per opportunity. A contract (SAM.gov):

```json
{
  "source": "sam.gov",
  "opportunityType": "contract",
  "opportunityId": "e5a50c4bacc5478bbea335f8ca2c1d89",
  "noticeId": "e5a50c4bacc5478bbea335f8ca2c1d89",
  "solicitationNumber": null,
  "title": "Systems Warfighting Architecture Navigator (SWAN) Operations, Sustainment, and Decision Support Services",
  "agency": "DEPT OF DEFENSE",
  "subAgency": "DEPT OF THE AIR FORCE",
  "office": "FA8802 INTEGRATION OPERATION PIKPKE",
  "agencyCode": "057",
  "noticeType": "Special Notice",
  "baseNoticeType": "Sources Sought",
  "status": "active",
  "naicsCodes": [],
  "classificationCode": null,
  "setAsideCode": null,
  "setAside": null,
  "postedDate": "2026-10-20",
  "responseDeadline": "2026-10-27T00:00:00.000Z",
  "responseDeadlineEstimated": false,
  "archiveDate": "2026-10-29",
  "placeOfPerformance": { "city": "El Segundo", "state": "CA", "zip": "90245", "country": "USA" },
  "url": "https://sam.gov/opp/e5a50c4bacc5478bbea335f8ca2c1d89/view",
  "descriptionSnippet": "Description Space Systems Command (SSC) is hosting a virtual Industry Day in anticipation of a forthcoming solicitation…",
  "matchedKeywords": [],
  "attachments": null,
  "changeType": null,
  "retrievedAt": "2026-10-21T17:59:02.158Z",
  "source_updated_at": "2026-10-21T03:30:45.000Z",
  "source_updated_at_basis": "sam_extract_last_modified"
}
```

A grant (Grants.gov), shortened:

```json
{
  "source": "grants.gov",
  "opportunityType": "grant",
  "opportunityId": "364134",
  "solicitationNumber": "HHS-2027-ACF-ORR-ZU-0045",
  "title": "Residential Services for Unaccompanied Alien Children",
  "agency": "Department of Health and Human Services",
  "subAgency": "Administration for Children and Families - ORR",
  "noticeType": "Forecast",
  "status": "forecasted",
  "postedDate": "2026-10-21",
  "responseDeadline": "2027-01-12",
  "responseDeadlineEstimated": true,
  "estimatedFunding": 280000000,
  "awardCeiling": 5600000,
  "awardFloor": 2000000,
  "numberOfAwards": 50,
  "assistanceListings": [{ "number": "93.676", "title": "Unaccompanied Children Program" }],
  "fundingCategories": ["Income Security and Social Services"],
  "url": "https://www.grants.gov/search-results-detail/364134",
  "attachments": [],
  "source_updated_at": "2026-10-21T17:49:44.000Z",
  "source_updated_at_basis": "grants_opportunity_last_updated"
}
```

Both sources share the same fields; fields that don't apply to a source are `null` or empty. The Output tab has **Overview**, **Contracts** and **Grants** views. A run summary (filters, rows per source, rows scanned, extract date, timings, warnings) is saved as `SUMMARY` in the run's key-value store.

**Matched vs scanned.** `SUMMARY.totals` has, per source, how many rows were scanned, how many were posted in your date window, how many matched your filters and how many were returned (plus, in monitor mode, how many were skipped as already reported). The status message says the same in one line, e.g. "SAM.gov: 5 returned, 45 matched of 6,156 posted in the window (8,156 extract rows read)". So when `maxResults` cuts a run short, you can see how many more matches there were.

**Warning rows (free).** The run adds a status row (`rowType: "status"`, never charged) when:

- SAM.gov's extract was last refreshed more than 36 hours before the run (`stale_data`). SAM.gov normally refreshes it daily, so notices posted since then aren't in the run yet.
- SAM.gov's extract had no rows (`no_data`), or its refresh time couldn't be read (`unknown_freshness`).
- Grants.gov returned nothing for a search without keywords (`no_data`).
- Either source failed (`source_error`).

**Attachments.** Grants.gov rows list the documents Grants.gov attaches to the opportunity (file name, description, folder and size) in `attachments`. Grants.gov's API doesn't give a download link, so `url` is `null` for files; open the opportunity's `url` to download them. For example, on 22 Oct 2026 DE-FOA-0003630 listed:

```json
"attachments": [
  { "type": "file", "fileName": "NOFO_DE-FOA-0003630_UNLOCK.pdf", "description": "NOFO_DE-FOA-0003630_UNLOCK", "folder": "DE-FOA-0003630 (BASE)", "folderType": "Full Announcement", "sizeBytes": 1114696, "url": null }
]
```

Forecasts often have no attachments yet (`[]`). Document links Grants.gov lists are included with their `url`. Contract rows have `attachments: null`, because SAM.gov's public extract has no attachment data; use the notice's `url` to see its attachments on SAM.gov.

**Contacts.** Notices carry the contracting officer or agency contact. With `includeContacts` on, each row gets those fields exactly as published on that notice. They're never collected into a separate contacts list, and they're off by default.

### Monitor mode: only new opportunities

1. Turn on `monitorMode`, pick a `stateStoreName` for this saved search, and schedule the Actor (daily is typical).
2. The first run returns all current matches (or, with `emitBaselineOnFirstRun` off, just remembers them).
3. Later runs return only opportunities whose ID hasn't been returned before, with `changeType: "new"`. A run with no new matches returns an empty dataset and costs only the Actor start.

If a run stops early because it reached your maximum charge, the undelivered opportunities are returned on the next run.

### Solicitation tracking: amendment and change alerts

Put the solicitation numbers you care about in `trackSolicitationNumbers` and schedule a daily run. Numbers are matched without case, spaces or punctuation, so `W912DY-26-R-0001` and `w912dy26r0001` are the same.

```json
{
  "trackSolicitationNumbers": ["1240LT26Q0109", "W912DY26R0001"],
  "stateStoreName": "my-bids-watchlist"
}
```

How it works:

1. Each run reads SAM.gov's **whole** public daily extract (about 210 MB and 71,000 active notices on 22 Oct 2026; about 8 seconds per run in our platform tests) and picks out every active notice under your numbers. In SAM.gov's extract, each amendment or follow-on notice appears as a new notice ID under the same solicitation number.
2. The first run for a number only remembers its current notices and returns a free status row (`tracking_started`, or `not_found` if the number isn't in the active extract yet).
3. Later runs compare with what was saved and return one **change row** (`rowType: "change"`) for each:
   - `new_notice`: a new notice or amendment under the number. `changes` lists the fields that differ from the previous latest notice (response deadline, notice type, base notice type, set-aside, NAICS, product/service code, title, archive date, place of performance, award fields, additional info link, description text), with `before` and `after`.
   - `notice_updated`: a notice already seen was edited in place (same fields, plus posted date).
   - `notice_removed`: a notice is no longer in the active extract. SAM.gov's extract doesn't say whether it was archived, cancelled or taken down, so check the notice on SAM.gov.
4. Numbers with no change get a free `unchanged` status row, so every tracked number appears in every run.

Each change row has `changeSummary` (plain English), `changes`, `trackedSolicitationNumber`, `comparedWithNoticeId`, `detectedAt` and the usual contract fields of the notice, plus `source_updated_at` (the extract's Last-Modified time). The **Tracked solicitation changes** view in the Output tab shows them.

What to know:

- **Alerts are next-day, not real-time.** SAM.gov refreshes the extract about once a day (on 21 and 22 Oct 2026, at about 03:30 UTC), so a change posted today is usually reported by a run the next day. Schedule the run after 04:00 UTC. If the extract hasn't been refreshed since the last run, the status rows say so.
- **Attachments aren't in the extract.** A change that only adds or replaces an attachment is seen only if SAM.gov also posts it as a new notice or edits the notice's fields.
- Search filters (keywords, NAICS, dates and so on) and `monitorMode` aren't used in tracking runs, and Grants.gov isn't checked.
- Keep one `stateStoreName` per watch list. If a run stops at your maximum charge, the changes it couldn't return are kept and returned on the next run (a free `changes_pending` status row says how many).

A change row from a platform test run on 22 Oct 2026, shortened:

```json
{
  "rowType": "change",
  "changeType": "new_notice",
  "trackedSolicitationNumber": "1240-LT26-Q0109",
  "changeSummary": "New Combined Synopsis/Solicitation posted 2026-10-21. Compared with notice d35a9184d1bf49fc93a17a1074c6b9a0 (2026-10-16): response deadline 2026-11-04T22:00:00.000Z → 2026-11-17T22:00:00.000Z; archive date 2026-11-19 → 2026-12-02; description text changed.",
  "changes": [
    { "field": "responseDeadline", "label": "response deadline", "before": "2026-11-04T22:00:00.000Z", "after": "2026-11-17T22:00:00.000Z" },
    { "field": "archiveDate", "label": "archive date", "before": "2026-11-19", "after": "2026-12-02" },
    { "field": "description", "label": "description text", "before": "previous text", "after": "new text" }
  ],
  "comparedWithNoticeId": "d35a9184d1bf49fc93a17a1074c6b9a0",
  "source": "sam.gov",
  "noticeId": "cbe71bb9577648beb6b5961f0588c070",
  "solicitationNumber": "1240LT26Q0109",
  "title": "4 GAOA Flaming Gorge Water System Buckboard in Ashley NF, Wyoming",
  "noticeType": "Combined Synopsis/Solicitation",
  "postedDate": "2026-10-21",
  "responseDeadline": "2026-11-17T22:00:00.000Z",
  "archiveDate": "2026-12-02",
  "url": "https://sam.gov/opp/cbe71bb9577648beb6b5961f0588c070/view",
  "detectedAt": "2026-10-22T09:51:13.933Z",
  "source_updated_at": "2026-10-22T03:30:44.000Z",
  "source_updated_at_basis": "sam_extract_last_modified"
}
```

### Pricing

Pay per event. You pay for results, not compute:

| Event | When it is charged | Price |
|---|---|---|
| Actor start | Once per run (per GB of memory; the default 256 MB run counts as one) | $0.00005 |
| Opportunity | Each opportunity row returned, and each change row in a tracking run | $0.003 |
| Alert run with matches | Monitor mode and solicitation tracking: once per run that returns at least one new opportunity or change | $0.01 |

Status rows in tracking runs (`tracking_started`, `unchanged`, `not_found`, `changes_pending`) are free.

The $0.01 "Alert run with matches" event covers both monitor runs that find new opportunities and tracking runs that find amendments or changes. A run that finds none pays nothing for this event. The event's short description on the Pricing tab mentions monitor mode only, but tracking runs are charged the same way.

Higher Apify plans get tier discounts (Silver −10%, Gold −20%). Prices on the Actor's Pricing tab are authoritative.

Examples at the base price:

- The default run (10 contracts + 10 grants): 20 × $0.003 = about $0.06.
- A one-off pull of 500 notices: 500 × $0.003 = $1.50.
- A daily monitor run with 20 new matches: 20 × $0.003 + $0.01 = $0.07 (about $2.10 a month). Days with no new matches cost $0.00005.
- A daily tracking run on 20 solicitation numbers where 3 changed: 3 × $0.003 + $0.01 = $0.019. A day with no changes costs $0.00005 (20 free status rows).

The Actor respects the **maximum cost per run** you set and says so in the status message when it stops early.

### Use it from code, spreadsheets or an AI agent

- **Schedule it**: Console > Schedules, daily, with `monitorMode` on, to get a new-opportunities feed.

- **Google Sheets, Make, Zapier, n8n, Slack**: use the Actor's Integrations tab to send each run's dataset where you need it.

- **API (Python)**:

  ```python
  from apify_client import ApifyClient
  client = ApifyClient("<YOUR_APIFY_TOKEN>")
  run = client.actor("yourevenings/us-gov-opportunities").call(run_input={"opportunityType": "contracts", "naicsCodes": ["541511"]})
  for item in client.dataset(run["defaultDatasetId"]).iterate_items():
      print(item["source"], item["title"], item.get("agency"), item.get("responseDeadline"))
  ```

- **AI agents**: the Actor can be run through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so Claude, ChatGPT or Cursor agents can call it with their own input.

#### AI agents can pay for runs themselves

AI agents can run this Actor and pay with stablecoins such as USDC through the x402 or MPP protocols, with no Apify account needed. The agent buys a prepaid, spend-capped Apify API token from Apify's Agent General Interface (AGI) and then runs the Actor with it as normal. Prepaid tokens only run Actors that use limited permissions, and this Actor does. Agentic payments are an experimental Apify feature, and the terms (minimum amount, expiry, usage limits) are set by Apify. See Apify's docs: [Let your AI agent pay for Actor runs](https://docs.apify.com/agents/payments), [x402](https://docs.apify.com/integrations/x402) and [MPP](https://docs.apify.com/integrations/mpp).

### FAQ

**Do I need a SAM.gov API key?**
No. Contract notices come from SAM.gov's public daily data extract and grants from the public Grants.gov API. Neither needs a key.

**Is this an official SAM.gov or Grants.gov product?**
No. This is not an official government product. It's an independent tool and is not affiliated with or endorsed by GSA, SAM.gov, Grants.gov or any other agency. It uses their public data.

**How current is it?**
Grants.gov is live. SAM.gov contract notices come from SAM.gov's public daily extract, so they can be up to about a day old compared with SAM.gov's website. Check `source_updated_at` on each row. Check the solicitation on SAM.gov before bidding: amendments and deadlines change.

**Can it tell me when a solicitation is amended?**
Yes, next-day: list the numbers in `trackSolicitationNumbers` and schedule a daily run (see Solicitation tracking). Changes come from SAM.gov's daily extract, so they show up the day after SAM.gov publishes them, and attachment-only changes aren't visible.

**Which notices are included by default?**
Active SAM.gov notices of every type except award notices, and posted plus forecasted grants. Use `includeAwardNotices`, `samNoticeTypes` and `grantStatuses` to change that.

**Why did my NAICS filter return no grants?**
Grants don't have NAICS codes or set-asides, so those filters search contracts only.

**Can I get older notices?**
Set `postedSince` to an earlier date. The SAM.gov extract covers currently published notices; archived notices aren't included.

**Is it legal to use this data?**
It's US federal government information that agencies publish for the public. If you turn on contacts, use them only to respond to the notice they came from, and follow the laws that apply to you.

### Feedback

Missing a filter, field or notice type? Open an issue on the Issues tab with your input and run ID, and it'll be looked at quickly.

# Actor input Schema

## `opportunityType` (type: `string`):

Which sources to search: federal contract opportunities from SAM.gov, grant opportunities from Grants.gov, or both.

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

Return opportunities that match any of these words or phrases. For contracts they are matched (whole words, case-insensitive) against the title, solicitation number and description. For grants, each keyword is sent to the Grants.gov search. Leave empty for all opportunities.

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

Contract notices whose NAICS code starts with any of these, for example <code>541511</code> or <code>5415</code> for all computer systems design services. Setting this skips Grants.gov, which has no NAICS codes.

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

Keep opportunities whose department, sub-agency, office or agency code contains any of these (case-insensitive), for example <code>VETERANS AFFAIRS</code>, <code>DEPT OF THE NAVY</code>, <code>National Institutes of Health</code> or <code>HHS-NIH11</code>.

## `setAsideTypes` (type: `array`):

SAM.gov set-aside codes, for example <code>SBA</code> (total small business), <code>SBP</code>, <code>8A</code>, <code>8AN</code>, <code>HZC</code> (HUBZone), <code>SDVOSBC</code>, <code>WOSB</code>, <code>EDWOSB</code>, <code>ISBEE</code>, or <code>ANY</code> for any set-aside. Setting this skips Grants.gov.

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

Contract notices whose product/service code (PSC, SAM.gov's <code>ClassificationCode</code>) starts with any of these, for example <code>R4</code> (professional support services), <code>D</code> (IT and telecom services, such as <code>DA01</code>) or <code>J059</code>. Applied before you're charged. Setting this skips Grants.gov, which has no PSC codes.

## `placeOfPerformanceStates` (type: `array`):

Contract notices whose place of performance is in one of these US states, DC or territories: 2-letter codes (<code>VA</code>) or names (<code>Virginia</code>). Applied before you're charged. Many notices list no place-of-performance state (about 3 in 4 in the extract on 22 Oct 2026); they never match this filter, and the run summary says how many were excluded for that reason. Setting this skips Grants.gov.

## `postedWithinDays` (type: `integer`):

Only opportunities posted in the last N days (0 = today only). Ignored when 'Posted since' is set.

## `postedSince` (type: `string`):

Optional exact start date, YYYY-MM-DD. Overrides 'Posted within the last N days'.

## `dueAfter` (type: `string`):

Optional, YYYY-MM-DD. Keep only opportunities whose response deadline or close date is on or after this date. Opportunities without a deadline are excluded when this is set.

## `maxResults` (type: `integer`):

Stop after this many opportunities from each source, newest first. 0 means all matches in the date window. The small default keeps test runs quick and cheap.

## `monitorMode` (type: `boolean`):

When on, only opportunities that weren't returned in an earlier monitor run are returned (<code>changeType: "new"</code>). Schedule the Actor daily with the same input to get a new-matches feed. Seen opportunity IDs are kept in the named key-value store below for 400 days.

## `emitBaselineOnFirstRun` (type: `boolean`):

In monitor mode, the first run has nothing to compare with. When on, it returns all current matches (charged as usual). When off, it only remembers them and returns nothing.

## `trackSolicitationNumbers` (type: `array`):

SAM.gov solicitation numbers to watch, e.g. <code>W912DY26R0001</code>. When set, the run reads SAM.gov's whole public daily extract and returns a row for each change since the last run: a new notice or amendment under the number (with response deadline, notice type, set-aside and other fields before and after), an edit to a known notice, or a notice leaving the active extract. Search filters are not used in these runs. Changes show up the day after SAM.gov publishes them, because the extract is refreshed about once a day. Attachments are not in the extract, so attachment-only changes are not seen. Each change row is charged as one opportunity, plus the alert event once on runs with changes; status rows (first run, no change, not found) are free. State is kept in the key-value store named below. Up to 500 numbers.

## `stateStoreName` (type: `string`):

Named key-value store in your account that remembers which opportunities were already returned (monitor mode) and the last known state of tracked solicitation numbers. Use a different name for each separate saved search or watch list.

## `includeDescription` (type: `boolean`):

Add a short plain-text <code>descriptionSnippet</code> (up to about 300 characters). The full notice is at <code>url</code>.

## `includeContacts` (type: `boolean`):

Add the point-of-contact fields exactly as published on each notice (name, title, email, phone). Off by default. They are passed through per notice, never compiled into a separate people list.

## `includeAwardNotices` (type: `boolean`):

SAM.gov also publishes award notices (contracts already awarded). Off by default, because they aren't open opportunities.

## `samNoticeTypes` (type: `array`):

Optional. Keep only these SAM.gov notice types, for example <code>Solicitation</code>, <code>Combined Synopsis/Solicitation</code>, <code>Presolicitation</code>, <code>Sources Sought</code>, <code>Special Notice</code>.

## `grantStatuses` (type: `array`):

Grants.gov opportunity statuses to include: <code>posted</code> and/or <code>forecasted</code>. Default: both.

## `activeOnly` (type: `boolean`):

Skip SAM.gov notices that are marked inactive.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each Grants.gov request. Failed requests are retried up to 3 times with backoff.

## Actor input object example

```json
{
  "opportunityType": "both",
  "postedWithinDays": 7,
  "maxResults": 10,
  "monitorMode": false,
  "emitBaselineOnFirstRun": true,
  "stateStoreName": "us-gov-opportunities-state",
  "includeDescription": true,
  "includeContacts": false,
  "includeAwardNotices": false,
  "grantStatuses": [
    "posted",
    "forecasted"
  ],
  "activeOnly": true,
  "requestTimeoutSecs": 30
}
```

# Actor output Schema

## `opportunities` (type: `string`):

All opportunity rows (contracts and grants) in one schema. Opens on the Overview view.

## `contracts` (type: `string`):

Contract opportunity columns.

## `grants` (type: `string`):

Grant opportunity columns.

## `summary` (type: `string`):

SUMMARY record: filters used, rows per source, rows scanned, SAM.gov extract Last-Modified time and timings.

## `changes` (type: `string`):

Tracking runs: change rows (charged) and status rows (free) for your tracked SAM.gov solicitation numbers.

# 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 = {
    "grantStatuses": [
        "posted",
        "forecasted"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("yourevenings/us-gov-opportunities").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 = { "grantStatuses": [
        "posted",
        "forecasted",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("yourevenings/us-gov-opportunities").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 '{
  "grantStatuses": [
    "posted",
    "forecasted"
  ]
}' |
apify call yourevenings/us-gov-opportunities --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yourevenings/us-gov-opportunities"
        }
    }
}
```

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/oMfUtAt9cIJYgkA5I/builds/5TZuslUabdLz6je26/openapi.json
