# Federal Contracts, Grants & Lobbying API (`insight.solutions/federal-contracts-grants-api`) Actor

Four federal money sources in one dataset: SAM.gov opportunities with contracting-officer contacts (free SAM.gov key), Grants.gov notices with award ceilings, USAspending awards and sub-awards, Senate LDA lobbying filings. Filter by keyword, agency, NAICS, set-aside, state. Three need no API key.

- **URL**: https://apify.com/insight.solutions/federal-contracts-grants-api.md
- **Developed by:** [Insight Solutions](https://apify.com/insight.solutions) (community)
- **Categories:** Business, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.36 / 1,000 opportunity returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Federal Contracts, Grants & Lobbying API

Four US federal money sources in **one dataset schema**: the solicitation before
the award, the funding notice, the award and its sub-awards after the fact, and
who was paid to lobby about it.

| Source | What it gives you | Key needed |
|---|---|---|
| **SAM.gov** contract opportunities | Solicitations, sources-sought, award notices — deadlines, set-asides, NAICS, PSC, place of performance and the contracting officer's published contact | Your own free SAM.gov key |
| **Grants.gov** funding opportunities | Notices with award ceiling, floor, expected awards, eligibility text, ALN numbers and the attachment list | None |
| **USAspending** awards | Prime awards with recipient, UEI, obligated amount, outlays, period of performance, competition fields, sub-award totals, optional transactions and sub-awards | None |
| **Senate LDA** lobbying filings | LD-1 and LD-2 filings with client, registrant, income or expenses, issue codes, named lobbyists and the government entities contacted | None |

Same columns on every row. `agency`, `title`, `postedAt`, `amount` and `naics`
mean the same thing whether GSA posted a solicitation, HHS posted a funding
notice, Treasury paid the invoice or a law firm filed the disclosure — so
"everything the federal government is buying, funding and being lobbied about
in cybersecurity" is one query and one table.

No login. No cookie that identifies anyone. No headless browser. All four are
public-domain US Government records.

> This product uses the Grants.gov API but is not endorsed or certified by the U.S. Department of Health and Human Services.

### At a glance

**Input** — this is the Store prefill; paste it and run, no key needed:

```json
{
  "sources": ["grants", "awards"],
  "keywords": ["cybersecurity"],
  "grantStatuses": ["posted", "forecasted"],
  "awardTypes": ["contracts"],
  "maxResults": 25
}
```

Add `"opportunities"` and `"lobbying"` to `sources` for the other two systems;
`opportunities` needs your own free SAM.gov key in `samApiKey`.

**Output** — one row per record, same columns across all four sources; the fields
you will use most are `title`, `agency`, `postedAt`, `amount` and `url` (full
list under *Output reference*). Anything that could not be fetched comes back as
a free diagnostic row (`ok: false`, `errorType`, `error`) instead of a charge,
and `summary` / `facet` rows are free too.

**Price** — $0.60 per 1,000 opportunities, $0.40 per 1,000 awards and $0.60 per
1,000 lobbying filings on the FREE tier (+ $0.001 per run); rows your filters
excluded, every detail fetch, every nested `transactions[]` / `subawards[]`, and
every `summary`, `facet` and `diagnostic` row are free. Pay-per-event, no browser,
limited permissions — works over the Apify MCP server (`mcp.apify.com`) and with
agentic (x402) payments.

**From code** —
`client.actor("insight.solutions/federal-contracts-grants-api").call(run_input={…})`
with `apify-client`, or
`POST https://api.apify.com/v2/acts/insight.solutions~federal-contracts-grants-api/run-sync-get-dataset-items`.

***

### What you get

One row per record. This is a real Grants.gov row, trimmed to the columns that
carry something:

```json
{
  "ok": true,
  "rowType": "opportunity",
  "source": "grants.gov",
  "input": "cybersecurity",
  "recordId": "363843",
  "url": "https://www.grants.gov/search-results-detail/363843",
  "title": "Advisory Support for Establishing a National Cybersecurity Operations Center (SOC)",
  "agency": "Department of State",
  "subAgency": "Bureau of Emerging Threats",
  "agencyCode": "DOS-ET",
  "solicitationNumber": "DFOP0019791",
  "postedAt": "2026-09-10T00:00:00.000Z",
  "responseDeadline": "2026-10-16T04:00:00.000Z",
  "daysUntilDeadline": 31,
  "status": "posted",
  "isActive": true,
  "awardCeiling": 13912185,
  "awardFloor": 13912185,
  "estimatedFunding": 13912185,
  "expectedAwards": 1,
  "costSharing": false,
  "eligibility": "Not for profit organizations, including think tanks, civil society and non governmental organizations; Public and private educational institutions; …",
  "eligibilityTypes": [{ "code": "25", "description": "Others (see text field entitled \"Additional Information on Eligibility\" for clarification)" }],
  "fundingInstruments": [{ "code": "CA", "description": "Cooperative Agreement" }],
  "fundingCategories": [{ "code": "ST", "description": "Science and Technology and other Research and Development" }],
  "alnNumbers": ["19.047"],
  "opportunityCategory": "Discretionary",
  "contacts": [{ "type": "agency", "fullName": "Bureau of Emerging Threats", "email": "ET-Programs@state.gov", "phone": "202-776-0446", "note": "ET-Programs@state.gov" }],
  "attachments": [{ "fileName": "08262026 NOFO - … v3.docx", "fileDescription": "NOFO", "mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "sizeBytes": 138629, "id": 355006, "url": null }],
  "description": "Improve Argentina's national cybersecurity posture by providing advisory support to design, establish, and operationalize a centralized, civilian led national Cybersecurity Operations Center …",
  "scrapedAt": "2026-09-15T04:10:00.000Z",
  "sourceUrl": "https://www.grants.gov/search-results-detail/363843"
}
```

A USAspending award row fills the award half of the same schema instead —
`awardId`, `generatedId`, `recipientName`, `recipientUei`, `amount`, `outlays`,
`startDate`, `endDate`, `awardingAgency`, `contractAwardType`, `naics`, `psc`,
`subawardCount`, `extentCompeted`, and `transactions[]` / `subawards[]` when you
ask for them. A Senate LDA row fills the lobbying half — `client`, `registrant`,
`amountReported`, `issueCodes`, `lobbyists[]`, `governmentEntities[]`.

Six dataset views ship with it: **Opportunities**, **Awards**, **Lobbying**,
**Deadlines** (opportunities sorted by how long you have left), **Summaries** and
**Problems**.

***

### Quick start

Keyless, and it returns rows immediately:

```json
{
  "sources": ["grants", "awards"],
  "keywords": ["cybersecurity"],
  "awardTypes": ["contracts"],
  "maxResults": 25
}
```

All four sources, once you have a SAM.gov key:

```json
{
  "sources": ["opportunities", "grants", "awards", "lobbying"],
  "samApiKey": "<your free SAM.gov Public API Key>",
  "keywords": ["cybersecurity"],
  "naicsCodes": ["541512"],
  "setAsides": ["SBA"],
  "lobbyingIssues": ["SCI"],
  "maxResults": 100
}
```

A daily monitor of new small-business solicitations:

```json
{
  "sources": ["opportunities"],
  "samApiKey": "<your key>",
  "noticeTypes": ["o", "k", "p"],
  "setAsides": ["SBA"],
  "naicsCodes": ["5415"],
  "incremental": true,
  "maxResults": 200
}
```

***

### The SAM.gov key, and why it is yours

SAM.gov's Terms of Use point automated users at its documented API rather than
at the endpoints its own web page calls, so this Actor uses the official
**Get Opportunities Public API v2** at `api.sam.gov` and never scrapes sam.gov.
That API takes a key, and the key belongs to you:

1. Sign in at **sam.gov**.
2. Open **Account Details**.
3. Choose **Request Public API Key**.
4. Paste it into `samApiKey`. The field is marked secret, so Apify encrypts it;
   the key is sent to `api.sam.gov` in an `X-Api-Key` header and never appears in
   a row, a log line, a status message or a `sourceUrl`.

**A personal (non-federal) key allows 10 requests per day.** Each request returns
up to 1,000 notices, so ten requests is up to 10,000 notices — but it is ten
*requests*, which is why:

- the run asks for the largest page the API allows and takes as few pages as
  `maxResults` needs;
- `includeDescriptions` is **off by default** — each notice's full description is
  a separate request, and at most five are fetched per run;
- the run stops itself at ten requests and leaves a free `cap-reached` row rather
  than spending an allowance you may want for something else;
- an HTTP 429 becomes a free `rate-limited` row that says what the daily limit
  is, and every row already returned stays in the dataset.

Leave `samApiKey` empty and the `opportunities` source is simply skipped, with
one free diagnostic row saying where the key comes from. The other three sources
need nothing at all.

***

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `sources` | multi-select | `["grants","awards"]` | `opportunities` (SAM.gov), `grants` (Grants.gov), `awards` (USAspending), `lobbying` (Senate LDA) |
| `keywords` | string\[] | `[]` | Free text, applied per source |
| `grantStatuses` | multi-select | `["posted","forecasted"]` | Add `closed` and `archived` for history |
| `awardTypes` | multi-select | `["contracts"]` | `contracts`, `idvs`, `grants`, `directPayments`, `loans`, `other` |
| `maxResults` | integer | `200` | **Per source**. `0` means no cap |
| `samApiKey` | string (secret) | — | Your own free SAM.gov Public API Key. Only the `opportunities` source needs it |
| `dateFrom` / `dateTo` | ISO date | — / today | Applied per source. USAspending's own floor is 2007-10-01; SAM.gov accepts at most a one-year window |
| `agencies` | string\[] | `[]` | Names or abbreviations. Resolved against each source's own agency list |
| `states` | string\[] | `[]` | Two-letter codes |
| `naicsCodes` | string\[] | `[]` | Six digits or a prefix |
| `pscCodes` | string\[] | `[]` | Product or Service Codes |
| `minAmount` / `maxAmount` | number | — | Award amount, grant ceiling, or lobbying income/expenses |
| `setAsides` | string\[] | `[]` | `SBA`, `8A`, `HZC`, `SDVOSBC`, `WOSB`, `EDWOSB`, … |
| `noticeTypes` | multi-select | `[]` (all) | `o` solicitation, `k` combined synopsis, `p` presolicitation, `r` sources sought, `s` special notice, `a` award notice, `g` sale of surplus, `i` intent to bundle |
| `recipients` | string\[] | `[]` | USAspending recipient search |
| `lobbyingClients` / `lobbyingRegistrants` / `lobbyingLobbyists` | string\[] | `[]` | Partial-match name filters |
| `lobbyingIssues` | string\[] | `[]` | LDA issue codes (`SCI`, `TAX`, `DEF`, …), validated against the LDA's own list |
| `filingYear` | integer | current year | Which year of LDA filings |
| `activeOnly` | boolean | `true` | Keep only SAM.gov notices still reported as active |
| `fundingCategories` / `eligibilities` / `fundingInstruments` | string\[] | `[]` | Grants.gov facet codes |
| `alnCodes` | string\[] | `[]` | ALN / CFDA, e.g. `93.788` |
| `filingTypes` | string\[] | `[]` | `Q1`…`Q4`, `RR`, `MM` and the amendment codes |
| `includeDetails` | boolean | `true` | The per-record detail fetch. **Inside the row price** |
| `includeDescriptions` | boolean | `false` | SAM.gov full descriptions; each one costs a request against the 10/day key |
| `includeTransactions` / `includeSubawards` | boolean | `false` | Nested on `award` rows, never billed separately |
| `maxTransactionsPerAward` / `maxSubawardsPerAward` | integer | `50` / `50` | Caps on those nested lists |
| `includeSummary` | boolean | `true` | Free `summary` and `facet` rows |
| `includeRawDescription` | boolean | `false` | Keep the untouched HTML in `descriptionHtml` |
| `incremental` | boolean | `false` | Skip records returned by an earlier run |
| `stateStoreName` | string | `federal-contracts-grants-state` | Which named store holds the cursor |
| `maxConcurrency` | integer | `4` | Sources and detail fetches in flight |
| `maxRunSecs` | integer | `240` | Time budget; rows already returned are kept |
| `proxyConfiguration` | object | `{"useApifyProxy": true}` | Datacenter by default; all four APIs also answered unproxied |

**Filters switch sources on.** Typing a set-aside turns the `opportunities`
source on; an ALN turns `grants` on; a recipient turns `awards` on; a lobbying
client turns `lobbying` on. It is additive only — it never removes a source you
picked.

***

### Output reference

Every row carries every column, `null` where it does not apply.

**Envelope** — `ok`, `rowType`, `input`, `source`, `sourceUrl`, `scrapedAt`,
`error`, `errorType`.

**Shared** — `recordId`, `url`, `title`, `agency`, `subAgency`, `office`,
`agencyCode`, `agencyHierarchy`, `postedAt`, `updatedAt`, `description`,
`naics`, `psc`.

**`opportunity`** — `noticeId`, `noticeType`, `noticeTypeCode`,
`solicitationNumber`, `parentNoticeId`, `responseDeadline`,
`responseDeadlineLocal`, `responseTimeZone`, `daysUntilDeadline`, `archiveDate`,
`setAside`, `setAsideDescription`, `placeOfPerformance`,
`placeOfPerformanceState`, `placeOfPerformanceCountry`, `awardCeiling`,
`awardFloor`, `estimatedFunding`, `expectedAwards`, `costSharing`, `eligibility`,
`eligibilityTypes`, `fundingInstruments`, `fundingCategories`, `alnNumbers`,
`opportunityCategory`, `contacts`, `attachments`, `isActive`, `isCanceled`,
`status`, `modificationCount`, `descriptionHtml`.

**`award`** — `awardId`, `generatedId`, `internalId`, `awardType`,
`awardTypeCode`, `awardCategory`, `contractAwardType`, `recipientName`,
`recipientUei`, `recipientId`, `recipientParentName`, `recipientParentUei`,
`recipientLocation`, `amount`, `outlays`, `baseAndAllOptions`,
`baseExercisedOptions`, `startDate`, `endDate`, `potentialEndDate`, `dateSigned`,
`lastModified`, `awardingAgency`, `awardingSubAgency`, `awardingOffice`,
`fundingAgency`, `fundingSubAgency`, `parentAwardId`, `cfdaNumber`, `saiNumber`,
`defCodes`, `extentCompeted`, `numberOfOffers`, `typeSetAside`, `subawardCount`,
`subawardTotal`, `executiveCompensation`, `transactions`, `subawards`.

**`lobbying-filing`** — `filingUuid`, `filingType`, `filingTypeDisplay`,
`filingYear`, `period`, `periodDisplay`, `filingDocumentUrl`, `postedByName`,
`terminationDate`, `registrant`, `registrantId`, `registrantCity`,
`registrantState`, `registrantCountry`, `registrantDescription`,
`registrantContactName`, `registrantContactPhone`, `client`, `clientId`,
`clientState`, `clientCountry`, `clientDescription`, `clientGovernmentEntity`,
`income`, `expenses`, `expensesMethod`, `amountReported`, `issueCodes`,
`activities`, `lobbyists`, `lobbyistCount`, `governmentEntities`,
`foreignEntities`, `affiliatedOrganizations`, `convictionDisclosures`.

**`summary` / `facet`** — `summaryType`, `metric`, `label`, `code`, `value`,
`count`, `rank`, `totalResults`.

#### Notes on particular columns

- **`daysUntilDeadline`** is the only derived number in the schema: whole days
  from that row's own `scrapedAt` to `responseDeadline`, negative once the
  deadline has passed. Everything else is published data, reshaped.
- **`amountReported`** on a lobbying filing is `income ?? expenses`, so one
  numeric column sorts across both LD-2 reporting styles — a firm reports income
  for a client, an in-house filer reports expenses.
- **Money is null when absent, never zero.** "No award ceiling published" and "a
  ceiling of nothing" are different facts.
- **Dates** are ISO-8601 UTC instants. Four upstream formats feed them — ISO with
  an offset, `MM/DD/YYYY`, `Sep 10, 2026 12:00:00 AM EDT`, and
  `2026-06-15 07:29:54` — each parsed with an explicit month map and offset
  table, never handed to a permissive date constructor. USAspending's
  `Last Modified Date` publishes no time zone and is read as UTC.
- **`contacts`** on a SAM.gov notice are the contracting officer or specialist
  that SAM.gov publishes **so vendors can respond to the notice**. Asking them
  about the solicitation is what they are for. They are not a marketing list.
- **`attachments`** carries metadata and, on SAM.gov, the resource link. Nothing
  is ever downloaded. The Grants.gov attachment download path was not verified,
  so those rows carry `url: null` rather than a link that may not work.

***

### Coverage, in numbers

Measured on 2026-09-15 against the live APIs:

- **SAM.gov** — the `opportunities` API returns up to 1,000 notices per request,
  and a personal key gets 10 requests a day. `postedFrom`/`postedTo` are
  required and may be at most one year apart.
- **Grants.gov** — 210 posted or forecasted opportunities matched "cybersecurity"
  on that date; roughly 1,200 are in `posted` status at any time. Adding
  `closed` and `archived` reaches back to at least 2015 — 18,316 hits for
  "water" alone.
- **USAspending** — for one probe filter: 675 contracts, 564 grants, 128 IDVs,
  40 direct payments, 5 other, 1 loan. Its own responses say the earliest date it
  will search is **2007-10-01**.
- **Senate LDA** — **56,482 filings in 2026** alone; 2,623 of them mention
  artificial intelligence in their issue descriptions.

### Freshness, honestly

- **SAM.gov and Grants.gov** are live at run time — a notice posted this morning
  is in this afternoon's run.
- **USAspending** lags agency reporting by weeks. It is the record of what was
  paid, not a real-time feed.
- **Senate LDA** filings appear within about a day of submission, but an LD-2
  covers a calendar quarter: a Q3 report is a quarterly summary, not a signal
  about this week.

***

### Running it every day

Set `incremental: true` and the run remembers what it has already returned, in a
named key-value store that outlives the run. Four ID spaces are kept apart —
SAM.gov notice IDs, Grants.gov opportunity IDs, USAspending internal IDs and LDA
filing UUIDs — and the check happens **before** the detail fetch and before the
charge, so a record you have already seen costs no request and no money. Use a
different `stateStoreName` for each saved search.

**The honest caveat:** ID de-duplication also suppresses a record that has since
been *amended*. A SAM.gov notice can be modified and a USAspending award's
`lastModified` moves as transactions post. If you want modifications, run with
`incremental: false` and a rolling `dateFrom` window instead. This is a "what's
new" cursor, not a change monitor.

A quiet day — nothing new since yesterday — finishes **successfully** with zero
paid rows and bills nothing.

***

### What you are never charged for

- Rows that were read and then excluded by one of your filters. Every filter runs
  **before** the row is written, so it is never billed.
- `summary` rows: how many records each source matched in total, USAspending's
  award counts by category, and its top ten agencies, recipients and NAICS codes
  by obligated dollars.
- `facet` rows: Grants.gov's own agency, funding-category, eligibility,
  funding-instrument and status counts.
- Every `diagnostic` row — `no-results`, `not-found`, `invalid-input`, `blocked`,
  `rate-limited`, `timeout`, `unavailable`, `cap-reached`, `budget-reached`,
  `notice`, `sam-api-key-required`.
- Nested `transactions[]`, `subawards[]` and `executiveCompensation[]`.
- Every detail fetch: Grants.gov `fetchOpportunity`, USAspending's award record,
  SAM.gov's descriptions, the agency lists and the LDA constants.
- A run that returns nothing. It finishes **FAILED**, says why, and bills
  nothing at all — the start fee included.

### Pricing

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Run started | $0.001 | $0.001 | $0.001 | $0.001 |
| **Opportunity returned** | **$0.0006** | $0.0006 | $0.00048 | $0.00036 |
| Award returned | $0.0004 | $0.0004 | $0.00032 | $0.00024 |
| Lobbying filing returned | $0.0006 | $0.0006 | $0.00048 | $0.00036 |

**$0.60 per 1,000 opportunities**, **$0.40 per 1,000 awards**, **$0.60 per 1,000
lobbying filings** at the free tier. A SAM.gov notice and a Grants.gov notice
cost the same, because they are the same row doing the same work.

The run honours `ACTOR_MAX_TOTAL_CHARGE_USD`: when the ceiling is reached it
stops fetching, leaves a free `budget-reached` row, keeps everything already
delivered and finishes successfully.

***

### Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor
runs with **limited permissions**, uses **pay-per-event** pricing and never enters
Standby, so it works over the Apify MCP server and with x402 agentic payments.
The **Integrations** tab pushes results to Slack, a webhook, Zapier, Make, Google
Sheets, Snowflake or BigQuery.

```bash
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~federal-contracts-grants-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sources":["grants","awards"],"keywords":["cybersecurity"],"maxResults":50}'
```

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/federal-contracts-grants-api").call(run_input={
    "sources": ["opportunities", "grants", "awards", "lobbying"],
    "samApiKey": "<your free SAM.gov Public API Key>",
    "keywords": ["cybersecurity"],
    "naicsCodes": ["541512"],
    "lobbyingIssues": ["SCI"],
    "maxResults": 100,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if not row.get("ok"):
        continue
    if row["rowType"] == "opportunity":
        print(row["source"], row["agency"], row["title"],
              row["responseDeadline"], row["daysUntilDeadline"], row["url"], sep=" | ")
    elif row["rowType"] == "award":
        print("award", row["recipientName"], row["amount"], row["awardingAgency"], row["url"], sep=" | ")
    elif row["rowType"] == "lobbying-filing":
        print("lobbying", row["client"], row["registrant"], row["amountReported"], row["issueCodes"], sep=" | ")
```

Leave `samApiKey` out and the other three sources still work. Set
`incremental: true` when you want a monitor rather than a backfill.

***

### FAQ

**Do I need any key at all?**
Only for SAM.gov contract opportunities, and that key is free and personal to
you. Grants.gov, USAspending and the Senate LDA need nothing.

**Why does SAM.gov need a key when the website does not?**
SAM.gov's Terms of Use direct automated users to its documented APIs rather than
to the endpoints its own web page calls. This Actor follows that: it uses
`api.sam.gov/opportunities/v2/search` and never scrapes sam.gov.

**Can I get more than 10 SAM.gov requests a day?**
That is the published limit for a personal (non-federal) key. Each request
returns up to 1,000 notices, so it is a limit on *queries*, not on volume. A
federal account gets a higher allowance from GSA.

**Why is my run slower than I expected?**
USAspending. A `spending_by_award` POST took between 1.2 and 14.9 seconds in
testing, and the category queries that build the free summary rows took 6–13
seconds each. Raise `maxRunSecs` for large runs, or set `includeSummary: false`.

**Can I filter by more than one NAICS code on SAM.gov?**
The API takes one NAICS per request and requests are the scarce resource, so the
first one goes into the query and the rest are matched on the rows before they
are written — which means they are still free to you, they just do not narrow
the request.

**Does it download attachments?**
No. It publishes the metadata — and, on SAM.gov, the resource link — so you can
decide. Attachment downloading is not in this version.

**Can I search SAM.gov entity or exclusion records?**
No, and deliberately. This Actor reads contract *opportunity* notices only. It
never touches entity registration, exclusion or Dun & Bradstreet data.

**What happens when a source is down?**
That source leaves a free diagnostic row saying so, and the others keep going.
The run succeeds if any source produced a row, and fails — free — if none did.

**Are the lobbyists' names really published?**
Yes. The Lobbying Disclosure Act requires registrants to name the individuals
who lobbied on each issue, and the Senate Office of Public Records publishes
those filings for public inspection. This Actor reproduces them as filed.

***

### Limitations

- **SAM.gov needs your key**, and a personal key is 10 requests a day. A very
  large SAM.gov backfill is several days of runs, not one.
- **Attachment downloads are not in v1.** Metadata and links only.
- **Federal Register, FEC and SAM.gov entity data are not in v1.**
- **Grants.gov has no server-side date filter.** Date narrowing for that source
  happens on the rows, before they are written and billed, which is correct but
  means a wide date filter reads more pages than it returns.
- **USAspending's PSC filter takes code *paths*, not flat codes**, so PSC
  narrowing for awards is done on the rows instead. Same for any filter the
  endpoint rejects: the query is re-sent without it and the narrowing happens
  here, with a free `notice` row telling you so.
- **The Senate LDA is 15 requests a minute** for an anonymous caller, and this
  Actor paces itself to 14 with at least four seconds between requests. Two
  hundred filings is about eight requests and under a minute; twenty thousand is
  not a single run.
- **Incremental mode is a "what's new" cursor, not a change monitor** — see the
  caveat above.
- **The upstream format may change.** These are four independently operated
  government APIs. Every parser treats every field as optional and a shape it
  does not recognise becomes a free diagnostic row rather than a wrong value, but
  a column can go null if an agency changes what it publishes.

***

### Sources, terms and attribution

All four sources are works of the United States Government and carry no
copyright (17 U.S.C. §105). They are procurement, spending and
lobbying-disclosure records published for public inspection. **No use
restriction of the kind the Ethics in Government Act places on congressional
financial disclosures applies to any of this data** — there is no equivalent
statute here.

- **SAM.gov.** Its Terms of Use state that automated data gathering and web
  scraping tools are prohibited and direct automated users to the APIs published
  at `open.gsa.gov/api` and `sam.gov/data-services`. This Actor uses exactly
  that: the documented Get Opportunities Public API v2, with your own key, at a
  polite volume, respecting the key's published allowance. A separate clause
  prohibiting systematic extraction is scoped to Dun & Bradstreet-supplied
  **entity** data — which this Actor never requests.
- **Grants.gov.** *This product uses the Grants.gov API but is not endorsed or
  certified by the U.S. Department of Health and Human Services.* The Grants.gov
  API terms also forbid modifying or misrepresenting API content and reserve
  HHS's right to limit or terminate access.
- **USAspending.** Its documentation states that endpoints do not currently
  require any authorization. DATA Act public data.
- **Senate LDA.** Source: **LDA.gov**. Its terms set 15 requests per minute for an
  anonymous caller, require citing LDA.gov as the source, and forbid modifying or
  misrepresenting the content. The Senate Office of Public Records cannot vouch
  for data or analyses derived from these data after they have been retrieved
  from LDA.gov.

This Actor is independent. It is not affiliated with, endorsed by or sponsored by
the U.S. General Services Administration, the Department of Health and Human
Services, the Department of the Treasury or the Senate Office of Public Records.
Nothing here is legal advice, and you are responsible for using the data
lawfully.

***

### Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

**Video, audio & social**

- [YouTube Transcript API](https://apify.com/insight.solutions/youtube-transcript-api) — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- [YouTube Comments API](https://apify.com/insight.solutions/youtube-comments-api) — comments and replies with likes, pinned and hearted flags, newest or top sort.
- [YouTube Channel API](https://apify.com/insight.solutions/youtube-channel-api) — a channel's videos, Shorts and live streams, plus YouTube search.
- [Podcast Search, Episodes & Charts API](https://apify.com/insight.solutions/podcast-api) — Apple Podcasts search, charts and full episode feeds.
- [Bluesky Scraper](https://apify.com/insight.solutions/bluesky-scraper) — profiles, posts, followers and follows from the public AT Protocol API.
- [Telegram Channel Scraper](https://apify.com/insight.solutions/telegram-channel-scraper) — posts, views and channel stats from public Telegram channels.
- [Substack Scraper](https://apify.com/insight.solutions/substack-scraper) — posts with full free text, comments and publication profiles.
- [Hacker News API](https://apify.com/insight.solutions/hacker-news-api) — stories, comments, users, front page and a structured "Who is hiring?" parser from the official HN APIs.

**News, documents & the web**

- [Google News Search, Topics & Real Article URLs](https://apify.com/insight.solutions/google-news-api) — news search and topic feeds with the publisher's real URL decoded.
- [Website to Markdown — Content Extractor for LLMs & RAG](https://apify.com/insight.solutions/website-content-extractor) — any site as clean Markdown, text and heading-aware chunks.
- [Internet Archive API](https://apify.com/insight.solutions/internet-archive-api) — archive.org search, item metadata, files and reviews.
- [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit) — archived URL inventories, snapshots and text diffs between dates.
- [Website Technology Detector](https://apify.com/insight.solutions/website-tech-detector) — the tech stack behind any site, with the evidence for each detection.
- [Domain Intelligence API](https://apify.com/insight.solutions/domain-intelligence-api) — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- [SEO Page Audit](https://apify.com/insight.solutions/seo-page-audit) — sitemap crawl with on-page checks, structured data and broken-link reports.
- [Keyword Suggestions API](https://apify.com/insight.solutions/keyword-suggestions-api) — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- [Website Contact Extractor](https://apify.com/insight.solutions/website-contact-extractor) — emails, phone numbers and social profiles from any list of websites.
- [Web Search Results API](https://apify.com/insight.solutions/web-search-api) — Bing and DuckDuckGo organic results with snippets, no key, no browser.
- [Company Enrichment API](https://apify.com/insight.solutions/company-enrichment-api) — a domain in, a company profile out: firmographics, contacts, tech stack, DNS and hiring signal.

**Business, finance & jobs**

- [Congress & Insider Trades API](https://apify.com/insight.solutions/congress-insider-trades-api) — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- [SEC EDGAR API](https://apify.com/insight.solutions/sec-edgar-api) — filings, XBRL financials and full-text search by ticker or CIK.
- [Clinical Trials & FDA API](https://apify.com/insight.solutions/clinical-trials-fda-api) — ClinicalTrials.gov studies plus openFDA recalls, labels, approvals, 510(k)s and adverse-event reports.
- [Product & Vehicle Recalls API](https://apify.com/insight.solutions/product-recalls-api) — CPSC, NHTSA, FDA and USDA recalls, vehicle complaints and ratings, plus a VIN decoder.
- [Y Combinator Companies, Batches & Founders](https://apify.com/insight.solutions/yc-companies-directory) — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- [Career Site Jobs API](https://apify.com/insight.solutions/ats-jobs-api) — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- [New Job Postings Monitor](https://apify.com/insight.solutions/job-postings-monitor) — new, closed and changed postings on the career sites you watch.
- [Remote Jobs API](https://apify.com/insight.solutions/remote-jobs-api) — RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy and more in one schema, deduplicated.
- [Shopify Products API](https://apify.com/insight.solutions/shopify-products-api) — any Shopify store's catalogue, variants, prices and stock signals.
- [Shopify Store Monitor](https://apify.com/insight.solutions/shopify-store-monitor) — price drops, sales, restocks, sell-outs and new products on any Shopify store, one row per change.

**Apps & games**

- [App Store & Google Play Reviews API](https://apify.com/insight.solutions/app-reviews-api) — reviews from both stores with ratings, versions and developer replies.
- [App Store Top Charts & App Search API](https://apify.com/insight.solutions/app-charts-api) — Apple top charts by country and genre, plus app search and details.
- [App Store Keyword Rank Tracker](https://apify.com/insight.solutions/app-store-keyword-rank-tracker) — where any app ranks for any keyword on the App Store and Google Play, with rank changes and ASO suggestions.
- [Steam Reviews API](https://apify.com/insight.solutions/steam-reviews-api) — Steam reviews with playtime, helpfulness and game details.
- [Steam Game Data API](https://apify.com/insight.solutions/steam-store-stats-api) — prices, tags, review scores, live player counts and top charts.

# Actor input Schema

## `sources` (type: `array`):

Which federal systems to read. `grants` (Grants.gov funding notices) and `awards` (USAspending prime awards) need no key at all. `opportunities` reads SAM.gov contract opportunities through the official Get Opportunities API and needs your own free `samApiKey`. `lobbying` reads Senate LDA filings. All four produce the same columns, so a run over several of them is one table.

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

Free-text search, applied per source: SAM.gov searches notice titles, Grants.gov searches the full notice, USAspending searches award text, and the Senate LDA searches the lobbying-issue descriptions. Several words are joined with spaces. Leave empty to take everything the other filters allow.

## `grantStatuses` (type: `array`):

Which Grants.gov statuses to search. `closed` and `archived` reach historical notices going back to at least 2015; `posted` and `forecasted` are the roughly 1,200 opportunities open at any time.

## `awardTypes` (type: `array`):

Which USAspending award categories to search. USAspending requires at least one, so leaving this empty means contracts.

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

How many paid rows each selected source may return. `0` means no cap. A four-source run at the default therefore tops out at 800 paid rows.

## `samApiKey` (type: `string`):

Your own free SAM.gov Public API Key, required only for the `opportunities` source. Get one at sam.gov → sign in → Account Details → **Request Public API Key**. A personal (non-federal) key allows 10 requests per day, and each request returns up to 1,000 notices. The key is sent to api.sam.gov in an `X-Api-Key` header and is never written to a row, a log line or a result URL. Leave empty and the `opportunities` source is skipped with a free diagnostic row explaining this.

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

ISO date, e.g. `2026-01-01`. Applied per source: SAM.gov posted date (the API requires a window and defaults to the last 30 days), Grants.gov open/close dates, USAspending action period (its own earliest date is 2007-10-01) and the LDA posting date.

## `dateTo` (type: `string`):

ISO date, e.g. `2026-09-30`. Defaults to today. SAM.gov accepts a window of at most one year; a wider range is clamped to the most recent year and a free diagnostic row says so.

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

Agency names or abbreviations, e.g. `["Department of Defense"]` or `["DOD"]`. Resolved per source: USAspending matches them against its published top-tier agency list, Grants.gov against the agency codes in the result set, SAM.gov against the notice's own organisation path, and the LDA against the government entities named on the filing. A name that cannot be resolved gets a free diagnostic row and the run continues.

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

Two-letter state codes, e.g. `["VA", "TX"]`. Matched against the place of performance on opportunities and awards, and against the client's state on lobbying filings.

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

Six-digit NAICS codes or prefixes, e.g. `["541512"]` or `["5415"]`. Used by SAM.gov and USAspending; Grants.gov and the LDA have no NAICS field and are unaffected.

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

Product or Service Codes, e.g. `["D302"]`. Sent to SAM.gov as a filter; on USAspending awards the code is matched on the returned rows instead, because the endpoint's PSC filter takes code *paths* rather than flat codes.

## `minAmount` (type: `integer`):

Keep only records worth at least this much: the award amount on USAspending, the award ceiling on Grants.gov, and the income or expenses reported on a lobbying filing. Leave empty for no minimum.

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

SAM.gov set-aside codes, e.g. `["SBA"]` (total small business), `["8A"]`, `["HZC"]`, `["SDVOSBC"]`, `["WOSB"]`, `["EDWOSB"]`. Setting this switches the `opportunities` source on.

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

Which kinds of SAM.gov notice to return. Leave empty for all of them. Setting this switches the `opportunities` source on.

## `recipients` (type: `array`):

Recipient names to search for on USAspending, e.g. `["Lockheed Martin"]`. Partial matches. Setting this switches the `awards` source on.

## `lobbyingClients` (type: `array`):

Client names on Senate LDA filings, e.g. `["Amazon"]`. Partial match. Setting this switches the `lobbying` source on.

## `lobbyingRegistrants` (type: `array`):

Registrant (lobbying firm) names, e.g. `["Akin Gump"]`. Partial match. Setting this switches the `lobbying` source on.

## `lobbyingIssues` (type: `array`):

Senate LDA general issue codes, e.g. `["SCI"]` (science/technology), `["TAX"]`, `["DEF"]`. Validated against the LDA's own published list; an unknown code gets a free diagnostic row naming where the valid ones live.

## `filingYear` (type: `integer`):

Which year of Senate LDA filings to read. Defaults to the current year when the `lobbying` source runs.

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

Keep only SAM.gov notices the system still reports as active. Turn it off to reach archived notices inside the date window.

## `fundingCategories` (type: `array`):

Grants.gov funding-category codes, e.g. `["HL"]` (health), `["ST"]` (science and technology), `["AG"]` (agriculture). Setting this switches the `grants` source on.

## `eligibilities` (type: `array`):

Grants.gov applicant-eligibility codes, e.g. `["02"]` (city or township governments), `["25"]` (others). Setting this switches the `grants` source on.

## `fundingInstruments` (type: `array`):

Grants.gov funding-instrument codes: `G` grant, `CA` cooperative agreement, `PC` procurement contract, `O` other.

## `alnCodes` (type: `array`):

Assistance Listing Numbers, e.g. `["93.788"]`. Sent to Grants.gov as its `cfda` parameter and to USAspending as `program_numbers`.

## `lobbyingLobbyists` (type: `array`):

Named lobbyists to search for. Setting this switches the `lobbying` source on.

## `filingTypes` (type: `array`):

LDA filing types, e.g. `["Q1"]`…`["Q4"]` (quarterly reports), `["RR"]` (registration), `["MM"]` (mid-year). The API takes one per request, so several types mean several requests against a 15-per-minute budget.

## `maxAmount` (type: `integer`):

The other end of the same band. Leave empty for no maximum.

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

Fetch the per-record detail: the Grants.gov synopsis with its award ceiling, eligibility text, agency contact and attachment list, and the USAspending award record with its sub-award totals, competition fields and period of performance. Inside the row price — it is not a separate charge. Turn it off for a faster, shallower run.

## `includeDescriptions` (type: `boolean`):

Fetch the full description text of each SAM.gov notice. Off by default because each description is a **whole extra request** against a personal key's 10-per-day allowance; at most 5 are fetched per run and the log says how many.

## `includeTransactions` (type: `boolean`):

Nest each USAspending award's transaction history on its row. Never billed separately.

## `includeSubawards` (type: `boolean`):

Nest each USAspending award's sub-awards on its row. Never billed separately.

## `maxTransactionsPerAward` (type: `integer`):

Cap on the nested transaction list carried by each USAspending award row. The default of 50 covers most awards; raise it when you need a full modification history, or set 0 to skip the transaction fetch entirely.

## `maxSubawardsPerAward` (type: `integer`):

Cap on the nested sub-award list carried by each USAspending award row. The default of 50 is enough for most prime awards; raise it for a large multi-tier contract, or set 0 to skip the sub-award fetch entirely.

## `includeSummary` (type: `boolean`):

Add free `summary` and `facet` rows: how many records each source matched in total, USAspending's award counts by category and its top ten agencies, recipients and NAICS codes by obligated dollars, and Grants.gov's own agency, category, eligibility and instrument facets. Never charged.

## `includeRawDescription` (type: `boolean`):

Keep the untouched HTML of a notice description in `descriptionHtml` alongside the plain-text `description`. Off by default because it is large.

## `incremental` (type: `boolean`):

Skip records this Actor has already returned, using a key-value store that outlives the run. Turns a daily job into a few new rows instead of a re-scrape. Note that ID de-duplication also suppresses a record that has since been *amended* — for modification tracking, run with this off and a rolling `dateFrom` window instead.

## `stateStoreName` (type: `string`):

Which named key-value store holds the incremental cursor. Use different names for different saved searches so they do not hide each other's records.

## `maxConcurrency` (type: `integer`):

How many sources and detail fetches run at once. The Senate LDA is always strictly serial, whatever this is set to, because its published limit is 15 requests a minute.

## `maxRunSecs` (type: `integer`):

Stop fetching after this many seconds and keep everything already returned. USAspending queries have taken up to 15 seconds each, so raise this for large runs.

## `proxyConfiguration` (type: `object`):

All four APIs answered from Apify's datacenter proxy and from no proxy at all in testing, so the cheap datacenter pool is the default and a cleared field still works.

## Actor input object example

```json
{
  "sources": [
    "grants",
    "awards"
  ],
  "keywords": [
    "cybersecurity"
  ],
  "grantStatuses": [
    "posted",
    "forecasted"
  ],
  "awardTypes": [
    "contracts"
  ],
  "maxResults": 25,
  "dateFrom": "",
  "dateTo": "",
  "agencies": [],
  "states": [],
  "naicsCodes": [],
  "pscCodes": [],
  "setAsides": [],
  "noticeTypes": [],
  "recipients": [],
  "lobbyingClients": [],
  "lobbyingRegistrants": [],
  "lobbyingIssues": [],
  "activeOnly": true,
  "fundingCategories": [],
  "eligibilities": [],
  "fundingInstruments": [],
  "alnCodes": [],
  "lobbyingLobbyists": [],
  "filingTypes": [],
  "includeDetails": true,
  "includeDescriptions": false,
  "includeTransactions": false,
  "includeSubawards": false,
  "maxTransactionsPerAward": 50,
  "maxSubawardsPerAward": 50,
  "includeSummary": true,
  "includeRawDescription": false,
  "incremental": false,
  "stateStoreName": "federal-contracts-grants-state",
  "maxConcurrency": 4,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per opportunity, award or lobbying filing, in one schema across all four sources, plus free summary and facet rows. Delivered as JSON items in the default dataset.

# 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 = {
    "sources": [
        "grants",
        "awards"
    ],
    "keywords": [
        "cybersecurity"
    ],
    "grantStatuses": [
        "posted",
        "forecasted"
    ],
    "awardTypes": [
        "contracts"
    ],
    "maxResults": 25,
    "includeDetails": true,
    "includeSummary": true,
    "incremental": false,
    "stateStoreName": "federal-contracts-grants-state",
    "maxConcurrency": 4,
    "maxRunSecs": 240,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("insight.solutions/federal-contracts-grants-api").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 = {
    "sources": [
        "grants",
        "awards",
    ],
    "keywords": ["cybersecurity"],
    "grantStatuses": [
        "posted",
        "forecasted",
    ],
    "awardTypes": ["contracts"],
    "maxResults": 25,
    "includeDetails": True,
    "includeSummary": True,
    "incremental": False,
    "stateStoreName": "federal-contracts-grants-state",
    "maxConcurrency": 4,
    "maxRunSecs": 240,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("insight.solutions/federal-contracts-grants-api").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 '{
  "sources": [
    "grants",
    "awards"
  ],
  "keywords": [
    "cybersecurity"
  ],
  "grantStatuses": [
    "posted",
    "forecasted"
  ],
  "awardTypes": [
    "contracts"
  ],
  "maxResults": 25,
  "includeDetails": true,
  "includeSummary": true,
  "incremental": false,
  "stateStoreName": "federal-contracts-grants-state",
  "maxConcurrency": 4,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call insight.solutions/federal-contracts-grants-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,insight.solutions/federal-contracts-grants-api"
        }
    }
}
```

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/fLN5iK8K84aRQiI20/builds/iE6u9D1m6iEuL7gfd/openapi.json
