Point de terminaison API https://northerninference.ca/v1 Utilisez ceci comme URL de base dans chaque intégration.

curl / HTTPie

Appelez Inférence Nordique directement avec curl ou HTTPie : une requête complète pour les deux formats, sur une API d'IA souveraine canadienne destinée aux équipes gouvernementales et réglementées.

Inférence Nordique est une API d'IA souveraine canadienne pour les équipes du gouvernement, de la défense, de la santé et des secteurs réglementés, y compris les organisations relevant du Programme des marchandises contrôlées. Chaque route comporte une résidence des données au Canada conforme à la LPRPDE, un chemin exact vers les derniers modèles de pointe et à poids ouverts, ainsi qu'un registre de chaîne de possession par requête.

Démarrez en 30 secondes

export NI_API_KEY=ni_live_YOUR_KEY_HERE
curl https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-haiku-4-5-20251001-t4","messages":[{"role":"user","content":"hi"}],"max_tokens":20}'

Le champ model est le contrat de route. Copiez les identifiants de route exacts depuis northerninference.ca/portal (page Modèles) ou depuis curl https://northerninference.ca/api/billing/models | jq '.models[].model_id'.


Complétion de chat de base

curl https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-haiku-4-5-20251001-t4",
    "messages": [{"role": "user", "content": "hi"}],
    "max_tokens": 20
  }'

Choisir une route

curl https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6-t4",
    "messages": [{"role": "user", "content": "Which jurisdiction am I in?"}],
    "max_tokens": 80
  }'

L'identifiant du modèle est le contrat de route. Copiez la clé de routage exacte depuis /models ou /api/billing/models. Les niveaux de route autorisés de la clé API déterminent quelles routes la clé peut utiliser.

Lire la chaîne de possession à partir des en-têtes de réponse

curl -sS -D /tmp/headers https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-haiku-4-5-20251001-t4","messages":[{"role":"user","content":"hi"}],"max_tokens":5}' \
  > /dev/null

grep -i '^x-ni-' /tmp/headers

Vous verrez quelque chose comme :

x-ni-request-id: 8f2e3b7d9a1c4f08
x-ni-resolved-tier: managed_canadian_cloud
x-ni-resolved-provider: Bedrock
x-ni-resolved-region: ca-central-1
x-ni-resolved-jurisdiction: CA
x-ni-custody-path: NI-CA -> Bedrock-CA
x-ni-credential-source: platform

En-têtes qui n'apparaissent que lorsque nous avons modifié quelque chose

Les en-têtes ci-dessus reviennent à chaque requête. Ceux-ci sont différents : ils n'apparaissent que lorsqu'Inférence Nordique a ajusté votre requête afin qu'elle s'exécute plutôt que d'échouer, lorsqu'une partie de celle-ci n'a pas pu atteindre le modèle ou, pour x-ni-reasoning-state, lorsque vous avez renvoyé des éléments de raisonnement. Si vous ne les voyez jamais, rien n'a été ajusté.

Ils sont importants, car la réponse arrive tout de même sous la forme d'un HTTP 200 normal. Sans les lire, il est impossible de distinguer une réponse produite exactement selon vos paramètres d'une réponse produite selon un paramètre ajusté.

En-têteSignification
x-ni-max-output-tokens-clampedVotre max_tokens dépassait le plafond fixe du fournisseur pour cette route, et nous l'avons abaissé à la valeur indiquée plutôt que de rejeter l'appel.
x-ni-reasoning-effort-clampedVotre reasoning_effort était hors des niveaux pris en charge par cette route (au-dessus du plus élevé, en dessous du plus faible comme minimal, ou none sur une route dont le modèle raisonne toujours), et nous l'avons exécuté à l'effort indiqué à la place.
x-ni-reasoning-stateVous avez renvoyé des éléments reasoning sur /v1/responses. replayed signifie que NI les a tous transmis à Claude. skipped=<reason> signifie qu'aucun n'a été transmis et que la requête s'est exécutée sans ce raisonnement antérieur. partial;skipped=<reason> signifie que certains ont été omis.
x-ni-params-droppedLe modèle derrière cette route refuse les paramètres de requête indiqués (par exemple temperature ou top_p) : nous les avons donc omis, et le modèle a utilisé ses propres valeurs par défaut au lieu de faire échouer l'appel. Un paramètre indiqué avec une valeur (par exemple thinking.display=updates) signifie que la route refuse cette valeur : nous avons donc envoyé à la place la valeur la plus proche qu'elle accepte. Une réponse /v1/responses affiche les champs omis à null.
x-ni-params-not-forwardedSur /v1/responses, les parties de text indiquées (par exemple la sortie structurée ou la verbosité) ne sont pas transmises au modèle sur cette route : la réponse a donc été produite sans elles.
x-ni-params-forwarding-unknownNous n'avons pas pu déterminer si les paramètres indiqués atteignent le modèle sur cette route. Considérez que la réponse a peut-être été produite sans eux.

