# SAM.gov Contract Opportunities Monitor (`orventasystems/samgov-opportunities-monitor`) Actor

Monitor SAM.gov for new federal contract opportunities. Filter by NAICS, set-aside, notice type, keyword, state and deadline. Returns clean, flat records with contacts and attachments, and only NEW notices since your last run.

- **URL**: https://apify.com/orventasystems/samgov-opportunities-monitor.md
- **Developed by:** [Purvin Patel](https://apify.com/orventasystems) (community)
- **Security:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 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.

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 Contract Opportunities Monitor

Get **new federal contract opportunities from SAM.gov** every day, filtered to exactly what your business can bid on, as clean spreadsheet-ready rows with contacts, deadlines and attachment links.

Built on the **official SAM.gov Opportunities API** (with your own free key), so it is reliable, fast and fully within SAM.gov's terms.

### Why use it

- ✅ **Only new notices**: remembers what it already sent you, so a daily schedule gives you just the fresh opportunities. No duplicates.
- 🎯 **Precise filters**: NAICS codes, set-aside types (Small Business, 8(a), HUBZone, SDVOSB, WOSB…), notice types, title keywords, state, and minimum days until the deadline.
- 🧹 **Clean output**: agency split into department / sub-tier / office, primary contact name, email and phone, deadline with **days left**, place of performance, attachments, award details and a direct SAM.gov link.
- 📬 **Plugs into anything**: export to Excel/CSV/JSON, or connect Slack, email, Google Sheets, Zapier or Make with Apify integrations.
- 🛡️ **Clear errors**: tells you if your API key is wrong or your daily SAM.gov limit is reached, instead of silently returning nothing.

### Who it's for

Government contractors, small businesses pursuing set-asides, bid and proposal consultants, BD teams and lead-gen agencies.

### How to get your free SAM.gov API key (about 5 minutes)

The key is **free** and anyone can get one. You don't need to be registered as a government contractor.

**1. Create a SAM.gov account (skip if you have one)**

1. Go to [sam.gov](https://sam.gov) and click **Sign In** (top right).
2. SAM.gov uses **Login.gov** for sign-in. Click **Create an account**, enter your email, confirm it, set a password, and set up two-factor authentication (text message or an authenticator app).
3. You'll be returned to SAM.gov. Accept the terms and finish your basic profile (name, etc.). You do **not** need an entity or UEI registration.

**2. Generate your public API key**

1. While signed in, click your **name or profile icon** (top right) and choose **Account Details**.
2. Scroll to the **Public API Key** section.
3. Click **Request API Key** (or the eye icon to view an existing key). SAM.gov asks you to **re-enter your password**.
4. **Copy the key right away.** SAM.gov only shows it until you leave the page. Save it somewhere safe, like a password manager.

**3. Paste it into this Actor**

- Paste the key into the **SAM.gov public API key** field. Apify stores it **encrypted**, and it never appears in run logs.

**Good to know**

- **Keys expire after about 90 days.** SAM.gov emails you before it expires. Generate a new key on the same Account Details page and paste it into your saved task.
- A brand-new key can take a few minutes to start working.
- If the Actor says your key wasn't accepted, check you copied the whole key without spaces, and that it hasn't expired.

### Example input

```json
{
  "apiKey": "YOUR_SAM_GOV_KEY",
  "postedWithinDays": 3,
  "naicsCodes": ["541511", "541512"],
  "setAsides": ["SBA", "SDVOSBC"],
  "noticeTypes": ["o", "k", "p", "r"],
  "minDaysToDeadline": 7,
  "onlyNew": true
}
```

**Tip:** schedule it **daily** with `postedWithinDays: 3`. The overlap guarantees nothing is missed, and "Only new notices" removes the repeats.

### Example output

```json
{
  "noticeId": "a1b2c3...",
  "title": "IT Help Desk Support Services",
  "solicitationNumber": "47QTCA26R0012",
  "type": "Combined Synopsis/Solicitation",
  "agency": "GENERAL SERVICES ADMINISTRATION / FEDERAL ACQUISITION SERVICE",
  "office": "GSA/FAS CENTER FOR IT SCHEDULE PROG",
  "postedDate": "2026-10-19",
  "responseDeadline": "2026-11-05T14:00:00-05:00",
  "daysToDeadline": 16,
  "setAside": "Total Small Business Set-Aside (FAR 19.5)",
  "setAsideCode": "SBA",
  "naicsCode": "541511",
  "placeOfPerformanceState": "IL",
  "contactName": "Jane Smith",
  "contactEmail": "jane.smith@gsa.gov",
  "contactPhone": "555-555-0100",
  "attachments": ["https://sam.gov/api/prod/opps/v3/opportunities/resources/files/.../download"],
  "samUrl": "https://sam.gov/opp/a1b2c3.../view"
}
```

Also included: `department`, `subTier`, `classificationCode`, all `contacts`, `awardAmount`, `awardeeName`, `awardeeUei`, `descriptionUrl`, and optionally the full `description` text.

### Input reference

| Field | What it does |
|---|---|
| SAM.gov public API key | Required. Your free key from SAM.gov. |
| Posted within the last N days | Date window (1–365). Default 3. |
| NAICS codes | One or more industry codes. Empty = all. |
| Title keywords | Match words in the notice title. |
| Set-aside types | Small Business, 8(a), HUBZone, SDVOSB, WOSB, EDWOSB and more. |
| Notice types | Solicitation, Combined Synopsis/Solicitation, Presolicitation, Sources Sought, Award, etc. Default: the four types you can respond to. |
| Place of performance state | Two-letter code, e.g. `VA`. |
| Minimum days until deadline | Skip notices closing too soon. |
| Only active notices | Skip archived notices (default on). |
| Only new notices | Return only notices not seen in earlier runs with the same filters (default on). |
| Fetch full description text | Adds the full notice text; uses one extra SAM.gov request per notice. |
| Maximum results | Safety cap per run. |

### SAM.gov request limits

SAM.gov limits how many API requests each key can make per day, and **personal (non-federal) keys get a small allowance, often only a few dozen requests a day.** This Actor is built around that limit:

- It fetches **1,000 notices per request**. A typical daily monitor uses **1 request per search**.
- Each NAICS × set-aside × keyword combination is a separate search. 3 NAICS codes × 1 set-aside = 3 requests. Combine codes into fewer searches where you can.
- **Full description text costs 1 extra request per notice.** Leave it off for daily monitoring and open the notice with `samUrl` or `descriptionUrl` instead, or turn it on only for very narrow searches.
- If the daily limit is reached, the run stops cleanly, **keeps everything found so far**, and tells you. Tomorrow's run picks up where it left off, because "Only new" remembers what you've already received.

### FAQ

**Does it scrape the SAM.gov website?** No. It uses the official public API with your key.

**Will amendments show up?** SAM.gov gives amended notices their own notice ID, so amendments appear as new rows. That's handy for tracking changes.

**Can I run several saved searches?** Yes. Create one Apify task per search. "Only new" memory is kept separately for each distinct set of filters.

**Is this affiliated with SAM.gov or GSA?** No. This is an independent tool that uses the public SAM.gov API.

### Related Actors

- **[US Building Permits Monitor – Contractor Leads](https://apify.com/orventasystems/building-permits-monitor)**: new building permits with contractor details from 9 major US cities.
- **[US Contractor Licenses – Multi-State Leads](https://apify.com/orventasystems/contractor-licenses)**: licensed contractors in 7 states, including the NY public-work Contractor Registry, with newly licensed alerts.

### Support

Found a problem or need a feature (e.g. Slack-ready summaries, agency filters)? Open an issue on the Actor's **Issues** tab. I typically respond within one business day.

# Actor input Schema

## `apiKey` (type: `string`):

Your FREE public API key from SAM.gov. How to get it: 1) Sign in at sam.gov (free Login.gov account; no contractor registration needed). 2) Click your name (top right) → Account Details. 3) In 'Public API Key', click Request API Key / the eye icon and re-enter your password. 4) Copy the key immediately (it's only shown once per visit). Keys expire about every 90 days. Full step-by-step guide in the README. Stored encrypted; never shown in logs.

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

Search notices posted in the last N days (1–365). For a daily schedule, 2–3 days is a safe overlap; duplicates are removed automatically when 'Only new notices' is on.

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

One or more NAICS codes (2–6 digits), e.g. 541511, 236220. Leave empty for all industries.

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

Only notices whose title contains one of these words/phrases (searched by SAM.gov). Leave empty for no keyword filter.

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

Limit to these set-aside types. Leave empty for all (including unrestricted).

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

Limit to these notice types. Leave empty for all.

## `state` (type: `string`):

Two-letter state code, e.g. IL. Leave empty for all states.

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

Skip notices whose response deadline is sooner than this many days away (0 = keep all, including notices without a deadline).

## `onlyActive` (type: `boolean`):

Skip archived/inactive notices.

## `onlyNew` (type: `boolean`):

Remember notices already returned by previous runs with the same filters and output only new ones. Ideal for daily schedules and alerts.

## `fetchDescriptions` (type: `boolean`):

Download the full notice description for each result. Uses one extra SAM.gov API request per notice, which counts against your daily SAM.gov quota.

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

Stop after this many notices are saved.

## Actor input object example

```json
{
  "postedWithinDays": 3,
  "naicsCodes": [],
  "keywords": [],
  "setAsides": [],
  "noticeTypes": [
    "o",
    "k",
    "p",
    "r"
  ],
  "minDaysToDeadline": 0,
  "onlyActive": true,
  "onlyNew": true,
  "fetchDescriptions": false,
  "maxResults": 500
}
```

# Actor output Schema

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

New SAM.gov contract opportunities found by 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 = {};

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

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

```

## MCP server setup

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