← Retour au blogue
EN FR

API Marchés Publics Canada pour l’IA et les LLM

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.

Ce que contient la base de 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:

Enregistrements par source (2 105 430 au total)
Tous les comptes sont en date d’avril 2026. Les sources fédérales se mettent à jour chaque semaine (lundi). Les sources provinciales suivent le même calendrier.
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.

Authentification

Tous les points de terminaison sont accessibles via RapidAPI. Deux en-têtes sont requis à chaque requête:

bash
# 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.

Points de terminaison

Surface de l’API
  • GET
    /contract
    Contrats attribués. Filtre par ministère, fournisseur, catégorie, plage de valeurs, dates, palier de gouvernement.
  • GET
    /tender
    Appels d’offres ouverts et historiques (CanadaBuys + SEAO). Filtre par type d’avis, habilitation sécuritaire, ministère.
  • GET
    /award
    Avis d’attribution CanadaBuys. Lien vers les appels d’offres via solicitation_number.
  • GET
    /disclosure
    Divulgations proactives SCT (contrats fédéraux de plus de 10 000 $), 2004–présent.
  • GET
    /standing_offer
    Offres à commandes et arrangements en matière d’approvisionnement TPSGC (instantané SOSA).
  • GET
    /{entity_type}/stats
    Statistiques agrégées. group_by: department, category, vendor_province. Comptes approximatifs via TABLESAMPLE.
  • GET
    /procurement/{solicitation_number}
    Vue cycle de vie complet: appel d’offres + attributions + contrats reliés par numéro de sollicitation.
  • GET
    /department/{name}
    Profil ministère: total d’enregistrements, valeur totale, répartition par type d’entité, catégories principales.
  • GET
    /vendor/{name}
    Profil fournisseur: tous les contrats et attributions, principaux ministères, répartition par valeur.
  • GET
    /sources
    Liste des sources actives avec nombre d’enregistrements et horodatages de dernière mise à jour.

Exemples de requêtes

Contrats par ministère, 12 derniers mois

curl
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"

Pagination par curseur (pour les agents)

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.

python
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")

Définition d’appel de fonction LLM

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.

json (outil OpenAI)
{
  "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"]
    }
  }
}

Exemple: trace de raisonnement d’un agent

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:

appel d’outil #1
{
  "entity_type": "contract",
  "department": "Health Canada",
  "category": "SRV",
  "issued_after": "2024-04-22",
  "sort_by": "value",
  "limit": 100
}
appel d’outil #2 (statistiques agrégées)
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.

Schéma d’enregistrement

Un enregistrement de contrat type:

json (enregistrement contrat)
{
  "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.

Décisions de conception pour agents LLM

Utiliser la pagination par curseur, pas par décalage

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.

Utiliser les stats pour les questions agrégées

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.

Utiliser les profils de département pour la découverte de fournisseurs

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 ».

Normaliser les noms de ministères

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:

noms de ministères canoniques (exemples)
# 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

Limites de débit et nouvelles tentatives

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.

Construire un pipeline RAG

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:

  • Le champ 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.
  • Pour les appels d’offres, intégrez title + notice_type + department ensemble. Le titre seul est souvent ambigu.
  • Découpez au niveau de l’enregistrement. Chaque enregistrement fait 200–800 tokens. Aucun découpage supplémentaire n’est nécessaire.
  • Utilisez 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.
  • Filtrez 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.

Questions fréquentes

Quelles sources de données ProcureData couvre-t-elle?
9 sources: contrats CanadaBuys (591 762), divulgations proactives SCT (499 868), appels d’offres SEAO Québec (368 149), contrats SEAO Québec (352 972), attributions CanadaBuys (143 129), appels d’offres CanadaBuys (99 182), contrats attribués Nouvelle-Écosse (30 788), registre de sole-source Alberta (13 596) et offres à commandes TPSGC (5 984). Total: 2 105 430 enregistrements.
L’API prend-elle en charge la pagination par curseur?
Oui. Chaque réponse de liste retourne un champ 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.
À quelle fréquence les données sont-elles mises à jour?
Les données fédérales (contrats, appels d’offres, attributions) se mettent à jour chaque semaine (lundi, 2h-6h UTC). Les divulgations proactives SCT se mettent à jour mensuellement. Le SEAO Québec, la Nouvelle-Écosse et l’Alberta se mettent à jour chaque semaine. Consultez le point de terminaison /sources pour les horodatages par source.
Puis-je filtrer par palier de gouvernement?
Oui. Utilisez ?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.
Existe-t-il un niveau gratuit pour tester?
Oui. Plan Basic: gratuit, 100 requêtes/jour. Plan Pro: 29 $/mois, 1 000 requêtes/jour. Plan Ultra: 99 $/mois, environ 127 000 requêtes/jour.
Où puis-je consulter la spécification OpenAPI?
La spécification OpenAPI 3.0.3 complète est disponible à procuredata.ca/openapi.json. Vous pouvez l’importer directement dans Postman, Insomnia ou tout cadre d’utilisation d’outils LLM.
Notes sur les données: Comptes d’enregistrements en date d’avril 2026. Valeurs entity_type: 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