Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the SAM.gov API page →
Government & Tenders

SAM.gov API & Scraper

The SAM.gov API returns US federal contract opportunities as clean JSON, with no api_key and no registration.

3 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

The primary search endpoint returns opportunities with id, url, title, solicitation_number, the notice type (sources sought, solicitation, special notice, award), a description preview, published_at and modified_at, the response_deadline with its local time and timezone, the is_active and is_cancelled flags, the buying office as department, office, office_code, office_location and the full org chain, the awardee where one exists, and a relevance_score — plus total_matches and an offset for paging. opportunity expands one notice into the full solicitation body, set_aside, naics_codes, product_service_code, place_of_performance and the published contacts with name, email and phone. attachments lists the notice's documents with name, kind, mime type, size and URL. One ReefAPI key, one shared credit pool, the standard envelope.

Reference

The parameters that actually change your result count

Four parameters move the numbers here, and one of them behaves differently from the other three because it is applied after fetching rather than upstream. Knowing which is which stops you from reading total_matches as a filtered count. All figures measured on 2026-08-27.

ParameterWhat it doesMeasured effect
q with phrase true (the default)Quotes your term so it matches as one phrase'web scraping' returned total_matches 11, and query_sent echoed the quoted form
phrase falseEvery word anywhere in the notice, in any orderThe same query returned total_matches 76
active_only trueApplied upstream. Removes anything past its deadline or archived11 matches became 1
published_within_daysApplied AFTER fetching, so total_matches stays unfiltered'data extraction' held total_matches 485 while filtered_out reported 91 rows removed
notice_typesNine codes. An unknown one is rejected, not ignored['zz'] returned INVALID_PARAM listing p, k, r, o, g, s, i, a, u
offset plus limitHard ceiling of 10,000, the index's own maxAllowedRecordsoffset 9999 with limit 2 returned INVALID_PARAM
sort newestApplied locally after fetching, because upstream date sorting is brokenmeta echoes upstream_sort '-modifiedDate' and upstream_date_filter_supported false
idThe 32-hex notice id, which is NOT the solicitation numberffabe21b876649d2a1669edb4858cd48 for solicitation W91ZLK-26-A-0123D
description_preview250 characters on search rows onlyThe same notice's full body from `opportunity` ran 3,642 characters
NAICS and PSCOnly on `opportunity`, never on a search rownaics_codes ['518210'] (an array of 6-digit strings), product_service_code 'B506' (a single 4-character code)

