Overview
The GovContractScout API gives you programmatic access to one normalized feed of U.S. government contract opportunities, aggregated from 50+ fragmented state, local, and federal portals into a single clean schema (title, agency, NAICS codes, extracted keywords, due dates, estimated value, and days left). It also exposes our matching algorithm so you can score opportunities against a contractor profile. Access is self-serve: sign up, create a key, and start calling the API immediately. See Authentication below.
Base URL
https://www.govcontractscout.com/api/v1Available Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/contracts | Search and filter contracts |
| GET | /v1/contracts/:id | Get contract details |
| GET | /v1/states | List states with contract counts |
| GET | /v1/naics | List NAICS codes with contract counts |
| POST | /v1/match | Score a contract against a profile |
| POST | /v1/match/batch | Score multiple contracts (max 50) |
| POST | /v1/match/search | Search contracts with match scoring |
| GET | /v1/usage | Check your API usage |
Authentication
All API requests require a valid API key sent via the Authorization header as a Bearer token.
curl -X GET "https://www.govcontractscout.com/api/v1/contracts" \
-H "Authorization: Bearer gcs_live_xxxxxxxxxxxxxxxxxxxx"Key Types
| Prefix | Environment | Data |
|---|---|---|
| gcs_live_ | Production | Real contracts |
Getting a Key
Keys are self-serve. Create one from your dashboard — no request, no approval, no email. Use a free tier to evaluate the data first.
- Sign in and open API Keys
- Create a key and accept the API Terms
- Copy the key immediately — it is only shown once
Rate Limits
Requests are rate-limited based on your tier and applied per API key. See pricing for the monthly allowances on each paid tier.
| Tier | Requests / Minute | Requests / Month |
|---|---|---|
| Free | 30 | 100 |
| Starter | 60 | 10,000 |
| Growth | 300 | 50,000 |
New free keys get 100 requests/month to evaluate the API — enough to test the shape of the data, too small to harvest it. Paid tiers are self-serve: check out and your key is issued or upgraded instantly. Email api-support@govcontractscout.com if you have questions about an existing key.
Response Headers
Every API response includes rate limit headers so you can track your usage programmatically:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1709500000| Parameter | Type | Required | Description |
|---|---|---|---|
| X-RateLimit-Limit | integer | No | Max requests per minute for your plan |
| X-RateLimit-Remaining | integer | No | Requests remaining in current window |
| X-RateLimit-Reset | integer | No | Unix timestamp when the window resets |
Handling 429 Responses
When you exceed the rate limit, the API returns a 429 status with a retry_after value in seconds:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry after 45 seconds.",
"retry_after": 45
}
}Pricing
Choose the tier that matches your integration volume. Checkout is instant — your key is issued or upgraded automatically. All tiers are a standalone API — separate from a GovContractScout Pro plan — and allow commercial use, but not reselling or redistributing the dataset (see the API terms).
Free
$0/mo
Evaluate the API. No credit card required.
- 100 requests / month
- 30 requests / minute
Starter
$99/mo
For a production integration.
- 10,000 requests / month
- 60 requests / minute
- Instant access on checkout
Growth
$199/mo
Higher volume, higher rate limit.
- 50,000 requests / month
- 300 requests / minute
- Instant access on checkout
Need more than 50k requests/month, or want an MCP / agent integration? Talk to us about an enterprise plan.
Error Handling
The API uses standard HTTP status codes and returns consistent error objects. All errors follow this format:
{
"error": {
"code": "error_code",
"message": "Human-readable description",
"param": "field_name",
"doc_url": "https://scout.govbidportals.com/docs/api#errors/error_code"
}
}Error Codes
| Code | HTTP Status | Description |
|---|---|---|
| invalid_api_key | 401 | API key is missing, invalid, or revoked |
| rate_limit_exceeded | 429 | Too many requests, retry after the specified delay |
| monthly_limit_exceeded | 429 | Monthly request quota reached; resets at the start of next month or upgrade your plan |
| invalid_parameter | 400 | A query parameter or body field has an invalid value |
| missing_parameter | 400 | A required parameter was not provided |
| resource_not_found | 404 | The requested contract or resource does not exist |
| payload_too_large | 413 | Request body too large (max 64 KB) — thrown by the match, batch, and search endpoints |
| validation_error | 422 | Request body failed validation (details array included) |
| usage_check_failed | 503 | Could not verify request usage right now — fail-closed, retry shortly |
| server_error | 500 | Internal server error |
Validation Errors
When request body validation fails, the response includes a details array with per-field errors:
{
"error": {
"code": "validation_error",
"message": "Request body validation failed",
"details": [
{ "field": "profile.naics_codes", "message": "Must be an array of strings" },
{ "field": "profile.service_areas", "message": "Required field missing" }
],
"doc_url": "https://docs.govcontractscout.com/errors/validation_error"
}
}List Contracts
/v1/contractsSearch and filter the contract database. Returns paginated results without the full description field (use the detail endpoint for that).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| state | string | No | Single state filter, 2-letter code (e.g., "CA") |
| states | string | No | Comma-separated state codes (e.g., "CA,TX,NY") |
| naics | string | No | NAICS code or prefix (e.g., "541512" or "541") |
| naics_codes | string | No | Comma-separated exact NAICS codes |
| min_value | integer | No | Minimum estimated value in dollars |
| max_value | integer | No | Maximum estimated value in dollars |
| keyword | string | No | Keyword search on contract title |
| agency | string | No | Agency name, partial match (case-insensitive) |
| due_after | string | No | ISO 8601 date, contracts due after this date |
| due_before | string | No | ISO 8601 date, contracts due before this date |
| posted_after | string | No | ISO 8601 date, contracts posted after this date |
| status | string | No | "active" (default), "expired", or "all" |
| sort | string | No | "due_date", "posted_date", "value", or "title" |
| order | string | No | "asc" or "desc" (default) |
| page | integer | No | Page number (default: 1, max: 20). Use filters to narrow to specific contracts rather than paging deep. |
| per_page | integer | No | Results per page (default: 20, max: 100) |
Example
curl -X GET "https://www.govcontractscout.com/api/v1/contracts?states=CA,TX&naics=541512&min_value=100000&status=active" \
-H "Authorization: Bearer gcs_live_xxxx"Pagination
The list endpoint returns up to 100 contracts per page. To pull a set of contracts, page through with per_page=100 and increment page (max 20). Do NOT fire one request per contract in parallel - that burns your rate limit and returns 429s. One page of 100 is one request, not 100.
import time
import requests
API = "https://www.govcontractscout.com/api/v1/contracts"
HEADERS = {"Authorization": "Bearer gcs_live_xxxx"}
all_contracts = []
page = 1
while page <= 20:
r = requests.get(
API,
headers=HEADERS,
params={"per_page": 100, "page": page, "status": "active"},
)
if r.status_code == 429:
# Respect the rate limit: wait for the window to reset, then retry.
retry_after = int(r.headers.get("Retry-After", "60"))
time.sleep(retry_after)
continue
r.raise_for_status()
data = r.json()
all_contracts.extend(data["data"])
if page >= data["meta"]["total_pages"]:
break
page += 1
time.sleep(1) # stay well under the per-minute rate limit
print(f"Fetched {len(all_contracts)} contracts")Response
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "IT Infrastructure Modernization",
"contract_number": "RFP-2026-0142",
"state": "CA",
"agency": "California Department of Technology",
"location": "Sacramento, CA",
"posting_date": "2026-02-15T00:00:00Z",
"due_date": "2026-03-30T17:00:00Z",
"estimated_value": 500000,
"naics_codes": ["541512", "541519"],
"keywords": ["cloud", "migration", "aws", "security"],
"status": "active",
"days_until_due": 27,
"has_attachments": true,
"created_at": "2026-02-15T08:30:00Z"
}
],
"meta": {
"total": 1547,
"page": 1,
"per_page": 20,
"total_pages": 78
}
}Get Contract
/v1/contracts/:idGet full details for a single contract, including the full description and updated_at timestamp.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | Yes | Contract UUID |
Example
curl -X GET "https://www.govcontractscout.com/api/v1/contracts/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer gcs_live_xxxx"Response
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "IT Infrastructure Modernization",
"contract_number": "RFP-2026-0142",
"state": "CA",
"agency": "California Department of Technology",
"location": "Sacramento, CA",
"posting_date": "2026-02-15T00:00:00Z",
"due_date": "2026-03-30T17:00:00Z",
"estimated_value": 500000,
"naics_codes": ["541512", "541519"],
"keywords": ["cloud", "migration", "aws", "security"],
"description": "The California Department of Technology (CDT) is seeking qualified vendors...",
"status": "active",
"days_until_due": 27,
"source_url": "https://caleprocure.ca.gov/event/12345",
"pdf_urls": [
"https://example.gov/scout/RFP-2026-0142-addendum1.pdf"
],
"has_attachments": true,
"created_at": "2026-02-15T08:30:00Z",
"updated_at": "2026-02-15T08:30:00Z"
}
}source_url is the original procurement-page link (e.g. the caleprocure event page) — use it to send an end user to the actual solicitation. It is returned on the detail endpoint only, on all tiers. Contracts sourced via BidNet aggregation return null here — we do not link users into third-party aggregator platforms. pdf_urls holds the solicitation document links (PDF, DOCX, XLS) for contracts where the source portal serves them publicly; it is gated to paid plans (Starter, Growth, Enterprise) — free/evaluation keys receive an empty array but still get has_attachments.
List States
/v1/statesGet a list of supported U.S. states with the number of currently active contracts in each.
Example
curl -X GET "https://www.govcontractscout.com/api/v1/states" \
-H "Authorization: Bearer gcs_live_xxxx"Response
{
"data": [
{ "code": "CA", "name": "California", "active_contracts": 2341 },
{ "code": "FL", "name": "Florida", "active_contracts": 1234 },
{ "code": "NY", "name": "New York", "active_contracts": 1543 },
{ "code": "TX", "name": "Texas", "active_contracts": 1876 }
]
}List NAICS Codes
/v1/naicsGet NAICS codes used in the contract database, with active contract counts. Optionally filter by code prefix or search by name.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| prefix | string | No | Filter by NAICS code prefix, 2-6 digits (e.g., "541") |
| search | string | No | Search by name, case-insensitive (e.g., "engineering") |
Example
curl -X GET "https://www.govcontractscout.com/api/v1/naics?prefix=541" \
-H "Authorization: Bearer gcs_live_xxxx"Response
{
"data": [
{ "code": "541330", "name": "Engineering Services", "active_contracts": 892 },
{ "code": "541512", "name": "Computer Systems Design Services", "active_contracts": 654 },
{ "code": "541519", "name": "Other Computer Related Services", "active_contracts": 432 },
{ "code": "541611", "name": "Administrative Management Consulting", "active_contracts": 387 }
]
}Score Contract
/v1/matchCalculate a match score for a single contract against your contractor profile. Uses a 5-factor algorithm: NAICS codes (30%), keywords/skills (25%), budget fit (20%), location (15%), and timeline (10%).
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| contract_id | string (UUID) | Yes | The contract to score |
| profile.naics_codes | string[] | Yes | Your NAICS codes (max 5) |
| profile.primary_skills | string[] | Yes | Your core competencies |
| profile.secondary_skills | string[] | No | Additional skills |
| profile.service_areas | string[] | Yes | States you can work in (2-letter codes) |
| profile.headquarters_state | string | Yes | Your HQ state (2-letter code) |
| profile.min_contract_value | integer | No | Minimum contract value you would bid on |
| profile.max_contract_value | integer | No | Maximum contract value you can handle |
| profile.min_days_to_deadline | integer | No | Minimum days needed to prepare a bid (default: 30) |
| profile.remote_capable | boolean | No | Can perform work remotely (default: false) |
Example
curl -X POST "https://www.govcontractscout.com/api/v1/match" \
-H "Authorization: Bearer gcs_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"contract_id": "550e8400-e29b-41d4-a716-446655440000",
"profile": {
"naics_codes": ["541512", "541519"],
"primary_skills": ["cloud migration", "aws", "devops"],
"secondary_skills": ["security", "terraform"],
"service_areas": ["CA", "NV", "OR"],
"headquarters_state": "CA",
"min_contract_value": 50000,
"max_contract_value": 1000000,
"remote_capable": true
}
}'Response
{
"data": {
"contract_id": "550e8400-e29b-41d4-a716-446655440000",
"match_score": 87,
"match_grade": "excellent",
"breakdown": {
"naics_score": 100,
"naics_weight": 0.30,
"budget_score": 100,
"budget_weight": 0.20,
"location_score": 100,
"location_weight": 0.15,
"keywords_score": 72,
"keywords_weight": 0.25,
"timeline_score": 80,
"timeline_weight": 0.10
},
"match_reasons": [
"Strong industry match - NAICS codes align perfectly",
"Contract value ($500,000) fits your budget range ($50K-$1M)",
"Located in your service area (California)",
"Your skills match: cloud, migration, aws, devops"
]
}
}Match Grades
| Grade | Score Range | Meaning |
|---|---|---|
| excellent | 80 – 100 | Strong fit, prioritize this contract |
| good | 60 – 79 | Good fit, worth reviewing |
| okay | 40 – 59 | Moderate fit, review if time permits |
| poor | 0 – 39 | Weak fit, likely skip |
Batch Score
/v1/match/batchScore multiple contracts against a profile in a single request. Maximum 50 contracts per request. Non-existent contract IDs are silently skipped.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| contract_ids | string[] (UUIDs) | Yes | Array of contract UUIDs to score (max 50) |
| profile | object | Yes | Contractor profile (same shape as /match endpoint) |
Example
curl -X POST "https://www.govcontractscout.com/api/v1/match/batch" \
-H "Authorization: Bearer gcs_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"contract_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"550e8400-e29b-41d4-a716-446655440001",
"550e8400-e29b-41d4-a716-446655440002"
],
"profile": {
"naics_codes": ["541512"],
"primary_skills": ["cloud", "aws"],
"service_areas": ["CA"],
"headquarters_state": "CA"
}
}'Response
{
"data": [
{
"contract_id": "550e8400-e29b-41d4-a716-446655440000",
"match_score": 87,
"match_grade": "excellent",
"breakdown": { ... },
"match_reasons": [ ... ]
},
{
"contract_id": "550e8400-e29b-41d4-a716-446655440001",
"match_score": 72,
"match_grade": "good",
"breakdown": { ... },
"match_reasons": [ ... ]
}
]
}Search + Match
/v1/match/searchThe power endpoint. Search contracts with filters AND score them against your profile in a single request. Results include both contract data and match details, sorted by match score by default.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| profile | object | Yes | Contractor profile (same shape as /match endpoint) |
| filters.states | string[] | No | State codes to search in |
| filters.min_value | integer | No | Minimum contract value |
| filters.max_value | integer | No | Maximum contract value |
| filters.status | string | No | "active" (default), "expired", "all" |
| min_score | integer | No | Minimum match score to include (0-100) |
| sort | string | No | "match_score" (default), "due_date", "posted_date", "value", "title" |
| order | string | No | "asc" or "desc" (default) |
| page | integer | No | Page number (default: 1, max: 20). Use filters to narrow to specific contracts rather than paging deep. |
| per_page | integer | No | Results per page (default: 20, max: 100) |
Example
curl -X POST "https://www.govcontractscout.com/api/v1/match/search" \
-H "Authorization: Bearer gcs_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"profile": {
"naics_codes": ["541512"],
"primary_skills": ["cloud", "aws"],
"service_areas": ["CA", "TX"],
"headquarters_state": "CA",
"remote_capable": true
},
"filters": {
"states": ["CA", "TX"],
"min_value": 100000,
"status": "active"
},
"min_score": 60,
"sort": "match_score",
"order": "desc",
"per_page": 10
}'Response
{
"data": [
{
"contract": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "IT Infrastructure Modernization",
"state": "CA",
"agency": "California Department of Technology",
"due_date": "2026-03-30T17:00:00Z",
"estimated_value": 500000,
"days_until_due": 27,
"status": "active"
},
"match": {
"match_score": 92,
"match_grade": "excellent",
"breakdown": {
"naics_score": 100, "naics_weight": 0.30,
"budget_score": 100, "budget_weight": 0.20,
"location_score": 100, "location_weight": 0.15,
"keywords_score": 80, "keywords_weight": 0.25,
"timeline_score": 80, "timeline_weight": 0.10
},
"match_reasons": [
"Strong industry match",
"Contract value fits budget",
"Located in service area"
]
}
}
],
"meta": {
"total": 47,
"page": 1,
"per_page": 10,
"total_pages": 5,
"filters_applied": {
"states": ["CA", "TX"],
"min_value": 100000,
"min_score": 60
}
}
}Win Likelihood
/v1/win-likelihoodEstimate the probability (0-100) that your company profile wins a specific contract, based on the historical award archetype that wins in its category plus incumbent/recompete intel. A paid-tier (Starter+) feature.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| contract_id | string (uuid) | Yes | The contract to score |
| profile | object | Yes | Contractor profile (same base shape as /match) |
| profile.company_name | string | No | Your company name - used to detect if you are the incumbent on a recompete |
| profile.past_award_amount | number | No | Your typical past award size in USD (compared against the incumbent's last award) |
| profile.past_agencies | string[] | No | Agencies you have worked with - matched against the awarding agency |
| profile.years_in_business | number | No | Years in business (track-record signal) |
| profile.past_awards_count | number | No | Number of past awards (track-record signal) |
Response
{
"data": {
"contract_id": "43308678-...",
"win_likelihood": 52,
"grade": "okay",
"reasons": [
"Best-fit archetype: Transportation & Logistics (791 past awards, typically $125-$6,329,308).",
"You are the incumbent (MUSE TRUCKING, INC.) on this recompete - incumbents hold a strong edge on renewals.",
"Your past awards ($300,000) are comparable to the incumbent's last award ($300,000) - a credible challenger."
],
"archetype": {
"key": "it-software-services",
"name": "IT & Software Services",
"size_band": "micro",
"typical_amount_min": 0,
"typical_amount_max": 7468956,
"typical_agency_types": ["health", "technology", "state-local-agency"],
"states": ["NY", "TX", "NH"],
"award_count": 1636
},
"intel": {
"likely_incumbent": "MUSE TRUCKING, INC.",
"last_award_amount": 300000,
"awarding_agency": "Department of Agriculture",
"is_recompete": true,
"competitor_count": 13,
"incumbent_matches_user": true
},
"breakdown": { }
}
}Intel signals (the non-obvious part): you are the incumbent (+14), a challenger on a recompete (-10, +6 if your past-award size is comparable), thin vs crowded competition (+/-6), and past agency relationships (+5).
Archetypes
/v1/archetypesList the winning-business archetypes derived from historical government contract awards. Each describes who wins what - the derived-data layer. A paid-tier (Starter+) feature.
Response
{
"data": [
{
"key": "it-software-services",
"name": "IT & Software Services",
"category": "Technology",
"sector": ["54", "51"],
"description": "Software development, IT systems design, data processing... wins technology solicitations."
}
],
"meta": { "count": 16 }
}API Usage
/v1/usageCheck your current API usage statistics, including requests used, remaining quota, and rate limit for the current billing period.
Example
curl -X GET "https://www.govcontractscout.com/api/v1/usage" \
-H "Authorization: Bearer gcs_live_xxxx"Response
{
"data": {
"plan": "starter",
"period_start": "2026-03-01",
"period_end": "2026-03-31",
"requests_used": 4521,
"requests_limit": 10000,
"requests_remaining": 5479,
"rate_limit_per_minute": 60
}
}Agent / MCP
The GovContractScout data and derived insights are callable by AI agents through an MCP (Model Context Protocol) server. Agents can search contracts, score fit, and estimate win likelihood — without writing raw HTTP code.
Tools
| Tool | Backend | Purpose |
|---|---|---|
| search_contracts | GET /v1/contracts | Search/filter contracts |
| get_contract | GET /v1/contracts/:id | Contract detail |
| search_naics | GET /v1/naics | NAICS lookup |
| get_states | GET /v1/states | State coverage |
| score_contract | POST /v1/match | 5-factor match score |
| win_likelihood | POST /v1/win-likelihood | Win probability vs the historical award archetype (derived data, paid) |
| archetypes | GET /v1/archetypes | List winning-business archetypes — who wins what (paid) |
Connect (Claude Code)
claude mcp add govcontractscout -- node /path/to/mcp-server/dist/index.js
claude mcp set-env govcontractscout GCS_API_KEY gcs_live_YOUR_KEYThe server requires a gcs_live_... API key (free or paid). Search, match, and lookup tools work on free; the derived-data tools (win_likelihood, archetypes) require a paid (Starter+) tier. An example agent ask: "Find Texas IT services contracts due this month, score the top one against our profile (NAICS 541511, TX), and estimate our win likelihood."
FAQ
How do I link an end user to the actual solicitation?
Use source_url from the contract detail endpoint (GET /api/v1/contracts/:id). It is the original procurement-page link, available on all tiers. The solicitation documents themselves are in pdf_urls (paid tiers).
How do I pull a large set of contracts without hitting rate limits?
Use pagination: per_page=100 and increment page (max 20). One page of 100 is one request, not 100. Do not fire one request per contract in parallel - that burns your rate limit and returns 429s. See the Pagination section for a full example.
Why am I getting 429 (rate limit exceeded)?
429 means you exceeded your per-minute rate limit. Free is 30/min, Starter 60/min, Growth 300/min. Respect the Retry-After header on the 429 response, or add a small delay between requests. If you are on a paid tier, the limit applies across all your keys (per-user), so a free key you created earlier does not throttle you.
What is the difference between the free and paid tiers?
Free: 100 requests/month, 30/min, all read endpoints + match scoring, no pdf_urls. Starter ($99/mo): 10,000 requests/month, 60/min, plus pdf_urls (solicitation documents). Growth ($199/mo): 50,000 requests/month, 300/min. See Pricing.
Can I use the API for a commercial product?
Yes - commercial use is allowed, including embedding the data in your own product (the intended use). You may not resell or redistribute the raw dataset as a competing data product. See the API terms.
How do I create an API key?
Sign in, go to the API keys page, and create a key. You will need to name it, describe what it is for, and accept the API terms. Free keys are instant; paid tiers are self-serve on checkout.
How fresh is the data?
Contracts are synced daily from the source portals. The detail endpoint returns updated_at so you can track changes.
Need help?
Contact us at api-support@govcontractscout.com
Get started
Free keys are self-serve — sign up and create one instantly. Paid tiers are instant too: check out and your key is issued or upgraded immediately.
Pricing
Free (100 req/mo) to test, Starter ($99/mo, 10,000 req/mo) and Growth ($199/mo, 50,000 req/mo) for production. Instant access on checkout. This is a standalone API, separate from a GovContractScout Pro plan. Commercial use is allowed, but reselling or redistributing the dataset is not, see the API terms.