# US Federal Tender Monitor (SAM.gov) (`mikee368/us-federal-tender-monitor`) Actor

New US federal contract opportunities from SAM.gov by keyword and NAICS code: only new notices since the last run, award notices excluded, set-asides and an alert digest. Bring your own free SAM.gov API key.

- **URL**: https://apify.com/mikee368/us-federal-tender-monitor.md
- **Developed by:** [Mike Berckmoes](https://apify.com/mikee368) (community)
- **Categories:** Lead generation, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 contract 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

## US Federal Tender Monitor (SAM.gov)

**Get new US federal government contract opportunities from SAM.gov every day, filtered by your keywords and NAICS codes, with only the notices you haven't seen yet.** Built on the official SAM.gov Get Opportunities API. You bring your own free SAM.gov API key.

### What does US Federal Tender Monitor do?

It searches **SAM.gov Contract Opportunities** (the official US federal procurement notices: solicitations, combined synopsis/solicitations, presolicitations, sources sought and special notices) and returns one clean row per notice:

- **Keyword search** in notice titles (English, used as-is), e.g. `software`, `cybersecurity`, `janitorial`.
- **NAICS filter**, e.g. `541511` (custom computer programming) or `541512` (computer systems design).
- **Only new notices since the last run** per *Monitor ID*, so a daily schedule gives you a clean list of new federal opportunities.
- **Award notices excluded** by default (you want opportunities you can still bid on).
- **Set-asides shown**, e.g. *Total Small Business Set-Aside (FAR 19.5)*, 8(a), HUBZone, SDVOSB, WOSB.
- **Alert digest** with a ready-made e-mail subject/text/HTML, plus an optional webhook (Make, Zapier, n8n, Slack).

### Why use it?

- Federal contractors, small businesses and bid consultants get a daily shortlist without logging in to SAM.gov.
- Quota-aware: a basic SAM.gov key allows about **10 requests per day**. This Actor uses at most 3 requests per run by default (1,000 notices per request), so a daily monitor fits comfortably.
- Structured output for spreadsheets, CRMs and alerts.

### How to use it

1. **Get a free SAM.gov public API key:** create or sign in to your SAM.gov account, open **Account Details**, and request a **Public API Key**.
2. Paste the key into **SAM.gov API key**, add **Keywords** and/or **NAICS codes**, and give the search a **Monitor ID**.
3. Run it once, then schedule it daily (for example weekdays at 08:00 US Eastern). Each run returns only new notices.

**Keys expire.** SAM.gov public API keys must be renewed every **90 days** (SAM.gov terms). When your key expires, the run reports *"SAM.gov refused the API key"* in `RUN_SUMMARY`; create a new key in your SAM.gov Account Details and update it in your input or saved task.

### Input example

```json
{
  "samGovApiKey": "YOUR-SAM-GOV-PUBLIC-API-KEY",
  "keywords": ["software", "cybersecurity"],
  "naicsCodes": [],
  "monitorId": "federal-it",
  "samGovMaxRequests": 3
}
```

- One SAM.gov request per keyword (title search) or per NAICS code. With NAICS codes, your keywords are matched on the title.
- If you list more keywords than *SAM.gov requests per run*, one date-window search is made and titles are matched locally.
- The first run looks back 3 days (*First-run lookback*); later runs continue from the last successful run.

### Output example (one row)

```json
{
  "source": "SAM_GOV",
  "noticeId": "8d72bf38…",
  "title": "Software-as-a-Service (SaaS) Subscriptions and Support",
  "buyerName": "DEPT OF DEFENSE / DEPT OF THE ARMY",
  "buyerCountry": "USA",
  "buyerCity": "…",
  "publicationDate": "2026-09-30",
  "deadline": "2026-10-05T16:00:00-04:00",
  "noticeType": "Sources Sought",
  "naicsCode": "541519",
  "setAside": null,
  "url": "https://sam.gov/workspace/contract/opp/8d72bf38…/view",
  "matchedTerms": ["software"],
  "relevance": 65,
  "isNew": true
}
```

`RUN_SUMMARY` shows the status, SAM.gov requests used, counts and the effective input. `DIGEST` holds the e-mail-ready list of new notices.

### How much does it cost?

Pay per result: **$3 per 1,000 notices** ($0.003 per notice), with no start fee. You pay only for new notices returned, so a run that finds nothing new costs nothing for results. Normal Apify platform usage applies (the Actor runs in 256 MB).

### Good to know / limitations

- **Quota.** Basic SAM.gov keys allow about 10 requests per day. If the quota is used up (HTTP 429), the run keeps what it has and the next run continues from the same date; requests are never retried automatically, so no quota is wasted.
- **Title search.** SAM.gov searches the notice title, not the full description.
- **Very large searches.** If more notices match than your request cap can fetch (more than 1,000 per request), the run is marked `partial` and the next run continues.
- **Links.** `url` is SAM.gov's own link to the notice.
- **Data used.** Only the public **Contract Opportunities API** (Get Opportunities v2) is used. **No Dun & Bradstreet (D\&B) or entity data is output**, and points of contact (names, e-mails) are not collected.

### Data sources and terms

- SAM.gov Get Opportunities Public API v2 (U.S. General Services Administration), used with your own key under the SAM.gov terms of use. Notices created by the U.S. federal government are generally not subject to copyright, but SAM.gov notes that some content may carry third-party restrictions.
- This Actor is not affiliated with GSA or SAM.gov.

### Also tracking European tenders?

Use **[EU Tender Monitor](https://apify.com/mikee368/eu-tender-monitor)**: TED (EU-wide), TenderNed (NL), BOAMP (FR) and Doffin (NO) in one English feed, with optional SAM.gov too.

### FAQ

**Do I need an API key?** Yes, your own free SAM.gov public API key (Account Details on SAM.gov). It must be renewed every 90 days.
**Can I monitor several searches?** Yes. Use a different *Monitor ID* per search (e.g. one per NAICS group); each remembers its own seen notices.
**Does it send e-mails itself?** No. It prepares the digest; your webhook or an Apify integration delivers it.

# Actor input Schema

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

English keywords searched in SAM.gov notice titles, e.g. software, cybersecurity, janitorial. One SAM.gov request per keyword (if you list more keywords than your request cap, one date-window search is made and titles are matched locally).

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

US NAICS codes (2-6 digits, e.g. 541511 = custom computer programming, 541512 = computer systems design). One SAM.gov request per code; your keywords (if any) are then matched on the notice title.

## `samGovApiKey` (type: `string`):

Your own free public API key: sign in at SAM.gov, open Account Details and request a Public API Key. Keys must be renewed every 90 days (SAM.gov terms); update it here when it expires. A basic key allows about 10 requests per day.

## `samGovMaxRequests` (type: `integer`):

Hard cap on SAM.gov API calls per run, to stay within your key's daily quota (basic keys: about 10/day). Each call returns up to 1,000 notices. If the cap stops a run early, the next run continues from the same date.

## `strictMatch` (type: `boolean`):

Keep only notices whose title contains one of your keywords.

## `dateFrom` (type: `string`):

Leave EMPTY for incremental monitoring (recommended): each run starts from the day of the previous successful run of this Monitor ID, and already-seen notices are skipped. The first run looks back 'First-run lookback' days. Set a date (YYYY-MM-DD) only for one-off backfills.

## `firstRunLookbackDays` (type: `integer`):

How many days back the very first run of a Monitor ID searches when 'Published on or after' is empty.

## `maxItemsPerSource` (type: `integer`):

Hard cap per source, which also caps cost.

## `excludeAwards` (type: `boolean`):

Skip award notices (contracts already awarded). Recommended for finding opportunities to bid on.

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

Remember notice IDs between runs (per Monitor ID) and output only notices not seen before. Default on; combine with an empty 'Published on or after' for a clean incremental feed.

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

Name of this monitor. Each monitor ID remembers which SAM.gov notices it has already returned, so scheduled runs give only new ones. Use a different ID per search.

## `resetState` (type: `boolean`):

Forget the seen notices and last-run time of this Monitor ID before running (starts again with the first-run lookback).

## `createDigest` (type: `boolean`):

Store a DIGEST record per run (counts per source, list of new notices, ready-made email subject/text/HTML) in the run's key-value store.

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

If set, the DIGEST JSON is POSTed here at the end of each run that found new notices (e.g. a Make, Zapier, n8n or Slack-workflow webhook that emails or posts it).

## `notifyWhenEmpty` (type: `boolean`):

Also call the webhook when a run finds 0 new notices.

## `digestEmailTo` (type: `string`):

Copied into DIGEST.email.to so your webhook/automation knows where to send it. The Actor itself does not send e-mails.

## Actor input object example

```json
{
  "keywords": [
    "software"
  ],
  "naicsCodes": [],
  "samGovMaxRequests": 3,
  "strictMatch": true,
  "firstRunLookbackDays": 3,
  "maxItemsPerSource": 50,
  "excludeAwards": true,
  "onlyNew": true,
  "monitorId": "default",
  "resetState": false,
  "createDigest": true,
  "notifyWhenEmpty": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset with one row per tender notice

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

Status, SAM.gov requests used, counts and the effective input

## `digest` (type: `string`):

New notices since last run with a ready-made e-mail subject/text/HTML

# 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": [
        "software"
    ],
    "naicsCodes": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("mikee368/us-federal-tender-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 = {
    "keywords": ["software"],
    "naicsCodes": [],
}

# Run the Actor and wait for it to finish
run = client.actor("mikee368/us-federal-tender-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 '{
  "keywords": [
    "software"
  ],
  "naicsCodes": []
}' |
apify call mikee368/us-federal-tender-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mikee368/us-federal-tender-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/m084F5O2MggdUV8NW/builds/N1v93JYUXC6J6fjfX/openapi.json