Two notices can carry near-identical solicitation numbers and be different records. A single search returned W91Zlk-26-A-01234D as a Sources Sought and W91ZLK-26-A-0123D as a Special Notice, same buying office, same project. The 32-hex id is the only safe key: use it for deduplication and for every follow-up call.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/sam-gov/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "q": "web scraping",
    "limit": 5
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "sam-gov",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 385.4,
    "record_count": 5,
    "bytes": 20874,
    "cache_hit": false,
    "stop_reason": "limit_reached",
    "method": "keyless_public_json_api_bare_dc_curl_cffi",
    "sort_applied": "newest",
    "upstream_sort": "-modifiedDate",
    "upstream_date_filter_supported": false,
    "active_only": false,
    "notice_types": null,
    "max_allowed_records": 10000
  },
  "data": {
    "opportunities": [
      {
        "id": "665b0e5ea7794aa78e2bc60b45d19d0b",
        "url": "https://sam.gov/opp/665b0e5ea7794aa78e2bc60b45d19d0b/view",
        "title": "Syndicated POINT OF SALE (POS) DATA PLATFORM (COS)",
        "solicitation_number": "W91Zlk-26-A-01234D",
        "notice_type": "Sources Sought",
        "notice_type_code": "r",
        "description_preview": "DECA‑26 – Syndicated Data Core Services\n\nProject Number:\n W91ZLK‑26‑R‑SDCS\n\nAOS Number:\n W9128Z‑25‑S‑A002\n\nPSC:\n B506 – Special Studies/Anal",
        "published_at": "[redacted-phone]T19:23:01Z",
        "modified_at": "[redacted-phone]T19:23:01Z",
        "response_deadline": "[redacted-phone]T15:00:00Z",
        "response_deadline_local": "[redacted-phone]T11:00:00-04:00",
        "response_timezone": "America/New_York",
        "is_active": true,
        "is_cancelled": false,
        "buyer_name": "W6QK ACC-APG DIR",
        "buyer": {
          "department": "DEPT OF DEFENSE",
          "office": "W6QK ACC-APG DIR",
          "office_code": "W91ZLK",
          "office_location": "ABER PROV GRD, MD, USA",
          "chain": [
            "[trimmed-depth]",
            "[trimmed-depth]",
            "[trimmed-depth]"
          ]
        },
        "awardee": null,
        "relevance_score": 52,
        "revisions": 0
      },
      {
        "id": "ffabe21b876649d2a1669edb4858cd48",
        "url": "https://sam.gov/opp/ffabe21b876649d2a1669edb4858cd48/view",
        "title": "Syndicated Point of Sale (POS) Data Platform (COS)",
        "solicitation_number": "W91ZLK-26-A-0123D",
        "notice_type": "Special Notice",
        "notice_type_code": "s",
        "description_preview": "DECA‑26 – Syndicated Data Core Services\n\nProject Number:\nW91ZLK‑26‑R‑SDCS\n\nAOS Number:\nW9128Z‑25‑S‑A002\n\nPSC:\nB506 – Special Studies/Analysis – Da",
        "published_at": "[redacted-phone]T15:58:14Z",
        "modified_at": "[redacted-phone]T05:07:15Z",
        "response_deadline": "[redacted-phone]T17:00:00Z",
        "response_deadline_local": "[redacted-phone]T13:00:00-04:00",
        "response_timezone": "America/New_York",
        "is_active": false,
        "is_cancelled": false,
        "buyer_name": "W6QK ACC-APG DIR",
        "buyer": {
          "department": "DEPT OF DEFENSE",
          "office": "W6QK ACC-APG DIR",
          "office_code": "W91ZLK",
          "office_location": "ABER PROV GRD, MD, USA",
          "chain": [
            "[trimmed-depth]",
            "[trimmed-depth]",
            "[trimmed-depth]"
          ]
        },
        "awardee": null,
        "relevance_score": 54,
        "revisions": 2
      },
      {
        "id": "1f316d9815db41ebb3f6451bfafc9cd8",
        "url": "https://sam.gov/opp/1f316d9815db41ebb3f6451bfafc9cd8/view",
        "title": "hCaptcha Enterprise and Premium Support",
        "solicitation_number": "SS-FIN-26-027",
        "notice_type": "Special Notice",
        "notice_type_code": "s",
        "description_preview": "The Treasury Common Services Center (TCSC) on behalf of the Financial Crimes Enforcement Network (FinCEN) intends to make an award on a sole source basis to Intuition Machines, Inc.; 1065 SW 8th Street #704; Miami, FL 33130 for the purchase of exi",
        "published_at": "[redacted-phone]T13:54:03Z",
        "modified_at": "[redacted-phone]T03:55:44Z",
        "response_deadline": "[redacted-phone]T17:00:00Z",
        "response_deadline_local": "[redacted-phone]T13:00:00-04:00",
        "response_timezone": "America/New_York",
        "is_active": false,
        "is_cancelled": false,
        "buyer_name": "TREASURY, DEPARTMENT OF THE",
        "buyer": {
          "department": "TREASURY, DEPARTMENT OF THE",
          "office": "TREASURY, DEPARTMENT OF THE",
          "office_code": "2000",
          "office_location": "US",
          "chain": [
            "[trimmed-depth]"
          ]
        },
        "awardee": null,
        "relevance_score": 58,
        "revisions": 0
      }
    ],
    "total_matches": 11,
    "returned": 5,
    "offset": 0,
    "query_sent": "\"web scraping\"",
    "phrase": true,
    "description_truncated": true,
    "description_preview_chars": 250,
    "source": "sam.gov"
  }
}
Actions

What the SAM.gov API does

ActionDescriptionConcrete use caseKey params
searchSearch every US federal contract opportunity by phrase — the demand side of a $700bn/year buyer. Each hit carries the response deadline, the buying department and office, the notice type (is this a heads-up, a live RFP, or an award?) and a 250-character preview of the solicitation text. Pair with `active_only=true` for things you can still bid on, or with notice type 'a' to see who won what.GovCon business-development teams call search to search every US federal contract opportunity by phrase.q, phrase, active_only, notice_types, published_within_days, ...
opportunityOne notice in full: the COMPLETE solicitation text (search only ever returns the first 250 characters), the response deadline with its timezone, the set-aside type, NAICS and PSC classification, place of performance, and the contracting officer's name, e-mail and phone as published on the notice.Bid and capture teams call opportunity to get one notice in full.id
attachmentsThe documents attached to a notice — the statement of work, the pricing sheet, the Q&A, the amendment. Returns each file's name, MIME type, size, posting date and a direct public download URL. The real requirement usually lives in these PDFs, not in the notice body.Public-sector analysts call attachments to get the documents attached to a notice.id
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/sam-gov/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"q":"web scraping","limit":5}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.sam-gov.search with {"q":"web scraping","limit":5}.
Use cases

Who uses this API and why

  • GovCon business-development teams call search to catch new sources-sought notices and solicitations in their space as they publish.
  • Bid/no-bid workflows use opportunity to read the full solicitation body, the set-aside type and the response deadline before committing.
  • Capture teams use the contacts published on an opportunity to reach the contracting office directly.
  • Competitive analysts follow awardee across award notices to see who is winning work under a given product-service code.
FAQ

Questions developers ask before integrating

What is the difference between the notice id and the solicitation number?

The id is a 32-character hex string minted by the system and unique per notice, such as ffabe21b876649d2a1669edb4858cd48. It is what `opportunity` and `attachments` take, and it is what appears in the sam.gov/opp/<id>/view URL, so pasting that whole URL works too. The solicitation number is the buying office's own reference, and it is neither unique nor consistently formatted: one search returned W91Zlk-26-A-01234D and W91ZLK-26-A-0123D as two separate notices for the same project. Key on the id.