Les deux en-têtes d'ajustement portent la valeur réellement appliquée, et non celle que vous avez envoyée, puisque vous connaissez déjà cette dernière.

Si vous préférez que ces cas échouent bruyamment plutôt que d'être ajustés, envoyez "strict_max_tokens": true pour la limite de sortie. Un effort de raisonnement que cette route ne prend pas du tout en charge, y compris une faute d'orthographe, est toujours rejeté avec un 400 qui nomme les valeurs acceptées par la route.

Diffusion en continu

curl -sS https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-haiku-4-5-20251001-t4",
    "messages": [{"role": "user", "content": "count to five"}],
    "max_tokens": 30,
    "stream": true,
    "stream_options": {"include_usage": true}
  }'

Extraction complète de la possession après l'appel

curl https://northerninference.ca/api/usage/custody/8f2e3b7d9a1c4f08 \
  -H "Authorization: Bearer $NI_API_KEY"

Étiqueter une requête avec votre propre référence

Envoyez X-NI-Reference et Inférence Nordique enregistre la valeur sur cette requête, l'affiche dans le portail (Requêtes, Dépenses par référence, le relevé mensuel), et l'intègre au registre de possession signé fourni par /api/usage/custody/{id}. Utilisez-la pour attribuer les dépenses d'IA à un dossier, à un contrat ou à un code SDT.

curl -sS -D /tmp/headers https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-NI-Reference: 7c1f0a9e4b2d8e11" \
  -d '{"model":"claude-haiku-4-5-20251001-t4","messages":[{"role":"user","content":"hi"}],"max_tokens":5}' \
  > /dev/null

grep -i '^x-ni-reference' /tmp/headers

La réponse la renvoie sous la forme x-ni-reference afin que vous puissiez confirmer ce qui a été enregistré. Règles :

avec un 400 invalid_reference avant l'exécution de la requête; une référence n'est jamais abandonnée silencieusement.

l'envoyons jamais à un fournisseur. Elle ne figure pas dans le corps de requête que voit le fournisseur.

information personnelle. Un HMAC à clé de votre propre identifiant (par exemple HMAC-SHA256(secret, case_id) tronqué à 32 caractères hexadécimaux) vous permet de faire correspondre une requête à un dossier sans que le numéro de dossier ne quitte jamais vos systèmes, ce qui est exactement ce dont un tribunal ou un vérificateur a besoin.

Si votre client ne peut pas définir d'en-têtes, envoyez "ni_reference": "..." au niveau supérieur du corps JSON (ou dans extra_body avec un SDK). Nous le retirons avant l'envoi. Lorsque les deux sont présents, l'en-tête prévaut.

Avec les SDK OpenAI ou Anthropic, transmettez-la par requête avec extra_headers, ou une seule fois pour tout le client avec default_headers :

client = OpenAI(api_key=NI_API_KEY, base_url="https://northerninference.ca/v1",
                default_headers={"X-NI-Reference": reference_for(case_id)})

Pour consulter les dépenses par référence : GET /api/usage/by-reference?days=30 (ajoutez &format=csv pour un dossier), et GET /api/usage/by-reference/statements?month=2026-08 pour le relevé d'un mois clos.

Nouvelles tentatives et facturation

Chaque requête d'inférence indépendante reçoit son propre X-NI-Request-ID généré par NI. Une nouvelle tentative depuis votre client constitue une autre requête et peut entraîner des frais supplémentaires, même si vous réutilisez une référence ou un en-tête de requête.

NI empêche que des rappels internes répétés ou des nouvelles tentatives de règlement ne facturent deux fois la même exécution. L'arrêt ou la déconnexion n'annule pas les frais liés à une utilisation avérée du fournisseur, y compris un raisonnement déjà effectué.

Utilisez X-NI-Reference pour regrouper les requêtes connexes et examiner leurs résultats de facturation individuels dans l'historique des requêtes. L'ancienne fonctionnalité d'inférence Idempotency-Key a été retirée : cet en-tête est ignoré et n'est pas transmis aux fournisseurs. NI ne stocke pas les réponses pour rediffusion.

Désactiver les solutions de secours

