Call contract search directly from a script or server instead of through the web app. Requires a Pro subscription.
Beta
Getting a token
- Go to your profile → API Access.
- Click Generate token.
- Copy it — it’s shown once and can’t be retrieved again.
The token reads search as you. Treat it like a password: keep it on a server or in a secrets store, never in a browser or a public repo. If one was ever sent over plain http://, regenerate it.
Making a request
Send the token as a bearer token against GET /api/v1/posts:
curl -H "Authorization: Bearer crk_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
"https://contractradar.io/api/v1/posts?q=electrical+wiring&state=TX&pageSize=10"Query parameters
All optional.
| Parameter | Type | Notes |
|---|---|---|
q | string | Keyword, matched semantically. Truncated to 200 characters; 400 above 2000. |
state | string, repeatable | Two-letter code, e.g. state=TX&state=NM. |
page | integer | Default 1. Clamped to a minimum of 1. |
pageSize | integer | Default 20. Clamped to 1–100. |
postType | string | Contract or Subcontract. |
coverageType | string, repeatable | Federal, State, City, County, or Regional. |
sort | string | relevance, posted_desc, posted_asc, deadline_asc, deadline_desc, name_asc, or name_desc. relevance needs q. |
postedAfter / postedBefore / deadlineAfter / deadlineBefore | date | yyyy-MM-dd, or the literal today. Nothing else. |
tag | string, repeatable | A Key:Value pair, e.g. tag=Set-Aside:8A. Repeat it to filter on several values. |
Only sort and the date parameters reject a bad value with a 400. An unrecognised postType, coverageType, state or tag is silently ignored — the filter just doesn’t apply, so a typo looks like too many results rather than an error.
Response shape
{
"items": [
{
"id": "8f14e45f-ceea-467e-bd3e-8f1f4c0e1234",
"externalId": "SAM-2026-00123",
"title": "Electrical wiring upgrade — Building 4",
"agency": "General Services Administration",
"placeOfPerformanceState": "TX",
"postedDate": "2026-09-10T00:00:00Z",
"responseDeadline": "2026-10-01T00:00:00Z",
"postType": "Contract",
"contractSource": "SamGov",
"contractSourceShortLabel": "Fed",
"contractSourceFullLabel": "Federal Contract",
"contractSourceAbbreviation": "FED",
"contractSourcePortalName": "SAM.gov",
"description": "Upgrade of electrical distribution systems...",
"link": "https://sam.gov/opp/abc123/view",
"linksToListingPageOnly": false,
"tags": [{ "key": "Set-Aside", "value": "WOSB" }]
}
],
"totalCount": 42,
"totalPages": 3,
"page": 1,
"pageSize": 20,
"totalIsCapped": false
}tags is always an array, never null. postType and contractSource serialize as strings, not integers.
| Field | Notes |
|---|---|
id | The ContractRadar post ID. |
externalId | The source portal’s own solicitation ID. |
title | Contract title. |
agency | Posting agency, or null. |
placeOfPerformanceState | Two-letter state code, or null. |
postedDate | ISO 8601 UTC. |
responseDeadline | ISO 8601 UTC, or null when the source gives none. |
postType | Contract or Subcontract. |
contractSource | The source pipeline, e.g. SamGov. |
contractSourceShortLabel / contractSourceFullLabel / contractSourceAbbreviation | Display forms of contractSource — short label, longer display label, and a ≤3-char badge code. |
contractSourcePortalName | The portal’s brand name, e.g. SAM.gov. |
description | Free text, or null. |
link | The original posting, or a portal listing page — see linksToListingPageOnly. |
linksToListingPageOnly | True when the portal has no per-solicitation deep link, so link points at a search page. |
tags | Pipeline-specific { key, value } pairs — set-asides, commodity codes, and similar. |
totalCount | Total matching results, or the cap when totalIsCapped is true. |
totalPages | Total pages at the requested pageSize. |
page / pageSize | The resolved (clamped) values used for this response. |
totalIsCapped | True when a keyword search hit the candidate cap, so totalCount is that cap. |
Errors
| Status | Meaning |
|---|---|
400 | A parameter failed validation — a bad date, an unrecognised sort, or q over 2000 characters. |
401 | The token is missing, malformed, or revoked. |
429 | Rate limited. Honour the Retry-After header (seconds). |
If your subscription lapses the token keeps working, falling back to the free daily search quota. Generate, regenerate, or revoke it from your profile.