Il n’existe pas de source unique, lisible par machine, pour les dépenses du gouvernement canadien. CanadaBuys couvre les contrats et appels d’offres fédéraux, mais utilise des noms de ministères incohérents, sans identifiants d’enregistrement stables, ni pagination adaptée à l’accès programmatique. Le SEAO couvre les 58 000 appels d’offres annuels du Québec, mais le flux OCDS brut exige un traitement non trivial. La Nouvelle-Écosse, l’Alberta et les autres provinces publient chacune séparément, dans des formats différents.
ProcureData normalise tout cela. 2 105 430 enregistrements répartis sur 9 sources, fédérales et provinciales, livrés via une seule API REST avec des noms de champs cohérents, une pagination par curseur et des temps de réponse inférieurs à 200 ms. Cette page est le guide de référence pour créer des agents LLM, des outils de rapport ou des pipelines RAG à partir de ces données.
Chaque enregistrement correspond à l’un des cinq types d’entités: contract, tender, award, disclosure ou standing_offer. La répartition par source:
| Source | Type d’entité | Enregistrements | Palier | Couverture |
|---|---|---|---|---|
| Contrats CanadaBuys | contract |
591 762 | fédéral | 2009–présent |
| Divulgations proactives SCT | disclosure |
499 868 | fédéral | 2004–présent |
| Appels d’offres SEAO Québec | tender |
368 149 | provincial | 2021–présent |
| Contrats SEAO Québec | contract |
352 972 | provincial | 2021–présent |
| Attributions CanadaBuys | award |
143 129 | fédéral | 2012–présent |
| Appels d’offres CanadaBuys | tender |
99 182 | fédéral | 2009–présent |
| Contrats attribués Nouvelle-Écosse | contract |
30 788 | provincial | 2010–présent |
| Registre de sole-source Alberta | contract |
13 596 | provincial | 1975–présent |
| Offres à commandes TPSGC | standing_offer |
5 984 | fédéral | instantané actuel |
Les enregistrements fédéraux utilisent government_level=federal. Les enregistrements du Québec, de la Nouvelle-Écosse et de l’Alberta utilisent government_level=provincial. Le niveau municipal est réservé pour une utilisation future.
Tous les points de terminaison sont accessibles via RapidAPI. Deux en-têtes sont requis à chaque requête:
# En-têtes requis pour chaque requête
X-RapidAPI-Key: VOTRE_CLÉ_API
X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com
Plan gratuit: 100 requêtes/jour. Plan Pro: 1 000 requêtes/jour à 29 $/mois. Plan Ultra: environ 127 000 requêtes/jour à 99 $/mois.
curl -G "https://procuredata-canadian-government-procurement-api.p.rapidapi.com/contract" \
--data-urlencode "department=National Defence" \
--data-urlencode "issued_after=2025-04-01" \
--data-urlencode "sort_by=value" \
--data-urlencode "limit=20" \
-H "X-RapidAPI-Key: VOTRE_CLÉ_API" \
-H "X-RapidAPI-Host: procuredata-canadian-government-procurement-api.p.rapidapi.com"
Chaque réponse de liste contient un champ next_cursor. Passez-le comme paramètre cursor dans la requête suivante. Les curseurs sont stables et adaptés aux appels d’outils séquentiels.
import requests
BASE = "https://procuredata-canadian-government-procurement-api.p.rapidapi.com"
HEADERS = {
"X-RapidAPI-Key": "VOTRE_CLÉ_API",
"X-RapidAPI-Host": "procuredata-canadian-government-procurement-api.p.rapidapi.com",
}
params = {"department": "Health Canada", "category": "SRV", "limit": 100}
records = []
while True:
r = requests.get(BASE + "/contract", headers=HEADERS, params=params)
data = r.json()
records.extend(data["results"])
if not data.get("next_cursor"):
break
params["cursor"] = data["next_cursor"]
print(f"{len(records)} contrats récupérés")
L’API se prête naturellement à l’utilisation d’outils dans les agents LLM. Voici une définition de fonction compatible OpenAI que vous pouvez intégrer directement dans tout agent ayant besoin d’interroger les données d’approvisionnement canadiennes. L’utilisation d’outils Anthropic suit la même structure.
{
"type": "function",
"function": {
"name": "query_canadian_procurement",
"description": "Recherche les contrats, appels d'offres et attributions du gouvernement canadien, sources fédérales et provinciales. Retourne des enregistrements structurés: ministère, fournisseur, valeur, catégorie, date.",
"parameters": {
"type": "object",
"properties": {
"entity_type": {
"type": "string",
"enum": ["contract", "tender", "award", "disclosure", "standing_offer"],
"description": "Type d'enregistrement d'approvisionnement à interroger"
},
"department": {
"type": "string",
"description": "Nom de ministère fédéral ou provincial (correspondance partielle acceptée)"
},
"vendor": {
"type": "string",
"description": "Nom du fournisseur (correspondance partielle)"
},
"q": {
"type": "string",
"description": "Recherche plein texte sur les champs titre et description"
},
"category": {
"type": "string",
"enum": ["SRV", "GD", "CNST", "SRVTGD"],
"description": "Catégorie: SRV=Services, GD=Biens, CNST=Construction, SRVTGD=Services+Biens"
},
"government_level": {
"type": "string",
"enum": ["federal", "provincial"],
"description": "Filtrer par palier de gouvernement"
},
"value_min": {
"type": "number",
"description": "Valeur minimale du contrat en CAD"
},
"value_max": {
"type": "number",
"description": "Valeur maximale du contrat en CAD"
},
"issued_after": {
"type": "string",
"description": "Enregistrements publiés à partir de cette date (AAAA-MM-JJ)"
},
"issued_before": {
"type": "string",
"description": "Enregistrements publiés jusqu'à cette date (AAAA-MM-JJ)"
},
"sort_by": {
"type": "string",
"enum": ["value", "date"],
"description": "Trier par valeur ou par date (défaut: date desc)"
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 500,
"description": "Nombre d'enregistrements à retourner (défaut 100)"
},
"cursor": {
"type": "string",
"description": "Curseur de pagination provenant du champ next_cursor d'une réponse précédente"
}
},
"required": ["entity_type"]
}
}
}
Un utilisateur demande: « Quels fournisseurs TI ont reçu le plus de contrats fédéraux de Santé Canada au cours des deux dernières années? » L’agent décompose cela en deux appels d’outils:
{
"entity_type": "contract",
"department": "Health Canada",
"category": "SRV",
"issued_after": "2024-04-22",
"sort_by": "value",
"limit": 100
}
GET /contract/stats?department=Health+Canada&category=SRV&group_by=vendor&period=1y
Le point de terminaison stats retourne des comptes et des sommes de groupe approximatifs via un échantillonnage de la base de données. Pour les grandes questions sur les dépenses totales ou la distribution par catégorie, c’est plus rapide que de parcourir tous les enregistrements.
Un enregistrement de contrat type:
{
"record_id": "canada_contracts|EC107-200001|C",
"entity_type": "contract",
"source_id": "canada_contracts",
"event_date": "2025-03-15",
"department": "Health Canada",
"vendor": "Deloitte Inc",
"contract_value": 2400000.00,
"category": "SRV",
"government_level": "federal",
"data": {
"solicitation_number": "EC107-200001",
"procurement_method": "Competitive",
"contract_period_start": "2025-03-15",
"contract_period_end": "2026-03-14",
"description": "Services de conseil en gestion",
"vendor_province": "Ontario"
}
}
Champ habilitation sécuritaire: les appels d’offres fédéraux de CanadaBuys incluent un champ security_clearance extrait du PDF de sollicitation. Valeurs: reliability, enhanced_reliability, secret, top_secret, none, ou null lorsqu’aucun document n’était disponible. Utile pour filtrer les appels d’offres accessibles aux fournisseurs non habilités.
La pagination par décalage se brise lorsque des enregistrements sont ajoutés entre les requêtes. Si votre agent pagine les résultats sur plusieurs tours ou appels d’outils, utilisez le paramètre cursor. Passez le next_cursor de la réponse précédente. Il n’est pas nécessaire de suivre un numéro de page ni de recalculer des décalages.
Si l’utilisateur demande « combien la Défense nationale a-t-elle dépensé en TI en 2024 », ne parcourez pas tous les contrats. Appelez /contract/stats?department=National+Defence&category=SRV&sum_field=contract_value&period=1y. Le point de terminaison stats utilise l’échantillonnage de base de données et répond en moins d’une seconde, même sur de grands ensembles filtrés.
Le point de terminaison /department/{name} retourne les principaux fournisseurs, la valeur totale et la répartition par catégorie d’un département sans pagination. Un seul appel d’outil répond à la plupart des questions « qui achète quoi chez X ».
Les données brutes de CanadaBuys contiennent 91 variantes de noms de ministères, normalisées en 23 noms canoniques dans l’API. Exemples courants:
# Utiliser ces chaînes exactes dans le paramètre department=
"National Defence"
"Public Services and Procurement Canada"
"Health Canada"
"Shared Services Canada"
"Royal Canadian Mounted Police"
"Canada Revenue Agency"
"Transport Canada"
"Environment and Climate Change Canada"
"Indigenous Services Canada"
"Fisheries and Oceans Canada"
# Ou utiliser /departments pour lister tous les noms canoniques
GET /departments
L’API retourne HTTP 429 lorsque vous dépassez la limite journalière de votre plan. RapidAPI envoie un en-tête Retry-After indiquant la réinitialisation (minuit UTC). Pour les agents exécutant des pipelines nocturnes, maintenez-vous sous 80 % de votre quota journalier pour conserver de la marge pour les nouvelles tentatives.
Pour l’intégration vectorielle d’enregistrements d’approvisionnement en vue de la génération augmentée par récupération, quelques notes pratiques:
description dans l’objet data est le texte le plus riche pour l’intégration. Il est renseigné pour la plupart des enregistrements CanadaBuys et tous les enregistrements de divulgation.title + notice_type + department ensemble. Le titre seul est souvent ambigu.event_date comme filtre de métadonnées pour les questions temporellement délimitées. Cela évite d’inclure des enregistrements périmés dans les réponses sur les dépenses actuelles.government_level dans les métadonnées avant la récupération si la question porte explicitement sur le niveau fédéral ou provincial.next_cursor. Passez cursor=<valeur> dans les requêtes suivantes. Les curseurs sont stables et adaptés aux agents effectuant des appels séquentiels sur plusieurs tours.
/sources pour les horodatages par source.
?government_level=federal pour CanadaBuys et SCT, ou ?government_level=provincial pour SEAO Québec, Nouvelle-Écosse et Alberta. Le champ est indexé; les réponses sont sous 200 ms pour les requêtes habituelles.
contract, tender, award, disclosure, standing_offer. Les noms de ministères sont normalisés depuis les données sources brutes (91 variantes vers 23 formes canoniques). Valeurs de catégorie: SRV (Services), GD (Biens), CNST (Construction), SRVTGD (Services et biens). Le champ security_clearance est extrait des PDF de sollicitation via pypdf pour les appels d’offres CanadaBuys seulement. Les points de terminaison de statistiques utilisent TABLESAMPLE SYSTEM pour l’agrégation approximative; des comptes exacts peuvent être obtenus en parcourant les résultats.
Obtenez votre clé API et commencez à interroger 2,1 M d’enregistrements de marchés publics aujourd’hui.
Obtenir une clé API sur RapidAPI Voir la spécification OpenAPI