curl https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -d '{
    "model": "claude-sonnet-4-6-t4",
    "messages": [{"role":"user","content":"hi"}],
    "max_tokens": 10,
    "allow_fallbacks": false
  }' \
  -H "Content-Type: application/json"

Activer la substitution des RPI

curl https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-haiku-4-5-20251001-t4",
    "messages": [{"role": "user", "content": "My name is Jane Doe, email jane@example.com"}],
    "max_tokens": 30,
    "pii_substitution": true
  }'

Les entités (nom, courriel, téléphone, NAS, carte de crédit, IP, emplacement) sont remplacées par des substituts déterministes générés par Faker avant de quitter l'infrastructure de NI, et les valeurs originales sont rétablies dans la réponse avant qu'elle ne vous parvienne. La table pii_audit_log consigne ce qui a été substitué; les administrateurs la consultent sous portail → Admin → Audit RPI.

Vision (entrée d'image)

Envoyez l'image sous forme de bloc de contenu image_url à toute route dont supports_vision est true :

B64=$(base64 -i screenshot.png | tr -d '\n')
curl -sS https://northerninference.ca/v1/chat/completions \
  -H "Authorization: Bearer $NI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6-t4",
    "messages": [
      {"role": "user", "content": [
        {"type": "text", "text": "What does this image say?"},
        {"type": "image_url", "image_url": {"url": "data:image/png;base64,'"$B64"'"}}
      ]}
    ],
    "max_tokens": 300
  }'

Voir vision-and-capabilities.md pour le guide complet, y compris comment indiquer à un client dont la table de modèles est codée en dur qu'une route NI prend en charge les images.

Appel d'outils sur les routes Gemini 3

Les modèles Gemini 3 attachent une signature de pensée à chaque appel de fonction qu'ils effectuent. Google exige que cette signature soit retournée à la prochaine requête et rejette le tour avec un 400 (Function call is missing a thought_signature in functionCall parts) lorsqu'elle est manquante. Inférence Nordique transporte la signature à l'intérieur de l'appel d'outil id. Rejouez le message de l'assistant et son tool_calls[].id exactement tel que reçu, ce que fait par défaut chaque SDK compatible OpenAI, et la règle est satisfaite sans travail supplémentaire. Ne raccourcissez pas, ne régénérez pas et ne reformatez pas les identifiants d'appel d'outil; renvoyez le même identifiant comme tool_call_id sur le message tool. La signature est également exposée sous provider_specific_fields sur le message et sur chaque appel d'outil, et en diffusion en continu, elle arrive avec le delta de l'appel d'outil. Un tour texte seul peut aussi porter une signature; il est recommandé de la rejouer, mais ce n'est pas obligatoire.

Liste des modèles : deux points d'accès, deux formes

NI possède deux points d'accès pour la liste des modèles. Ils retournent délibérément des formes JSON DIFFÉRENTES, alors faites correspondre votre chemin jq au bon point d'accès :

Point d'accèsAuthentificationEnveloppeChamp d'identifiant
GET /v1/modelsClé API requise.data[].id
GET /api/billing/modelsaucune (public).models[].model_id (aussi .id)

/v1/models est la liste compatible OpenAI. Elle requiert une clé et retourne les routes que cette clé est autorisée à appeler, dans la forme standard d'OpenAI ({"object": "list", "data": [{"id": ...}]}). Pointez n'importe quel SDK OpenAI vers https://northerninference.ca/v1 et client.models.list() fonctionne simplement.

curl -sS https://northerninference.ca/v1/models \
  -H "Authorization: Bearer $NI_API_KEY" \
  | jq '.data[] | {id, supports_vision, recommended_for_agentic, capabilities}'

/api/billing/models est le catalogue public non authentifié. Il retourne chaque route publique avec des métadonnées complètes (tarifs, niveau de confidentialité, résidence des données, capacités), enveloppées dans {"models": [ ... ]}.

curl -sS https://northerninference.ca/api/billing/models \
  | jq -c '.models[] | {id: .model_id, name: .display_name, tier: .privacy_tier.label, in: .input_cost_per_m_usd, out: .output_cost_per_m_usd}'

Erreur courante : /v1/models place le tableau sous .data (et non .models), et chaque élément utilise .id (il n'y a pas de .name). Utiliser .models[] contre /v1/models donne Cannot iterate over null. Un appel non authentifié à /v1/models retourne un 401 dont le corps renvoie au catalogue public /api/billing/models.


Vous constatez un problème? Écrivez à support at northerninference dot ca.

↑