CanadaBuys API: Access Federal Tenders and Contracts Programmatically
CanadaBuys is Canada's federal procurement portal, run by Public Services and Procurement Canada (PSPC). It publishes every federal contract, open tender, and contract award. The problem: there is no public REST API. The data lives behind a web UI and bulk CSV dumps that are awkward to work with at any scale.
ProcureData wraps all CanadaBuys data into a clean REST API: 834,073 records across contracts, tenders, and awards, normalized to a consistent schema, searchable by department, vendor, keyword, date, and value. It refreshes weekly.
Why the native portal is painful at scale
The CanadaBuys web portal works for one-off lookups. It breaks down the moment you need to pull data systematically: for a vendor intelligence tool, a procurement dashboard, an LLM agent, or just a spreadsheet of DND contracts from the last 12 months.
CanadaBuys portal
- No REST API, no pagination endpoint
- Bulk downloads are multi-GB CSVs with inconsistent column names across years
- ~90 department name variants for the same departments
- No full-text search across descriptions
- No way to link a tender to its resulting contract
ProcureData API
- REST API, JSON responses, under 200ms
- Cursor pagination for iterating the full dataset
- Normalized department names (20 canonical forms)
- Full-text search via
?q= /procurement/{solicitation_number}links tender to awards and contracts
834,073 CanadaBuys records. One endpoint. Free tier includes 25 requests per day.
What CanadaBuys data looks like in the API
Each record includes top-level fields for fast filtering (department, vendor, contract_value, category, event_date) plus a data object with the raw source fields. A contract record:
{
"record_id": "canada_contracts|W8486-226285|A",
"entity_type": "contract",
"source_id": "canada_contracts",
"event_date": "2025-11-03",
"department": "National Defence",
"vendor": "L3Harris Technologies Inc",
"contract_value": 8400000.00,
"category": "GD",
"government_level": "federal",
"data": {
"solicitation_number": "W8486-226285",
"procurement_method": "Competitive",
"contract_period_start": "2025-11-03",
"contract_period_end": "2028-03-31",
"description": "Communications equipment and support",
"vendor_province": "Ontario"
}
}
Query examples
Open tenders from CanadaBuys, filtered by keyword
curl -G "https://procuredata-canadian-government-procurement-api.p.rapidapi.com/tender" \
--data-urlencode "q=software development" \
--data-urlencode "government_level=federal" \
--data-urlencode "issued_after=2025-01-01" \
--data-urlencode "limit=20" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com"
All contracts awarded to a specific vendor
curl -G "https://procuredata-canadian-government-procurement-api.p.rapidapi.com/contract" \
--data-urlencode "vendor=Deloitte" \
--data-urlencode "government_level=federal" \
--data-urlencode "sort_by=value" \
--data-urlencode "limit=50" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com"
Contracts from a department, last 12 months, sorted by value
curl -G "https://procuredata-canadian-government-procurement-api.p.rapidapi.com/contract" \
--data-urlencode "department=National Defence" \
--data-urlencode "issued_after=2025-05-01" \
--data-urlencode "sort_by=value" \
--data-urlencode "limit=100" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com"
Full procurement lifecycle: tender to contract
The /procurement/{solicitation_number} endpoint returns the full lifecycle view: the original tender notice, all award notices, and all resulting contracts linked by solicitation number. One call instead of three.
curl "https://procuredata-canadian-government-procurement-api.p.rapidapi.com/procurement/W8486-226285" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com"
Department name normalization
CanadaBuys has roughly 90 department name variants in the raw data: "National Defence", "Dept. of National Defence", "DND", "Department Of National Defence Canada" all refer to the same buyer. The API normalizes these to about 20 canonical names. Use ?department=National Defence and you will get all of them, regardless of which variant the original record used.
To get the full list of canonical department names and their record counts:
curl "https://procuredata-canadian-government-procurement-api.p.rapidapi.com/departments" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com"
Frequently asked questions
/tender endpoint with ?q=your+keyword&government_level=federal. The q parameter searches across tender title and description. Add issued_after and department filters to narrow results.
/sources for the exact last-updated timestamp per source.
?category=SRV for services, GD for goods, CNST for construction, or SRVTGD for services and goods combined. These map to CanadaBuys's own commodity codes.
government_level=federal returns CanadaBuys, TBS proactive disclosures, and PSPC standing offers. Department names normalized from approximately 90 raw variants to about 20 canonical forms. Category codes: SRV (Services), GD (Goods), CNST (Construction), SRVTGD (Services and Goods). Alberta pre-2000 records are sparse; practical queries should use issued_after=2010-01-01.
Start querying CanadaBuys contracts, tenders, and awards with a free API key.
Get API Key on RapidAPI View OpenAPI Spec