# 🇺🇸 SAM.gov Contracts Scraper (`skootle/sam-gov-federal-contracts`) Actor

Scrape SAM.gov for U.S. federal contract opportunities + join with USAspending recent-award history. Set-aside type, agency hierarchy, contacts, attachments, place-of-performance. Watchlist + change-detection modes. Export, run via API, schedule, or integrate with other tools.

- **URL**: https://apify.com/skootle/sam-gov-federal-contracts.md
- **Developed by:** [Skootle](https://apify.com/skootle) (community)
- **Categories:** AI, Lead generation, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 federal contract opportunity records

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

![SAM.gov Federal Contracts hero](https://raw.githubusercontent.com/kesjam/skootle-actors-assets/main/heroes/sam-gov-federal-contracts.png)

### TL;DR

Scrape SAM.gov for active U.S. federal contract opportunities and join each with recent award history from USAspending. Returns clean JSON with deadlines, contacts, attachments, agency hierarchy split out, set-aside type, place-of-performance, and a recent-awards block per opportunity. Direct from official SAM.gov + USAspending APIs (no scraping fragility). Watchlist mode emits only NEW or CHANGED opportunities since the previous run. Built for federal BD pipelines, capture management, AI proposal-drafting agents.

---

<!-- skootle:review-cta -->
> Try it on a small dataset, then let us know what you think in a [review](https://apify.com/skootle/sam-gov-federal-contracts/reviews).

---

### What does SAM.gov + USAspending Federal Contracts Intelligence do?

This actor extracts active federal contract opportunities from SAM.gov and joins each one with recent award history from USAspending.gov. You give it filters (NAICS codes, agencies, set-aside categories, free-text keywords); it returns one well-typed record per opportunity with: notice ID, solicitation number, title, posted/response/closing dates in ISO 8601, full agency hierarchy (department → agency → office), set-aside type, place-of-performance, attachment URLs, contact emails, primary NAICS, plus a `recentAwards` block per opportunity showing who has won similar contracts.

Every record carries `agentMarkdown` (300-500 chars) and `fieldCompletenessScore` (0-100). Every run also writes an `AGENT_BRIEFING.md` ranked by completeness × deadline urgency.

### Why scrape SAM.gov?

SAM.gov is the U.S. federal government's official portal for posting open solicitations. Every federal contract opportunity above the micropurchase threshold flows through SAM.gov. For federal BD teams, capture managers, government contractors, GovCon analysts, and AI-powered proposal-drafting tools, SAM.gov is the canonical opportunity feed.

The official SAM.gov + USAspending APIs are both free, but they're separate systems with different schemas and inconsistent date formats. This actor handles both calls and joins them so you don't run two pipelines.

### Who needs this?

- **Federal BD and capture managers** filtering opportunities by NAICS, set-aside, and agency
- **Government contractors** monitoring small-business set-asides (8(a), HUBZone, SDVOSB, WOSB, EDWOSB)
- **Prime contractors** finding teaming partners on new opportunities
- **GovCon market analysts** measuring opportunity volume by agency, NAICS, set-aside category
- **AI proposal-drafting tools** consuming the SOW + evaluation criteria as structured input
- **Compliance teams** tracking which agencies post what, when
- **Investors and lobbyists** measuring federal spend pipeline by parent agency

### How to use SAM.gov + USAspending Federal Contracts

1. Get a free SAM.gov API key at https://open.gsa.gov/api/get-opportunities-public-api/ (~3 min)
2. Open the **Input** tab on the actor page, paste your key into `samGovApiKey`
3. Set filters: `naicsCodes`, `agencies`, `setAsides`, or free-text `keywords`
4. Set `maxItems` (default 50)
5. Optionally enable `joinUsaspending` (default `true`) for the recent-awards enrichment
6. Optionally enable `detectChanges` for change-detection mode
7. Click **Start**

### How much will scraping SAM.gov cost?

This actor is priced per event:

- **Actor Start**: $0.01 once per run
- **Federal opportunity record**: tiered, charged per record written

| Apify plan | $/1000 records |
|---|---|
| FREE | $35.00 |
| BRONZE | $29.75 |
| SILVER | $24.50 |
| GOLD | $21.00 |
| PLATINUM | $21.00 |
| DIAMOND | $18.90 |

A daily NAICS-filtered watchlist returns ~50-200 records day 1, then 10-50 per day. Roughly $1-$4 per day on GOLD.

### Is it legal to scrape SAM.gov?

Yes — federal contracting opportunities are public-record data published by the U.S. government. Both SAM.gov and USAspending are official .gov APIs explicitly designed for programmatic access. SAM.gov requires a free API key (rate-limit signal, not a content gate). USAspending has no auth requirement.

### Examples

#### Example 1: Daily watchlist on IT services NAICS

```json
{
  "samGovApiKey": "YOUR_KEY",
  "naicsCodes": ["541512", "541511", "541519"],
  "watchlistMode": true,
  "maxItems": 100
}
````

#### Example 2: 8(a) set-aside opportunities only

```json
{
  "samGovApiKey": "YOUR_KEY",
  "setAsides": ["8A"],
  "watchlistMode": true,
  "maxItems": 100
}
```

#### Example 3: DOD opportunities

```json
{
  "samGovApiKey": "YOUR_KEY",
  "agencies": ["DEPT OF DEFENSE"],
  "maxItems": 200
}
```

#### Example 4: Free-text AI keyword search

```json
{
  "samGovApiKey": "YOUR_KEY",
  "keywords": ["artificial intelligence", "machine learning"],
  "maxItems": 100
}
```

#### Example 5: Change-detection mode

```json
{
  "samGovApiKey": "YOUR_KEY",
  "naicsCodes": ["541512"],
  "detectChanges": true,
  "maxItems": 200
}
```

Filter for `changeStatus: 'updated'` to see what shifted overnight.

#### Example 6: HUBZone + SDVOSB combined

```json
{
  "samGovApiKey": "YOUR_KEY",
  "setAsides": ["HZC", "SDVOSBC", "WOSB", "EDWOSB"],
  "maxItems": 200
}
```

#### Example 7: Posted-this-week opportunities

```json
{
  "samGovApiKey": "YOUR_KEY",
  "postedFrom": "2026-05-02",
  "postedTo": "2026-05-09",
  "maxItems": 500
}
```

#### Example 8: Capture-team intelligence

```json
{
  "samGovApiKey": "YOUR_KEY",
  "naicsCodes": ["541512"],
  "joinUsaspending": true,
  "usaspendingLookbackMonths": 24,
  "maxItems": 50
}
```

The `recentAwards` block per opportunity gives you "who has won similar work" without a second pipeline.

### Input parameters

| Field | Type | Default | Description |
|---|---|---|---|
| `samGovApiKey` | string | required | Free key from https://open.gsa.gov/api/get-opportunities-public-api/ |
| `naicsCodes` | string\[] | `[]` | NAICS code filter |
| `agencies` | string\[] | `[]` | Agency name filter |
| `setAsides` | enum\[] | `[]` | `8A`, `HZC`, `SDVOSBC`, `WOSB`, `EDWOSB`, `IEE` |
| `keywords` | string\[] | `[]` | Free-text search |
| `postedFrom`, `postedTo` | YYYY-MM-DD | `null` | Posted-date window |
| `joinUsaspending` | bool | `true` | Add `recentAwards` enrichment |
| `usaspendingLookbackMonths` | int | `24` | How far back lookups go |
| `detectChanges` | bool | `false` | Add `changeStatus` + `changedFields[]` |
| `watchlistMode` | bool | `false` | Idempotent diff |
| `maxItems` | int | `50` | Hard cap |

### Federal Contracts output format

#### `federal_opportunity`

| Field | Type | Description |
|---|---|---|
| `outputSchemaVersion`, `recordType`, `recordId` | string | Discriminated identity (`samgov:opp:<noticeId>`) |
| `noticeId`, `solicitationNumber`, `url` | string | SAM.gov IDs + URL |
| `title`, `description` | string | Title + full SOW |
| `noticeType` | enum | `Solicitation`, `Combined Synopsis/Solicitation`, `Sources Sought`, `Special Notice` |
| `postedAt`, `responseDeadline`, `archiveDate` | ISO 8601 | Standard timestamps |
| `agencyDepartment`, `agencyName`, `agencyOffice` | string | Full hierarchy split |
| `setAsideType` | enum | `8A`, `HZC`, `SDVOSBC`, etc. |
| `naicsCode`, `naicsDescription` | string | Primary NAICS |
| `placeOfPerformance` | object | `{ city, state, zip, country }` |
| `pointsOfContact` | array | `[{ name, email, phone, role }]` |
| `attachments` | array | `[{ name, url, contentType }]` |
| `recentAwards` | array | (when `joinUsaspending: true`) `[{ recipient, agency, amountUsd, awardDate, naics }]` |
| `awardHistorySummary` | object | `{ totalAwards, totalUsd, avgAwardUsd, topRecipient }` |
| `fieldCompletenessScore`, `agentMarkdown` | int / string | Quality + LLM-ready summary |
| `changeStatus`, `changedFields` | enum / string\[] | (when `detectChanges: true`) |

#### Federal Contracts scraper output example

```json
{
  "outputSchemaVersion": "2026-05-08",
  "recordType": "federal_opportunity",
  "recordId": "samgov:opp:abc123",
  "noticeId": "abc123",
  "solicitationNumber": "FA8773-26-R-0042",
  "title": "Cloud Engineering Support Services",
  "noticeType": "Combined Synopsis/Solicitation",
  "postedAt": "2026-05-08T13:00:00.000Z",
  "responseDeadline": "2026-06-15T17:00:00.000Z",
  "agencyDepartment": "DEPT OF DEFENSE",
  "agencyName": "DEPT OF THE AIR FORCE",
  "agencyOffice": "AIR FORCE LIFE CYCLE MANAGEMENT CENTER",
  "setAsideType": "SDVOSBC",
  "naicsCode": "541512",
  "recentAwards": [
    { "recipient": "Acme Corp", "agency": "DEPT OF THE AIR FORCE", "amountUsd": 4250000, "awardDate": "2025-09-15", "naics": "541512" }
  ],
  "awardHistorySummary": {
    "totalAwards": 23,
    "totalUsd": 84500000,
    "avgAwardUsd": 3673913,
    "topRecipient": "Acme Corp"
  },
  "fieldCompletenessScore": 95,
  "agentMarkdown": "**🇺🇸 Cloud Engineering Support Services**\n- 📋 SDVOSBC · NAICS 541512\n- 🏢 DEPT OF THE AIR FORCE / AFLCMC\n- 📅 posted 2026-05-08 · 📆 due 2026-06-15\n- 💰 23 prior awards, $84.5M total, avg $3.7M\n- 🔗 https://sam.gov/opp/abc123"
}
```

### During the Actor run

The actor calls SAM.gov's `/opportunities/v2/search` API with your filters, then for each opportunity (when `joinUsaspending: true`) calls USAspending's `/api/v2/search/spending_by_award/`. Both APIs are rate-limited at 1 second between requests.

The actor writes:

1. **`OUTPUT`** — run summary
2. **`AGENT_BRIEFING`** — top opportunities by completeness × deadline urgency
3. **`WATCHLIST_STATE`** — (when `watchlistMode: true`) seen notice IDs

### FAQ

#### How does this actor work?

The actor calls SAM.gov's official Opportunities API and USAspending's official Awards API. Both are free public .gov APIs. Records are normalized into one schema per opportunity with the recent-awards block joined.

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

Yes — get it free at https://open.gsa.gov/api/get-opportunities-public-api/ (~3 minutes; email + organization required). USAspending requires no key.

#### Can I monitor for new opportunities only?

Yes. Set `watchlistMode: true`. The actor stores seen notice IDs and emits only new opportunities.

#### Can I see what changed on an opportunity?

Yes. Set `detectChanges: true`. The actor diffs each record against the previous run and emits `changeStatus` (`new | updated | unchanged`) plus `changedFields[]`.

#### Can I filter by set-aside type?

Yes. `setAsides: ["8A", "HZC", "SDVOSBC", "WOSB", "EDWOSB"]`.

#### Can I get the full SOW?

Yes — `description` carries the full SOW from SAM.gov. Attachments are listed in `attachments[]` with direct URLs.

#### Can I use this with the Apify API?

Yes. POST to `https://api.apify.com/v2/acts/skootle~sam-gov-federal-contracts/runs`.

#### Can I integrate with Make / Zapier / n8n / Slack?

Yes. Click **Integrations** on the actor page.

#### Why does this actor cost more than free SAM.gov scrapers?

This actor ships the USAspending join (so you don't run two pipelines), the agency-hierarchy split, set-aside enum, change-detection mode, watchlist diff mode, agent-ready markdown summaries, and continuous maintenance.

#### Your feedback

Hit a bug or want a feature? Open an issue on the [Issues tab](https://apify.com/skootle/sam-gov-federal-contracts/issues/open) rather than the reviews page, and we'll fix it fast (typically within 48 hours).

### Why choose SAM.gov + USAspending Federal Contracts

- **Two APIs in one record** — SAM.gov opportunity + USAspending award history joined per opp
- **Agency hierarchy split** — `agencyDepartment`, `agencyName`, `agencyOffice` separate fields
- **Set-aside enum** — typed for easy filtering
- **Change-detection mode** — `changeStatus` + `changedFields[]` per record
- **Watchlist diff mode** — only emits NEW opportunities since the last run
- **Versioned schema** — `outputSchemaVersion: '2026-05-08'`
- **Idempotent record IDs** — `samgov:opp:<noticeId>` stable across runs
- **Agent-grade output** — `agentMarkdown` ready to paste into an LLM context
- **Direct from .gov APIs** — no HTML scraping fragility

### Other Skootle actors you might want to check

- **[Wellfound Jobs Scraper](https://apify.com/skootle/wellfound-jobs-scraper)** — startup hiring intelligence
- **[Crexi Commercial Real Estate](https://apify.com/skootle/crexi-commercial-real-estate-scraper)** — CRE listings with 50+ fields
- **[SEC EDGAR Filings Monitor](https://apify.com/skootle/sec-edgar-filings)** — public-company filings stream
- **[Reddit Subreddit Scraper](https://apify.com/skootle/reddit-subreddit-monitor)** — sentiment + brand monitoring
- **[Hacker News Watchlist](https://apify.com/skootle/hackernews-watchlist)** — tech discourse stream

### Support and contact

File issues on this actor's page — replies within 48 hours.

# Actor input Schema

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

Required. Get a free key in 4 steps: (1) Sign in at https://sam.gov with login.gov. (2) Click your name → My Account. (3) Skip the optional 'Request Role' step. (4) On Account Details, scroll to 'Public API Keys' → click 'Request API Key' → confirm with your password. Copy the key and paste it here. Stored encrypted; never visible to anyone, including the actor author. Rotate every 90 days per SAM.gov terms.

## `searchKeywords` (type: `array`):

Free-text full-text search across opportunity titles and descriptions, e.g. \['cybersecurity', 'logistics'].

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

Comma-separated NAICS codes to filter by industry, e.g. \['541511', '541512'] for software development services.

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

Small business set-aside categories.

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

Filter by federal agency name keyword(s), e.g. \['Defense', 'GSA', 'NASA'].

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

Filter by U.S. state codes for place of performance, e.g. \['VA', 'CA', 'TX'].

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

Limit to specific notice categories.

## `postedFrom` (type: `string`):

Earliest posted date (YYYY-MM-DD). Defaults to 7 days ago.

## `postedTo` (type: `string`):

Latest posted date (YYYY-MM-DD). Defaults to today.

## `enrichWithUsaspending` (type: `boolean`):

When true, every opportunity is augmented with recent NAICS-matched award history from USAspending (recipient, amount, date, agency).

## `enrichmentLookbackMonths` (type: `integer`):

How far back to query USAspending awards by NAICS for enrichment.

## `detectChanges` (type: `boolean`):

When true, the actor reads the previous run's record set from the key-value store, diffs by noticeId + fingerprint, and emits changeStatus = new | updated | unchanged plus changedFields\[].

## `maxItems` (type: `integer`):

Maximum opportunity records to save. Default is conservative so the daily auto-test fits Apify's 5-minute window. Raise it for production runs.

## Actor input object example

```json
{
  "searchKeywords": [
    "cybersecurity"
  ],
  "naicsCodes": [],
  "setAsideTypes": [],
  "agencies": [],
  "states": [],
  "noticeTypes": [],
  "enrichWithUsaspending": true,
  "enrichmentLookbackMonths": 24,
  "detectChanges": false,
  "maxItems": 10
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

Normalized federal contract opportunity records, optionally enriched with USAspending award history.

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

Compact OUTPUT object with item count, error counts, and quality diagnostics.

# 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 = {
    "searchKeywords": [
        "cybersecurity"
    ],
    "naicsCodes": [],
    "setAsideTypes": [],
    "agencies": [],
    "states": [],
    "noticeTypes": [],
    "postedFrom": "",
    "postedTo": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("skootle/sam-gov-federal-contracts").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 = {
    "searchKeywords": ["cybersecurity"],
    "naicsCodes": [],
    "setAsideTypes": [],
    "agencies": [],
    "states": [],
    "noticeTypes": [],
    "postedFrom": "",
    "postedTo": "",
}

# Run the Actor and wait for it to finish
run = client.actor("skootle/sam-gov-federal-contracts").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchKeywords": [
    "cybersecurity"
  ],
  "naicsCodes": [],
  "setAsideTypes": [],
  "agencies": [],
  "states": [],
  "noticeTypes": [],
  "postedFrom": "",
  "postedTo": ""
}' |
apify call skootle/sam-gov-federal-contracts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=skootle/sam-gov-federal-contracts",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "🇺🇸 SAM.gov Contracts Scraper",
        "description": "Scrape SAM.gov for U.S. federal contract opportunities + join with USAspending recent-award history. Set-aside type, agency hierarchy, contacts, attachments, place-of-performance. Watchlist + change-detection modes. Export, run via API, schedule, or integrate with other tools.",
        "version": "0.1",
        "x-build-id": "zbUXzj5VqVjfmqWLD"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/skootle~sam-gov-federal-contracts/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-skootle-sam-gov-federal-contracts",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/skootle~sam-gov-federal-contracts/runs": {
            "post": {
                "operationId": "runs-sync-skootle-sam-gov-federal-contracts",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/skootle~sam-gov-federal-contracts/run-sync": {
            "post": {
                "operationId": "run-sync-skootle-sam-gov-federal-contracts",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "samGovApiKey"
                ],
                "properties": {
                    "samGovApiKey": {
                        "title": "SAM.gov API key (paste here)",
                        "type": "string",
                        "description": "Required. Get a free key in 4 steps: (1) Sign in at https://sam.gov with login.gov. (2) Click your name → My Account. (3) Skip the optional 'Request Role' step. (4) On Account Details, scroll to 'Public API Keys' → click 'Request API Key' → confirm with your password. Copy the key and paste it here. Stored encrypted; never visible to anyone, including the actor author. Rotate every 90 days per SAM.gov terms."
                    },
                    "searchKeywords": {
                        "title": "Search keywords",
                        "type": "array",
                        "description": "Free-text full-text search across opportunity titles and descriptions, e.g. ['cybersecurity', 'logistics'].",
                        "items": {
                            "type": "string"
                        }
                    },
                    "naicsCodes": {
                        "title": "NAICS codes",
                        "type": "array",
                        "description": "Comma-separated NAICS codes to filter by industry, e.g. ['541511', '541512'] for software development services.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "setAsideTypes": {
                        "title": "Set-aside types",
                        "type": "array",
                        "description": "Small business set-aside categories.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "SBA",
                                "8A",
                                "HZC",
                                "SDVOSBC",
                                "WOSB",
                                "EDWOSB",
                                "VSA",
                                "VOSB",
                                "ISBEE"
                            ],
                            "enumTitles": [
                                "Small Business Total Set-Aside (SBA)",
                                "8(a) Sole Source / Competitive (8A)",
                                "HUBZone Set-Aside (HZC)",
                                "Service-Disabled Veteran-Owned Small Business Set-Aside (SDVOSBC)",
                                "Women-Owned Small Business Set-Aside (WOSB)",
                                "Economically Disadvantaged WOSB (EDWOSB)",
                                "Veteran-Owned Small Business Sole Source (VSA)",
                                "Veteran-Owned Small Business Set-Aside (VOSB)",
                                "Indian Small Business Economic Enterprise (ISBEE)"
                            ]
                        }
                    },
                    "agencies": {
                        "title": "Agencies",
                        "type": "array",
                        "description": "Filter by federal agency name keyword(s), e.g. ['Defense', 'GSA', 'NASA'].",
                        "items": {
                            "type": "string"
                        }
                    },
                    "states": {
                        "title": "Place-of-performance states",
                        "type": "array",
                        "description": "Filter by U.S. state codes for place of performance, e.g. ['VA', 'CA', 'TX'].",
                        "items": {
                            "type": "string"
                        }
                    },
                    "noticeTypes": {
                        "title": "Notice types",
                        "type": "array",
                        "description": "Limit to specific notice categories.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "Solicitation",
                                "Presolicitation",
                                "Combined Synopsis/Solicitation",
                                "Sources Sought",
                                "Award Notice",
                                "Special Notice"
                            ],
                            "enumTitles": [
                                "Solicitation",
                                "Presolicitation",
                                "Combined Synopsis/Solicitation",
                                "Sources Sought",
                                "Award Notice",
                                "Special Notice"
                            ]
                        }
                    },
                    "postedFrom": {
                        "title": "Posted from (ISO date)",
                        "type": "string",
                        "description": "Earliest posted date (YYYY-MM-DD). Defaults to 7 days ago."
                    },
                    "postedTo": {
                        "title": "Posted to (ISO date)",
                        "type": "string",
                        "description": "Latest posted date (YYYY-MM-DD). Defaults to today."
                    },
                    "enrichWithUsaspending": {
                        "title": "Enrich with USAspending award history",
                        "type": "boolean",
                        "description": "When true, every opportunity is augmented with recent NAICS-matched award history from USAspending (recipient, amount, date, agency).",
                        "default": true
                    },
                    "enrichmentLookbackMonths": {
                        "title": "USAspending lookback (months)",
                        "minimum": 1,
                        "maximum": 120,
                        "type": "integer",
                        "description": "How far back to query USAspending awards by NAICS for enrichment.",
                        "default": 24
                    },
                    "detectChanges": {
                        "title": "Detect changes since previous run (monitoring mode)",
                        "type": "boolean",
                        "description": "When true, the actor reads the previous run's record set from the key-value store, diffs by noticeId + fingerprint, and emits changeStatus = new | updated | unchanged plus changedFields[].",
                        "default": false
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum opportunity records to save. Default is conservative so the daily auto-test fits Apify's 5-minute window. Raise it for production runs.",
                        "default": 10
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
