# SAM.gov Contract Opportunities Scraper - Federal Bids (`cleandatalabs/samgov-opportunities`) Actor

SAM.gov API alternative: federal contract opportunities by NAICS, PSC, set-aside, agency, state and deadline, with contacts and bid documents. No API key, no 10 requests/day limit, ~$3 per 1,000. Monitor mode returns only new or changed notices.

- **URL**: https://apify.com/cleandatalabs/samgov-opportunities.md
- **Developed by:** [Clean Data Labs](https://apify.com/cleandatalabs) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 opportunities

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 API Alternative and Scraper: Federal Contract Opportunities by NAICS, Set-Aside and Agency

**Get US federal contract opportunities from [SAM.gov](https://sam.gov) as clean JSON, CSV or Excel: no SAM.gov API key, no 10-requests-a-day cap, about $3 per 1,000 results.** Filter government bids by NAICS, PSC, set-aside (small business, 8(a), HUBZone, SDVOSB, WOSB), agency, state and response deadline, or run it on a schedule in **monitor mode** to get only **new or changed** notices (amendments, deadline changes, cancellations, awards). Every row includes the contracting-officer contact, a `days_until_deadline` countdown and links to the bid documents.

No SAM.gov account, no start fee, no subscription. Failed rows are never charged.

*Built and maintained by **[Clean Data Labs](https://apify.com/cleandatalabs)**.*

### Ready-made examples (one click to run)

| Example | What it finds |
|---|---|
| [IT services bids, small business](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-it-services-small-business) | NAICS 541511/541512 with a Total Small Business set-aside |
| [Construction bids (NAICS 236, 238)](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-construction-bids-236-238) | Open building and specialty-trade solicitations |
| [Janitorial contracts (NAICS 561720)](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-janitorial-contracts-561720) | Custodial and cleaning work |
| [Engineering services (NAICS 541330)](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-engineering-services-541330) | Federal engineering opportunities |
| [Veterans Affairs opportunities](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-va-opportunities) | Open VA solicitations |
| [New in the last 7 days](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-new-opportunities-last-7-days) | Solicitations posted or updated this week |

### Why teams use it

- **Daily bid alerts without a $500 to $2,500 a year seat.** Schedule a monitor for your NAICS codes, PSCs, agencies and set-asides. Unchanged notices are skipped and never billed, so a quiet day costs almost nothing.
- **Never miss an amendment.** SAM.gov posts each amendment as a new notice. The monitor ties every version back to the original solicitation and tells you what changed: `amended`, `deadline_changed`, `canceled`, `awarded`, `notice_type_changed` or `updated`, with the previous deadline and previous notice ID.
- **Bid-ready rows.** `days_until_deadline`, `primary_contact_name/email/phone`, `attachment_links`, `set_aside_description`: drop them straight into a sheet, CRM or Slack message.
- **Filters SAM.gov's own search makes hard:** NAICS and PSC prefixes, agency by plain name (`Department of Veterans Affairs`, `DHS`, `NAVFAC`), a response-deadline window, place-of-performance state, set-asides including "no set-aside", and strict keyword matching.
- **Fair billing.** One flat price per saved notice, including details, contacts and attachment links. Rows whose details SAM.gov failed to return are saved with an `error` field and **free**; empty rows are never saved.

### Who it's for

- **Small businesses and GovCon firms** watching for solicitations they can bid on.
- **Capture and business development teams** that need a daily change feed in their NAICS codes.
- **Proposal consultants** building lead lists and deadline calendars for clients.
- **Analysts** tracking federal demand by agency, NAICS, PSC or region.
- **AI agents and automations** that need clean, typed federal-opportunity data (see [For AI agents](#for-ai-agents)).

### Quick start

**1. Search** (one-off): open small-business construction work in the Southwest.

```json
{
  "naicsCodes": ["236220", "238210"],
  "setAsides": ["SBA", "SDVOSB", "8(a)", "HUBZone"],
  "states": ["CO", "UT", "AZ", "NM", "TX"],
  "updatedWithinDays": 30,
  "openForResponseOnly": true,
  "maxResults": 20
}
```

**2. Monitor** (scheduled): new or changed IT notices from the VA and DHS that are due in the next 60 days.

```json
{
  "monitorMode": true,
  "monitorId": "it-va-dhs",
  "naicsCodes": ["5415"],
  "pscCodes": ["DA", "R4"],
  "agencies": ["Department of Veterans Affairs", "DHS"],
  "deadlineWithinDays": 60,
  "updatedWithinDays": 7,
  "maxResults": 1000
}
```

The first monitor run returns current matches from the lookback window (or nothing, if you set `"monitorFirstRun": "baseline"`). Every later run returns only notices that are new or changed since the previous run.

### Monitor mode: alerts, scheduling and webhooks

#### How it works

1. Each monitor keeps its memory in a **named key-value store, `samgov-monitor-state`**, in your own Apify account: one record per `monitorId` (`STATE-<monitorId>`). Named stores do not expire.
2. Each run asks SAM.gov for everything modified since the previous run (with a 2-hour overlap, so nothing slips through), oldest first.
3. Notices whose version, modified date, deadline, type and status are unchanged are skipped **before** any detail request and are never saved or charged.
4. Everything else is compared field by field with what the monitor last saw and labeled:

| `change_type` | Meaning |
|---|---|
| `new` | First time this solicitation family is seen |
| `amended` | A new version (amendment) of a notice you already saw |
| `deadline_changed` | The response deadline moved (`previous_response_deadline` shows the old one) |
| `canceled` | The notice was canceled |
| `awarded` | The notice became an award notice |
| `notice_type_changed` | e.g. Sources Sought became a Solicitation |
| `updated` | Same version, but title, set-aside, attachments or awardee changed |

`changed_fields` lists exactly what differs (`notice_version`, `response_deadline`, `set_aside`, `attachments`, ...), and `previous_notice_id`, `previous_notice_type_code` and `first_seen_at` give you the history.

If a run is cut short (by `maxResults`, a cost limit or a SAM.gov outage), the next run continues where it stopped, and notices whose details failed are re-checked. `RUN_SUMMARY.caught_up` tells you whether the monitor is up to date.

Leave `monitorId` empty and an ID is derived from your filters, so changing a filter starts a fresh monitor. Set `resetMonitor: true` to start over.

#### Schedule it

1. In Apify Console open **Schedules → Create new**, pick a cron such as `0 13 * * 1-5` (weekdays 13:00 UTC) or `0 */4 * * *` (every 4 hours).
2. Add this actor with your monitor input. Keep the same `monitorId` in every scheduled run.

#### Get notified: webhook or integration

On the actor's **Integrations** tab you can connect **Slack, email, Google Sheets, Zapier, Make or n8n**, or add an **HTTP webhook** for the event **Run succeeded**. A useful payload template:

```json
{
  "runId": {{resource.id}},
  "status": {{resource.status}},
  "datasetId": {{resource.defaultDatasetId}},
  "keyValueStoreId": {{resource.defaultKeyValueStoreId}},
  "chargedEventCounts": {{resource.chargedEventCounts}}
}
```

- `chargedEventCounts.opportunity` is the number of new or changed notices saved (0 means nothing changed).
- Fetch the rows with `GET https://api.apify.com/v2/datasets/<datasetId>/items?view=monitor` (or without `view` for every field).
- Fetch `GET https://api.apify.com/v2/key-value-stores/<keyValueStoreId>/records/RUN_SUMMARY` for counts per `change_type`, `has_changes`, `caught_up` and `next_check_from`.
- The run's status message also reads like an alert, e.g. `Monitor: 2 amended, 1 deadline_changed, 5 new (230 scanned, 222 unchanged)`.

### Input

| Input | What it does |
|---|---|
| `keywords` | Free text, same as the SAM.gov search box |
| `keywordMatch` | `sam` (default, SAM.gov's broad relevance search) or `all`: every word and every `"quoted phrase"` must appear in the title, description or solicitation number |
| `naicsCodes` | Exact or prefix: `541512`, `5415` (all 5415xx), `23` (all construction) |
| `pscCodes` | Product Service Codes, exact or prefix: `DA01`, `R4`, `Z2` |
| `agencies` | Department or agency names, acronyms or SAM.gov organization IDs: `Department of Veterans Affairs`, `DHS`, `Air Force`, `GSA`, `100006688`. Sub-commands like `NAVFAC` are matched against the office hierarchy |
| `noticeTypes` | Solicitation, Combined Synopsis/Solicitation, Presolicitation, Sources Sought, Special Notice, Award Notice and more |
| `setAsides` | `SBA`, `SBP`, `8A`, `8AN`, `HZC`, `SDVOSBC`, `WOSB`, `EDWOSB`, `VSA`, `ISBEE`, `IEE`, `LAS`, `NONE`; friendly names like `SDVOSB`, `HUBZone`, `8(a)` also work |
| `states` | Place-of-performance states, e.g. `CO`, `TX` |
| `updatedWithinDays` | Lookback: posted or modified in the last N days (default 7; 0 = no limit). In monitor mode, the first run's lookback |
| `deadlineWithinDays` | Response due between now and N days from now |
| `deadlineFrom` / `deadlineTo` | Response deadline window, `YYYY-MM-DD` |
| `openForResponseOnly` | Skip notices whose response deadline has passed |
| `activeOnly` | Skip archived or inactive notices (default true) |
| `monitorMode` | Return only new or changed notices since the previous run (default false) |
| `monitorId` | Name of the monitor's memory, e.g. `cyber-va-daily` |
| `monitorFirstRun` | `emit` (default) returns current matches on the first run; `baseline` only remembers them, free |
| `resetMonitor` | Forget this monitor's memory and start over |
| `includeDetails` / `includeContacts` / `includeAttachments` | Full record, points of contact and bid-document links (default on) |
| `maxResults` | Maximum notices to save; you are charged per saved notice (default 100) |

Every input from earlier versions works unchanged and returns the same fields; the new fields are additions.

### Output fields

| Field | Description |
|---|---|
| `notice_id` / `solicitation_number` | SAM.gov notice ID and solicitation number |
| `original_notice_id` | ID of the first version of this solicitation (amendments share it) |
| `title` | Opportunity title |
| `notice_type` / `notice_type_code` | e.g. Solicitation (`o`), Sources Sought (`r`) |
| `department` / `agency` / `office` | Buying organization |
| `office_city` / `office_state` | Contracting office location |
| `posted_date` / `modified_date` | When this version was posted and last changed |
| `response_deadline` / `response_timezone` | When responses are due |
| `days_until_deadline` | Whole days left until the deadline (negative once passed, null if none) |
| `is_active` / `is_canceled` | Notice status |
| `naics` / `psc_code` | NAICS codes and product/service code |
| `set_aside` / `set_aside_description` | e.g. `SBA` / Total Small Business Set-Aside (FAR 19.5) |
| `pop_city` / `pop_state` / `pop_zip` / `pop_country` | Place of performance |
| `award_amount` / `award_date` / `awardee_name` / `awardee_uei` | Award details, when published |
| `description` | Notice description (up to 5,000 characters) |
| `contacts` | Points of contact: `type`, `name`, `title`, `email`, `phone` |
| `primary_contact_name/title/email/phone`, `secondary_contact_*` | The same contacts as flat columns |
| `attachments` | Bid documents and links: `name`, `type`, `url`, `size_bytes`, `posted_date`, `access` |
| `attachment_links` / `attachment_count` | Direct download URLs and how many there are |
| `change_type` / `changed_fields` | Monitor mode only: what changed (see above) |
| `previous_response_deadline` / `previous_notice_type_code` / `previous_notice_id` / `first_seen_at` | Monitor mode only: the state before this change |
| `error` | Only on rows SAM.gov failed to return in full; those rows are free |
| `url` | Link to the notice on SAM.gov |
| `scraped_at` | When the row was collected (UTC) |

Dataset views: **Overview**, **Monitor changes**, **Contacts** and **Attachments**. Attachment download URLs redirect to a short-lived file link on SAM.gov.

### Sample output

**Search row**, from a live run on November 3, 2026 (`description` shortened, `contacts` list and extra attachments omitted for display):

```json
{
  "notice_id": "fa88edcad10d4663952477e2761cb534",
  "title": "Install Generator- FCI Bastrop",
  "solicitation_number": "15BBNF27Q50100001",
  "notice_type": "Combined Synopsis/Solicitation",
  "notice_type_code": "k",
  "department": "JUSTICE, DEPARTMENT OF",
  "agency": "FEDERAL PRISON SYSTEM / BUREAU OF PRISONS",
  "office": "FAO",
  "office_city": "GRAND PRAIRIE",
  "office_state": "TX",
  "posted_date": "2026-11-02T20:29:10+00:00",
  "modified_date": "2026-11-02T20:29:10+00:00",
  "response_deadline": "2026-12-02T11:00:00-08:00",
  "response_timezone": "America/Los_Angeles",
  "days_until_deadline": 28,
  "is_active": true,
  "is_canceled": false,
  "description": "Amendment 0001- Correct Set Aside error in the Instruction to Offerors\n\nSolicitation \n\nThe Federal Bureau of Prisons (FBOP) is issuing solicitation …",
  "original_notice_id": "4050e6eff13e474fbafda0642129140e",
  "url": "https://sam.gov/opp/fa88edcad10d4663952477e2761cb534/view",
  "naics": ["238210"],
  "psc_code": "Z2FF",
  "set_aside": "SBA",
  "set_aside_description": "Total Small Business Set-Aside (FAR 19.5)",
  "pop_city": "Bastrop",
  "pop_state": "TX",
  "pop_zip": "78602",
  "pop_country": "USA",
  "primary_contact_name": "Patrick Ford",
  "primary_contact_email": "pford@bop.gov",
  "primary_contact_phone": null,
  "attachments": [
    {
      "name": "Instructions to Offerors.pdf",
      "type": "file",
      "url": "https://sam.gov/api/prod/opps/v3/opportunities/resources/files/aaec49922277423da58924cdf2ee4c16/download",
      "size_bytes": 1142350,
      "posted_date": "2026-10-23T18:19:07.399+00:00",
      "access": "public"
    }
  ],
  "attachment_count": 8,
  "scraped_at": "2026-11-03T23:41:23.044310+00:00"
}
```

**Monitor row**: a real amendment (Amendment 4 to a Department of Energy RFP, posted November 3, 2026) as reported by a monitor that had last seen Amendment 3. Shortened for display:

```json
{
  "notice_id": "585a560fb4b84fa690b1d5281ce51779",
  "title": "Building America Subject Matter Expert Technical Support",
  "solicitation_number": "RFP-2026-10245()",
  "notice_type": "Solicitation",
  "agency": "ENERGY, DEPARTMENT OF",
  "response_deadline": "2026-11-16T18:00:00-07:00",
  "days_until_deadline": 13,
  "original_notice_id": "1f4fdf5909e44f5ba721860b49a509b4",
  "naics": ["541715"],
  "psc_code": "AG41",
  "pop_state": "CO",
  "primary_contact_email": "Kim.Tangler@nlr.gov",
  "attachment_count": 7,
  "change_type": "amended",
  "changed_fields": ["notice_version"],
  "previous_response_deadline": "2026-11-16T18:00:00-07:00",
  "previous_notice_type_code": "o",
  "previous_notice_id": "3085955966cb496f803ed0b0e1fcef1e",
  "url": "https://sam.gov/opp/585a560fb4b84fa690b1d5281ce51779/view"
}
```

### How it compares

Facts below were checked on November 3, 2026 on each product's public pricing page or Apify Store listing. Prices change, so check the linked pages before you decide.

#### vs. GovCon platforms and the official API

| | **This actor** | [HigherGov](https://www.highergov.com/pricing/) | [GovTribe](https://govtribe.com/plans) | [SAM.gov official API](https://open.gsa.gov/api/get-opportunities-public-api/) |
|---|---|---|---|---|
| Price | $3.00 per 1,000 notices (down to $2.40), no start fee, no subscription | Starter $500/year (1 user); Standard $2,500/year (up to 10 users) | $1,900 per seat/year (Pro $2,100) | Free |
| Federal opportunities | Yes | Yes | Yes | Yes |
| Saved searches / alerts | Monitor mode with typed `change_type` | Unlimited searches, alerts and pipelines | Unlimited saved searches and pursuits | Build it yourself |
| Export limits | Every row lands in an Apify dataset (CSV, Excel, JSON, API) | 1,000 records per search on Starter (20,000 and 100,000 on higher tiers) | Up to 3,000 records per export (25,000 on Enterprise) | Paged API |
| Access | Apify API, webhooks, Zapier, Make, n8n, MCP | API access, Zapier | Zapier, Unanet, AI/MCP | Needs a personal API key; 10 requests/day for a non-federal user with no SAM.gov role |
| Beyond federal opportunities | No | Forecasts, state and local, vendor and people database, AI tools, labor pricing | State and local, contact search, AI credits | Separate APIs |

HigherGov and GovTribe are full GovCon platforms; if you need forecasts, award analytics or pipeline management, they do far more. This actor is the "lite" option: the federal opportunity feed, alerts and contacts, billed per notice.

#### vs. other SAM.gov actors on Apify

| Actor | Price (Free plan) | Start fee | Monitor (new or changed) | Notes from the listing |
|---|---|---|---|---|
| **This actor** | $0.003/notice | None | Yes: typed `change_type`, previous deadline, amendment tracking | Agency by name, PSC/NAICS prefixes, deadline window, strict keywords, flat contacts, attachment links, failed rows free |
| [fortuitous_pirate/sam-gov-scraper](https://apify.com/fortuitous_pirate/sam-gov-scraper) | $0.003/result | $0.005 per run | Yes (new or updated; webhook URL) | PSC, agency, posted and due dates, attachment URLs and downloads |
| [scrapesage/sam-gov-scraper](https://apify.com/scrapesage/sam-gov-scraper) | $0.0025/opportunity (to $0.00138 on Gold+) | $0.001 per run | No built-in monitor | Attachment downloads $0.002 each |
| [jungle_synthesizer/samgov-scraper](https://apify.com/jungle_synthesizer/samgov-scraper) | $0.001/record | Not listed | No | 518 of 847 runs failed in the last 30 days |
| [automation-lab/samgov-government-contracts-scraper](https://apify.com/automation-lab/samgov-government-contracts-scraper) | $0.000115/item | $0.005 per run | No | Filters: notice type, set-aside, NAICS, PSC |
| [parseforge/us-gov-contract-watch-scraper](https://apify.com/parseforge/us-gov-contract-watch-scraper) | $0.0135/result; attachments $0.005 | Not listed | Yes (new or changed) | Also covers CanadaBuys and UK Contracts Finder |

### For AI agents

This actor is built to be called by LLM agents and automations.

- **MCP:** add it to any MCP client through Apify's MCP server: `https://mcp.apify.com?tools=cleandatalabs/samgov-opportunities` (sign in with OAuth or an `Authorization: Bearer <APIFY_TOKEN>` header).
- **One HTTP call:** `POST https://api.apify.com/v2/acts/cleandatalabs~samgov-opportunities/run-sync-get-dataset-items?token=<APIFY_TOKEN>` with the input JSON as the body returns the rows directly (keep `maxResults` modest so it finishes within the sync timeout).
- **Typed, stable output:** snake_case fields, ISO-8601 dates with offsets, `null` for missing values, lists for `naics`, `contacts`, `attachments` and `attachment_links`. `days_until_deadline` is an integer, so "due in the next 10 days" is a simple filter.
- **Mapping user requests to input:**
  - "IT bids for small businesses due this month": `{"naicsCodes": ["5415"], "setAsides": ["SBA"], "deadlineWithinDays": 30}`
  - "What did the VA post or change since yesterday?": `{"agencies": ["Department of Veterans Affairs"], "monitorMode": true, "monitorId": "va"}`
  - "Zero-trust work at DHS": `{"keywords": "\"zero trust\"", "keywordMatch": "all", "agencies": ["DHS"]}`
- **Cheap polling:** in monitor mode an agent can poll often; unchanged notices cost nothing, and `RUN_SUMMARY.has_changes` says whether anything happened.
- **Grounding:** every row has a `url` to the official SAM.gov notice, and `attachment_links` point to the official documents.

### Pricing

**Pay per notice saved**, including details, contacts and attachment links. No start fee.

| Apify plan | Price per notice | Per 1,000 notices |
|---|---|---|
| Free | $0.003 | $3.00 |
| Bronze | $0.0028 | $2.80 |
| Silver | $0.0026 | $2.60 |
| Gold and above | $0.0024 | $2.40 |

Not charged: unchanged notices skipped by a monitor, baseline runs, notices removed by filters, and rows with an `error` field.

#### Free credit

Apify's free plan includes **$5 of usage credit every month**, no credit card required. At the Free-plan price that covers up to about 1,600 notices a month, plenty for a daily monitor on a few NAICS codes.

### FAQ and troubleshooting

#### Why did I get zero results?

Your filters may be too narrow. Widen `updatedWithinDays` (or set it to 0), remove `states`, `setAsides` or `agencies`, or turn off `openForResponseOnly`. In monitor mode, zero rows simply means nothing changed.

#### My keyword search returns unrelated notices.

SAM.gov's keyword search is broad: a multi-word query matches notices containing any of the words, and it also searches long descriptions. Set `keywordMatch: "all"` and quote phrases (`"zero trust"`) for precise results.

#### How do I filter by agency?

Use the department or agency name, its acronym or its SAM.gov organization ID. The log shows what each name resolved to. Names that are not a department or agency (for example `NAVFAC`) are matched against the full office hierarchy, which scans more notices but is still accurate.

#### Do set-aside and state filters work with `includeDetails` off?

`NONE` set-aside and state filters rely on full notice details, so the actor switches `includeDetails` on automatically when you use them.

#### Why are award fields empty?

Award amount, date and awardee are filled only on award notices that publish them.

#### Is there a limit per run?

SAM.gov's search returns at most 10,000 notices per query. Monitor mode walks past this automatically; for one-off searches, narrow your filters.

#### Do I need a SAM.gov account or API key?

No. All data is public US Government information from SAM.gov. You only need an Apify account; the free plan includes $5 of credit a month.

#### Is this a replacement for the official SAM.gov API?

For reading contract opportunities, yes. The [official Get Opportunities API](https://open.gsa.gov/api/get-opportunities-public-api/) is free, but it needs a personal API key and allows 10 requests a day for a non-federal user with no SAM.gov role. If you have a higher-limit key and want to build your own pipeline, the official API is a good choice; this actor saves you the key management, paging, filtering and contact flattening.

#### How do I find small-business set-aside bids for my NAICS code?

Put your codes in `naicsCodes` (prefixes like `5415` work) and add `SBA`, `8A`, `HZC`, `SDVOSBC` or `WOSB` to `setAsides`. See the [IT services example](https://apify.com/cleandatalabs/samgov-opportunities/examples/samgov-it-services-small-business).

#### Can I get results into Google Sheets, Excel or my CRM?

Yes. Export the dataset as CSV, Excel or JSON, or use Apify integrations (Google Sheets, Zapier, Make, n8n) or the API.

### More from Clean Data Labs

- [Prediction Markets Odds API](https://apify.com/cleandatalabs/prediction-markets-odds): live Kalshi and Polymarket odds, bid/ask and volume in one schema.
- [Substack Scraper](https://apify.com/cleandatalabs/substack-newsletters): Substack posts with engagement metrics, plus top newsletters in any category.
- [All Clean Data Labs actors](https://apify.com/cleandatalabs)

### Support

Questions, bugs or feature requests? Email **<clean-data-labs@mail.grokbot.com>** or open an issue on the actor's Issues tab.

*Clean Data Labs: clean, structured public data, ready to use.*

# Actor input Schema

## `keywords` (type: `string`):

Free-text search, same as the SAM.gov search box (e.g. cybersecurity, janitorial, "fire alarm"). Leave empty to list everything that matches the other filters.

## `keywordMatch` (type: `string`):

SAM.gov's own keyword search is broad: a multi-word query matches notices containing any of the words. Strict keeps only notices whose title, description or solicitation number contains every word (words also match as prefixes, so cyber matches cybersecurity) and every "quoted phrase". Recommended for monitors.

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

NAICS codes, exact or prefix: 541512 matches only that code, 5415 (or 5415\*) matches every 5415xx code, 23 matches all construction.

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

Product Service Codes, exact or prefix: DA01 (IT application development), R4 (all R4xx professional services), Z2 (construction of structures).

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

Department or agency names, acronyms or SAM.gov organization IDs, e.g. Department of Veterans Affairs, DHS, Air Force, GSA, 100006568. Names that are not a department or agency (e.g. NAVFAC, Army Corps of Engineers) are matched against the full office hierarchy.

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

Leave empty for all types.

## `setAsides` (type: `array`):

Keep only these set-asides: SBA (Total Small Business), SBP (Partial SB), 8A, 8AN (8(a) sole source), HZC (HUBZone), SDVOSBC (SDVOSB), WOSB, EDWOSB, VSA (VA veteran-owned), ISBEE, IEE, LAS, or NONE. Friendly names such as SDVOSB, HUBZone or 8(a) also work.

## `states` (type: `array`):

Two-letter place-of-performance state codes, e.g. CO, TX.

## `updatedWithinDays` (type: `integer`):

Only notices posted or modified in the last N days. 0 = no limit. In monitor mode this is the first run's lookback; later runs check everything changed since the previous run.

## `deadlineWithinDays` (type: `integer`):

Only notices whose response deadline is between now and N days from now, e.g. 14. Notices without a deadline are skipped.

## `deadlineFrom` (type: `string`):

Earliest response deadline, as YYYY-MM-DD (UTC).

## `deadlineTo` (type: `string`):

Latest response deadline, as YYYY-MM-DD (UTC, end of day).

## `openForResponseOnly` (type: `boolean`):

Skip notices whose response deadline has already passed (and awards without a deadline).

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

Skip archived/inactive notices.

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

Save only notices that are new or changed since the previous run with the same monitor ID. Adds change_type, changed_fields, previous_response_deadline, previous_notice_type_code, previous_notice_id and first_seen_at.

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

Name for this monitor's memory, e.g. cyber-va-daily. Leave empty to derive it from your filters (changing a filter then starts a fresh monitor). Letters, digits, - and \_ work best.

## `monitorFirstRun` (type: `string`):

What the very first run of a monitor does. Baseline is free and makes the next run return only real changes.

## `resetMonitor` (type: `boolean`):

Forget everything this monitor has seen and start again.

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

Fetch each notice's full record (NAICS, PSC, set-aside, place of performance, contacts, full description). One extra request per notice.

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

Include the official government points of contact, as a contacts list plus flat primary_contact\_\* and secondary_contact\_\* columns.

## `includeAttachments` (type: `boolean`):

List each notice's bid documents and links (name, direct download URL, size, posted date) in attachments and attachment_links. Needs details on.

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

Stop after this many notices. You pay only for complete notices saved; failed rows are free.

## Actor input object example

```json
{
  "keywords": "cybersecurity",
  "keywordMatch": "sam",
  "updatedWithinDays": 7,
  "openForResponseOnly": false,
  "activeOnly": true,
  "monitorMode": false,
  "monitorFirstRun": "emit",
  "resetMonitor": false,
  "includeDetails": true,
  "includeContacts": true,
  "includeAttachments": true,
  "maxResults": 100
}
```

# Actor output Schema

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

One row per SAM.gov federal contract notice: agency, NAICS, set-aside, deadlines, place of performance, contacts and URL.

## `monitorChanges` (type: `string`):

In monitor mode: what changed since the last run, one row per new or changed notice.

## `runSummary` (type: `string`):

Counts, the SAM.gov query used and, in monitor mode, change counts and has_changes.

# 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 = {
    "keywords": "cybersecurity"
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleandatalabs/samgov-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 = { "keywords": "cybersecurity" }

# Run the Actor and wait for it to finish
run = client.actor("cleandatalabs/samgov-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 '{
  "keywords": "cybersecurity"
}' |
apify call cleandatalabs/samgov-opportunities --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cleandatalabs/samgov-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/jZBk5GJVXM1G850zi/builds/QBAjJJdCis5R07lCZ/openapi.json
