# SAM.gov Contract Opportunities Search & Alerts (`openwell-data/federal-contract-opportunity-monitor`) Actor

Filter the public SAM.gov Contract Opportunities extract by NAICS, keywords, set-aside, state and agency. Clean JSON, deduplicated, with new/changed tracking. No API key needed.

- **URL**: https://apify.com/openwell-data/federal-contract-opportunity-monitor.md
- **Developed by:** [Openwell Data](https://apify.com/openwell-data) (community)
- **Categories:** Business, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 results

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

Turn the government's daily bulk file of federal bid opportunities into a clean, filtered, deduplicated feed. Filter by NAICS code, keywords, set-aside, state and agency, then optionally get **only new or changed notices** on every scheduled run.

**No API key, no SAM.gov account and no login needed.** The Actor reads the public Contract Opportunities data extract that the U.S. General Services Administration publishes on SAM.gov and data.gov. It downloads that official bulk file; it does not read or automate SAM.gov web pages.

Use it as a **SAM.gov opportunities API**: search federal contract opportunities (RFPs, solicitations, sources sought, presolicitations) by NAICS code, keyword, set-aside, state and agency, and get JSON, CSV or Excel out.

### Who uses SAM.gov contract opportunity alerts

- Small businesses and consultancies that bid on federal work and want a daily alert feed for their NAICS codes.
- Proposal and business-development teams that want structured data to push into a CRM, spreadsheet, Slack or Airtable.
- Analysts who want a queryable snapshot of what is open right now.

### What you get: SAM.gov opportunity data as JSON, CSV or Excel

One dataset row per matching notice, for example:

```json
{
  "noticeId": "5e1bed195d704dc189d7a231c4a5ab9c",
  "title": "TTS for DTB Pilot - Request for Information",
  "noticeType": "Sources Sought",
  "department": "LIBRARY OF CONGRESS",
  "office": "CONTRACTS SERVICES",
  "postedDate": "2026-09-28T15:34:54",
  "responseDeadline": "2026-10-12T17:00:00-04:00",
  "daysToDeadline": 13,
  "naicsCode": "541511",
  "pscCode": "DA01",
  "setAsideCode": null,
  "placeOfPerformance": { "city": "Washington", "state": "DC", "zip": "20540", "country": "USA" },
  "matchedKeywords": ["software", "data"],
  "changeStatus": "new",
  "samUrl": "https://sam.gov/workspace/contract/opp/5e1bed195d704dc189d7a231c4a5ab9c/view"
}
```

Other fields: solicitation number, sub-tier agency, archive date, set-aside description, a trimmed description, the additional-info link and, for award notices, the award number, date and amount. The awardee name is deliberately not included (it can be an individual). See `docs/sample_output.json`.

### How to search SAM.gov opportunities by NAICS code and keyword

1. Enter NAICS codes (prefix match, so `5415` covers all 5415xx), and/or keywords, set-aside codes, states or agencies. All filters are combined with AND; the values inside one filter are OR (keywords can be switched to "all").
2. Set **Maximum results**. This is your cost cap: results are newest first and you pay per delivered notice.
3. For a daily alert feed, give the run a **watchlist name**, tick **Only new or changed notices**, and put the Actor on a daily Schedule. The Actor remembers what it already delivered under that name (in a key-value store in your account) and marks each row `new` or `updated`.
4. Send results anywhere with Apify integrations, webhooks or the API (see "Use with AI agents and the API" below).

### Get federal RFP and bid alerts every day

To turn this into a federal bid alert service: save a task with your NAICS codes, tick **Only new or changed notices**, give it a watchlist name, and add a daily Schedule (the government file refreshes once a day, so daily is the useful frequency). Connect the run to email, Slack, Google Sheets, Airtable or a webhook, and each morning you receive only what is new or changed since the previous run. You can keep several watchlists (one per NAICS code group, client or region), each remembering its own history.

### Pricing (pay per event)

You pay only for what is delivered. Proposed launch prices:

| Event | Price | When |
|---|---|---|
| Actor start | $0.0001 | Each run (covers downloading and scanning the ~230 MB daily file) |
| Result delivered | $0.005 | Each notice added to your dataset, whether new or an update to a notice you already received under the same watchlist name |

**What $0.005 buys:** one complete, deduplicated SAM.gov notice with about 24 structured fields (NAICS, PSC, set-aside, response deadline and days left, place of performance, matched keywords, direct SAM.gov link), with contact details stripped. Nothing else is billed for the notice, and there are no subscription or seat fees.

Examples: a daily watchlist that finds 5 new or updated notices costs about $0.0251 per day ($0.0001 + 5 x $0.005). A one-off pull of 100 notices costs $0.5001. There is no charge for notices that do not match, and **Maximum results** plus the run's own maximum-cost setting stop spending at the limit.

### Use with AI agents and the API

Every run is a plain Apify Actor, so anything that can call the Apify API can use it.

- **REST API.** Start a run and get the results in one call (replace `YOUR_TOKEN` with your Apify API token):

```bash
curl -X POST "https://api.apify.com/v2/acts/federal-contract-opportunity-monitor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"naicsCodes":["5415"],"keywords":["cybersecurity"],"placeOfPerformanceStates":["VA"],"maxResults":20}'
```

(Use the Actor's full `username~actor-name` ID from its API tab if the short name does not resolve.) The same input works with the Apify JavaScript and Python clients.

- **MCP (Model Context Protocol).** Apify's MCP server (`https://mcp.apify.com`) exposes any Store Actor as a tool, so Claude, ChatGPT-style agents, Cursor and other MCP clients can search federal contract opportunities in plain language. Add this Actor to the server's tool list (for example with the `actors` URL parameter, `https://mcp.apify.com?actors=USERNAME/federal-contract-opportunity-monitor`) and give the agent your Apify token. The input schema doubles as the tool description, and **Maximum results** keeps an agent's spend bounded.
- **Scheduled runs and webhooks.** Create a Schedule in Apify Console (for example daily at 09:00), set a webhook on the run's success event, and post the dataset to your CRM or chat. With a watchlist name each run returns only new or changed notices, which is what an alerting agent wants.
- **Spending control.** Set the run's maximum cost in the run options and **Maximum results** in the input; the Actor stops at whichever limit comes first.

### Frequently asked questions

**Do I need a SAM.gov account or API key?** No. The Actor uses the public bulk data extract, so it needs no login and no key.

**How fresh is the data?** The government file is regenerated once a day (about 03:30 UTC). A notice posted today usually appears in tomorrow's run.

**Can I get only new opportunities?** Yes. Give the run a watchlist name and tick **Only new or changed notices**; each row is marked `new` or `updated`.

**Which notice types are covered?** By default: solicitations, combined synopsis/solicitations, presolicitations, sources sought and special notices. Other types, such as award notices, can be added with the **noticeTypes** input.

**Can I filter by NAICS code?** Yes, with prefix matching (`5415` covers every 5415xx code). You can combine it with keywords, set-aside, state and agency.

**Are contracting officer names, emails or phone numbers included?** No. They are deliberately left out, and emails or phone numbers inside description text are removed. Open the `samUrl` for the official contact.

**Does it include attachments or the full historical archive?** No. Attachments are not included (use `samUrl`), and the extract holds active notices only.

**How much does it cost?** $0.0001 per run plus $0.005 per delivered notice. You control the maximum with **Maximum results** and the run's maximum cost.

**Can I export to CSV or Excel?** Yes. Any Apify dataset can be downloaded as JSON, CSV, Excel, XML or HTML from the run's Output tab or the API.

**Is this official?** No. It is an independent tool and is not affiliated with SAM.gov or the U.S. government.

### Important limitations (please read)

- **Not real time.** The government file is regenerated once a day (roughly 03:30 UTC). A notice posted this afternoon appears tomorrow.
- **Active notices only.** The file holds notices that are still active on SAM.gov, not the full historical archive. Use USAspending.gov data for historical awards.
- **Latest version only.** You see each notice as currently published. Attachments (the solicitation PDFs) are not included; open the `samUrl` for those.
- **No contact details.** The source file includes contracting officers' names, emails and phone numbers. This Actor deliberately does not output them, and it also removes any email address or phone number that appears inside a notice's free-text description. Follow `samUrl` to see the official point of contact.
- **Place of performance is often blank** in the source. Filtering by state excludes notices that do not state one.
- **Descriptions are trimmed** (default 600 characters, configurable). Keyword matching uses the full text.
- Dates come from SAM.gov as published (posted date has no time zone; the deadline usually carries its own offset).
- This is a convenience feed, not legal or procurement advice. Always confirm details and deadlines on SAM.gov before you bid.

### Data source and attribution

Data: "Contract Opportunities from SAM.gov", published by the U.S. General Services Administration (Federal Acquisition Service) via SAM.gov Data Services and Data.gov. U.S. government data with no access restrictions stated in the dataset metadata. This Actor is an independent tool and is **not affiliated with, endorsed by or operated by SAM.gov or the U.S. government.**

### Privacy and terms

No personal data is collected, stored or output beyond the public business information listed above. The Actor sends no data to third parties, uses no AI or LLM at run time, and makes one download request to the government file per run.

### Support

Issues and feature requests go through the Actor's Issues tab. Contact: claudefarmceo@gmail.com. Support is AI-assisted, on behalf of the publisher.

### Technical notes

Node.js 22, Apify SDK 3, streaming CSV parsing (memory stays low). Runs in about 40 seconds on 512 MB.
Set the `CONTACT_EMAIL` environment variable (publisher contact, used only in the download User-Agent; optional). Run locally: `npm install`, then put your input in `storage/key_value_stores/default/INPUT.json` and run `npm start` (or `apify run`). Tests: `npm test`.

# Actor input Schema

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

Match notices whose title or description contains any of these words or phrases (case-insensitive). Leave empty to skip keyword filtering.

## `keywordMode` (type: `string`):

'any' = at least one keyword must match. 'all' = every keyword must match.

## `excludeKeywords` (type: `array`):

Drop notices containing any of these words or phrases.

## `searchDescription` (type: `boolean`):

If off, keywords are matched against the title only.

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

2 to 6 digits. '5415' matches every 5415xx code.

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

For example 'D3' (IT services) or 'R408'.

## `setAsideCodes` (type: `array`):

SAM.gov set-aside codes, for example SBA, 8A, 8AN, SDVOSBC, SDVOSBS, WOSB, EDWOSB, HZC, HZS, IEE, ISBEE, VSA.

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

Two-letter US state codes. Notices with no place of performance stated are excluded when this is set.

## `departments` (type: `array`):

Case-insensitive text matched against department, sub-tier and office, for example 'ARMY' or 'VETERANS AFFAIRS'.

## `noticeTypes` (type: `array`):

Empty = Solicitation, Combined Synopsis/Solicitation, Presolicitation, Sources Sought and Special Notice. Add 'Award Notice' to see who won contracts.

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

0 = no limit (the extract holds only notices still active on SAM.gov).

## `onlyOpenForResponse` (type: `boolean`):

Drops notices whose stated response deadline is in the past. Notices with no deadline are kept.

## `minDaysToDeadline` (type: `integer`):

Optional. Notices with no stated deadline are excluded when this is set.

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

Newest first. You are charged per delivered notice, so this caps the cost of a run.

## `descriptionMaxChars` (type: `integer`):

Characters of the description to return (0 = none). Matching always uses the full text.

## `watchlistName` (type: `string`):

Lowercase letters, digits and dashes. If set, the actor remembers which notices it has already delivered under this name and marks each result as new or updated.

## `onlyNewOrChanged` (type: `boolean`):

Requires a watchlist name. Use with a daily schedule to get an alert feed instead of repeats.

## `sourceUrl` (type: `string`):

Leave empty. Override only for testing.

## Actor input object example

```json
{
  "keywordMode": "any",
  "searchDescription": true,
  "naicsCodes": [
    "5415"
  ],
  "postedWithinDays": 14,
  "onlyOpenForResponse": true,
  "maxResults": 20,
  "descriptionMaxChars": 600,
  "onlyNewOrChanged": false
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items, one per delivered result

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

Counts, source date and cost-relevant details for this run

# 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 = {
    "naicsCodes": [
        "5415"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("openwell-data/federal-contract-opportunity-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 = {
    "naicsCodes": ["5415"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("openwell-data/federal-contract-opportunity-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 '{
  "naicsCodes": [
    "5415"
  ],
  "maxResults": 20
}' |
apify call openwell-data/federal-contract-opportunity-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,openwell-data/federal-contract-opportunity-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/BH43GTf7hJuwZ1Nor/builds/oReyR9aUSRVCEcMtw/openapi.json
