API Tutorials
From first request to a running contractor-alert workflow. Each tutorial is self-contained with copy-paste code.
Quickstart
Create a key and make your first request in under five minutes.
- Get a key. For a free key, no account is needed. Select Email me a free key on the API documentation page, or POST to /api/api-keys/free.
- For a paid key, sign in and create it on the dashboard API keys page. Name it, describe what it is for, and accept the terms.
- Set your key: export GCS_API_KEY=your_key_here
- Make the first request:
curl "https://scout.govbidportals.com/api/v1/contracts?states=CA&per_page=5" \
-H "Authorization: Bearer $GCS_API_KEY"Result: A JSON response with up to 5 active California contracts, each with id, title, agency, due_date, and NAICS.
馃挕 Use a free key (100 req/mo) to test the shape before you scale.
Pagination
Pull large sets of contracts without hitting rate limits.
- The list endpoint returns up to 100 contracts per page. Use per_page=100 and increment page (max 20).
- Stop when page reaches total_pages from the response meta.
- Add a 1s delay between pages to stay under your per-minute limit.
import requests, time
r = requests.get("https://scout.govbidportals.com/api/v1/contracts",
headers={"Authorization": "Bearer " + API_KEY},
params={"per_page": 100, "page": page, "status": "active"})
data = r.json()
all_contracts.extend(data["data"])
if page >= data["meta"]["total_pages"]:
break # done
page += 1
time.sleep(1)Result: Every contract matching your filters, one page of 100 at a time.
馃挕 Do NOT fire one request per contract in parallel - that triggers 429s. One page of 100 is one request.
Filtering
Narrow the dataset to the contracts you care about.
- Filter by state (state or states), NAICS (naics or naics_codes), value (min_value/max_value), keyword, and agency.
- Combine filters with & in one request - they are AND-ed together.
- Use date filters (due_after, due_before, posted_after) to focus on upcoming work.
curl "https://scout.govbidportals.com/api/v1/contracts?states=CA,NV&naics_codes=541512&min_value=100000&due_after=2026-10-01" \
-H "Authorization: Bearer $GCS_API_KEY"Result: Only CA/NV IT-services contracts worth $100k+ due after October.
馃挕 The naics param accepts a 2-6 digit code or prefix - 541 matches all IT-services sectors.
Match Scoring
Score a contract against your company profile with the 5-factor engine.
- Build a profile: NAICS codes, budget range, service area (states), keywords, and timeline preference.
- POST the profile and a contract_id to /api/v1/match.
- Read match_score, match_grade, and match_reasons to decide whether to pursue it.
curl -X POST "https://scout.govbidportals.com/api/v1/match" \
-H "Authorization: Bearer $GCS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contract_id": "550e8400-e29b-41d4-a716-446655440000",
"profile": {
"naics_codes": ["541512"],
"min_budget": 50000,
"max_budget": 5000000,
"state": "CA",
"keywords": ["cloud", "migration"]
}
}'Result: A match_score (0-100), grade, and human-readable reasons explaining the score.
馃挕 Use /api/v1/match/batch to score many contracts at once, or /api/v1/match/search to search and score in one call.
Link to Solicitations
Send end users to the actual solicitation page and documents.
- GET /api/v1/contracts/{id} for a contract's detail.
- source_url is the original procurement-page link - send users there.
- pdf_urls (paid tiers) are the solicitation documents (RFP, specs).
curl "https://scout.govbidportals.com/api/v1/contracts/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer $GCS_API_KEY"Result: The detail includes source_url (original page) and pdf_urls (documents) for paid keys.
馃挕 source_url is available on all tiers and is detail-only - fetch it per contract you care about.
Build a Contractor Alert
The end-to-end pattern: watch for matching contracts and notify your users.
- Run a scheduled job (cron) that queries the list endpoint with your filters.
- For each new match, GET its detail to grab source_url (and pdf_urls on paid).
- Email your users a link to the solicitation. Respect rate limits with pagination + delays.
# Pseudocode for a nightly alert job
new_contracts = search(filters) # paginate, compare to last run
for c in new_contracts:
detail = get_detail(c["id"]) # source_url, pdf_urls
notify_user(email, detail["source_url"], detail["title"])Result: Your users get notified the moment a relevant solicitation drops, with a link straight to it.
馃挕 This is the pattern the API was built for - you bring the matching/UX, we supply clean, fresh, normalized data.