Skip to content

Search Window

On Developer and Pro there is no search window: /opportunities/search and /awards/search reach every SAM.gov notice and award notice we hold. The free trial searches the last 90 days.

Plan /opportunities/search, /awards/search Earliest searchable date
Free Trial 90 days ~3 months ago
Developer no window everything we hold
Pro no window everything we hold

Other datasets start where our data starts, on every plan. Contracts and subawards begin at October 2024 (FY2025), and so do the FPDS totals on company routes. Contract and subaward searches carry a window block too, and it shows that data floor, not a plan limit. The remaining datasets have no date limit.

Lookups by ID are never limited. /opportunities/{notice_id} and /awards/{award_number} return the record regardless of age, on every plan. On the free trial a search by solicitation_number is still a search, so it finds notices from the last 90 days only; fetch by notice_id to reach older ones.

What happens on the free trial when you pass an older date

Date filters older than 90 days are clamped to the window floor. No 400: the response carries a top-level window block that tells you exactly what happened, so you can show users why the result set is bounded.

Concrete example, free trial on 2026-09-14:

# request:
GET /api/v1/opportunities/search?naics=541511&posted_after=2024-01-01&limit=20

# response (200 OK):
{
  "data": [ ... 20 rows, all with posted_date >= 2026-06-16 ... ],
  "pagination": { "limit": 20, "offset": 0, "total": ..., "has_next": true },
  "filters_applied": {
    "naics": "541511",
    "posted_after": "2026-06-16"
  },
  "window": {
    "plan_window_days": 90,
    "earliest_searchable": "2026-06-16",
    "clamped": true,
    "date_from_requested": "2024-01-01",
    "reason": "Requested start date predates your plan window (last 90 days). Clamped to 2026-06-16. Paid plans have no search window: https://govconapi.com/pricing"
  }
}

The window block is always present on both search endpoints. On paid plans it reads "plan_window_days": null, "earliest_searchable": null, "clamped": false. On the free trial, clamped: true means results were bounded by the window: either you sent no date and the floor was injected, or you sent an older date and it was clamped up. When clamping is due to your explicit date, the block also includes date_from_requested so you can tell the two cases apart. Inspect your window directly via GET /api/v1/me (fields historical_window_days and historical_earliest_allowed, both null on paid plans).

Common questions

How can I tell the difference between search and lookup? Search endpoints are URL-stem (/opportunities/search) and return paginated lists. Lookup endpoints have an identifier in the path (/opportunities/<notice_id>, /companies/<uei>) and return a single record or that record's relations.

I have a notice_id from 2018, can I still fetch it? Yes, on every plan. GET /api/v1/opportunities/<notice_id> returns it.

I want every award for one specific UEI going back years. Use GET /api/v1/companies/<uei>/awards (Pro). It is a lookup, so no window applies.

Why does has_next: true still appear on the free trial? The window injects a floor into the query; has_next reflects whether there are more matching rows within the window. To page further, raise offset normally.

I need contracts or subawards from before October 2024. That is a data coverage floor, not a plan limit: coverage begins October 2024 and no plan reaches further back, so the answer is a backfill conversation rather than an upgrade. Email [email protected].

How far back does /subawards/* go? Coverage today is FY2025 + FY2026 (every FFATA subaward from October 2024 onward). The window.earliest_searchable field on subaward responses shows that data floor (2024-10-01), so a customer never sees a date in the response that returns zero rows. Older date filters are clamped to it, the window block surfaces what happened, and single-record lookup by subaward_sam_report_id is not gated. Records before October 2024 are not in the API today on any plan.

Separate rule for /opportunities/delta

/opportunities/delta is a sync endpoint ("what changed since I last pulled"), not a backfill tool. It has its own cap of 60 days on every plan, independent of the search window. A since value older than 60 days is silently clamped; the sync block in the response surfaces since_requested and a clamp_reason when this happens. For an initial backfill, use /opportunities/search with date filters; for ongoing sync, call /delta with a recent since (last hour / last day / last week is typical).

A REST API and MCP server for U.S. federal procurement data.

Get a free key, emailed instantly, or follow the quickstart.

Found something wrong, missing or confusing on this page?

Press Ctrl + Enter to send a note. Highlight text first and it travels with your note.