Why is my exact-phrase search returning so few results?

Because phrase matching is the default and it is doing its job. 'web scraping' returned 11 notices as a quoted phrase and 76 with phrase false, which loosens to every word anywhere in any order. The response echoes back exactly what was sent upstream in query_sent, so you can always confirm which mode you got. Start with the phrase for precision, and switch to phrase false when you are casting a wide net over a category rather than hunting one term.

Why does total_matches stay the same when I set published_within_days?

Because that filter runs here, after the rows arrive, rather than upstream. A search for 'data extraction' with published_within_days 90 kept total_matches at 485, the unfiltered upstream count, and reported filtered_out 91 for the rows removed locally. The practical consequence: the parameter narrows what you receive but does not reduce what was fetched, so treat total_matches as the size of the unfiltered match set and use returned plus filtered_out to understand your page. active_only is the opposite case; it runs upstream and cut 11 matches to 1.

Which notice-type codes should I ask for?

Nine exist and they answer different questions. 'r' Sources Sought means the buyer is still asking who can do this, which is the cheapest door for a new vendor. 'p' Presolicitation announces an upcoming requirement. 'o' Solicitation and 'k' Combined Synopsis/Solicitation are the live RFPs you can bid on. 's' Special Notice covers industry days and RFIs. 'a' Award Notice tells you who won and therefore who the incumbent is. 'u' Justification and Approval explains a sole-source award, 'i' covers bundling intent, 'g' surplus property sales. An unrecognized code is rejected with the full list in the error rather than being silently dropped.

How are deadlines and timezones represented?

Three fields that agree with each other. response_deadline is UTC with a Z suffix, response_deadline_local is the same instant carried with its offset, and response_timezone is an IANA name such as America/New_York. A deadline measured as 2026-08-18T15:00:00Z came back locally as 2026-08-18T11:00:00-04:00. Award notices return all three as null, on 3 of 3 measured, because an award has no response deadline. archive_date is a bare date with no time at all.

What tells me whether a notice is still live?

Three independent booleans, and they are not redundant. is_active is the one to filter on for biddability. is_archived says the record has aged out of the active index, and it pairs with archive_date. is_cancelled says the buyer withdrew the requirement, which is different from letting it expire. One measured notice returned is_active false with is_archived true and archive_date 2026-08-18, alongside revision '2' (a string, not a number) which counts amendments. The search row for the same notice reported revisions 2 as an integer, so watch the type when you compare them.

How do I reach the contracting officer?

The `opportunity` action returns a contacts[] array as published on the notice, typed as primary and secondary. A measured notice returned a primary contact with a name, a .mil e-mail address and a phone number as bare digits with no formatting or extension separator, plus a secondary contact whose phone was null. title was null on both. Two contacts on one notice is common and the primary is the one to write to; the secondary is usually the specialist who will actually answer.

How do I get the actual statement of work?

Call `attachments` with the same notice id. It returned two files for a measured notice, each with a name, kind, size_bytes, posted_at and a direct public download URL under the sam.gov file-resource path, with access 'public'. The real requirement usually lives in those PDFs rather than in the body. One shape to expect: the `mime` field carries a file extension such as '.pdf' rather than a MIME type, so branch on the extension or on the name, not on a media type string.

What is the SAM.gov API?

SAM.gov API is a ReefAPI endpoint group for us federal contract opportunities, response deadlines and award notices. It returns live JSON through POST requests under /sam-gov/v1.

Is the SAM.gov API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. SAM.gov calls use the same shared credit balance as every other ReefAPI engine.

Do I need a SAM.gov login or account?

No login to SAM.gov is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the SAM.gov data?

The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the SAM.gov API use?

SAM.gov actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call SAM.gov from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call sam-gov actions with the same key, credit pool and JSON envelope used by normal REST requests.

docs / sam-gov

SAM.gov

US federal contract opportunities, response deadlines and award notices.

base /sam-gov/v13 endpoints
post/sam-gov/v1/opportunity1 credit

One notice in full: the COMPLETE solicitation text (search only ever returns the first 250 characters), the response deadline with its timezone, the set-aside type, NAICS and PSC classification, place of performance, and the contracting officer's name, e-mail and phone as published on the notice.

ParameterAllowed / rangeDescription
idrequiredThe 32-character SAM.gov notice id, as returned by `search` in `id`. A full https://sam.gov/opp/<id>/view URL also works — the id is read out of it.
Try in playground →
post/sam-gov/v1/attachments1 credit

The documents attached to a notice — the statement of work, the pricing sheet, the Q&A, the amendment. Returns each file's name, MIME type, size, posting date and a direct public download URL. The real requirement usually lives in these PDFs, not in the notice body.

ParameterAllowed / rangeDescription
idrequiredThe 32-character SAM.gov notice id, as returned by `search` in `id`. A full https://sam.gov/opp/<id>/view URL also works — the id is read out of it.
Try in playground →