Authentification et scopes
La platform API s’authentifie avec une clé de votre organisation. Elle existe sous deux formes — même organisation, mêmes scopes, runtime différent :
| Form | Credential | Sent as |
|---|---|---|
| Server (backend) | kld_sk_live_… | Authorization: Bearer … ou X-Api-Key |
| Publishable (browser) | kld_pk_live_… | échangée par le SDK contre une session de courte durée ; jamais envoyée comme raw bearer |
Authorization: Bearer kld_sk_live_…
# or
X-Api-Key: kld_sk_live_…
Les server keys sont le bearer que vous envoyez depuis votre backend à chaque requête.
Les publishable keys sont destinées au navigateur : le SDK en échange une contre un session token de courte durée
lié à l’origin au runtime, de sorte que la publishable key elle-même ne reste jamais une
credential permanente dans le source de la page. Une publishable key présentée directement comme
bearer est rejetée — utilisez-la via le SDK. Une server key ne reçoit aucun accès CORS,
une page ne peut donc jamais lire une réponse générée avec elle — mais CORS ne peut pas
empêcher la requête de quitter le navigateur. Une server key placée dans le source d’une page
est donc déjà divulguée au moment où l’API la refuse. C’est précisément pourquoi le SDK refuse
les clés kld_sk_… au mount : gardez toujours les server keys
côté serveur.
Les anciennes clés kld_live_… existantes continuent de fonctionner comme direct bearer aux deux endroits.
Scopes
Une clé porte des capability scopes ; chaque famille de routes en exige un :
| Scope | Route family | Used by |
|---|---|---|
ai | /inference-api/b2b/v1/chat/*, /retrieval/* | chat embed |
design | /inference-api/b2b/v1/design/* | editor embed |
maps | designed basemaps | the tile embed |
vendor | (modifier, not a route) | the chat embed, on your own data |
Par défaut, une clé Pro/Enterprise est créée avec ai, design et maps.
Les clés du forfait Free sont limitées à maps + le produit tile ; consultez
Obtenir une clé API pour le tableau canonique
plan × scope × produit.
Admission effective = clé stockée × niveau actuel. Le session-exchange au runtime
recalcule l’admission à chaque appel. Ainsi, une clé Pro-tier rétrogradée vers Free
ne crée plus que des sessions tile à partir de ce moment — même si la clé stockée contient encore
ai et design dans ses restrictions. Le subcode de rejet
distingue les deux cas :
insufficient_scope— la clé n’a jamais eu la capability.tier_capability_not_allowed— la clé l’avait, mais le niveau actuel ne l’autorise plus. Mettez à niveau le forfait pour la restaurer.
Un allowed_products vide dans la clé stockée signifie tous les produits (pas
aucun). Le niveau continue de réduire ce surensemble à ce que le forfait autorise.
vendor — demandez-le volontairement, et uniquement là où vous en avez besoin
vendor n’est pas un contrôle d’accès de route. Il n’autorise ni ne refuse une requête ; il détermine
si le chat AI peut consulter les données vendor importées par votre organisation lorsqu’il
répond. Tous les autres scopes répondent à "cette clé peut-elle appeler cet endpoint ?" ; vendor
répond à "cette clé peut-elle parler au nom de nos données internes ?".
Il n’est donc jamais inclus par défaut — demandez-le explicitement lors du mint :
{ "name": "our-site-widget", "scopes": ["ai", "vendor"] }
La clé qui porte vendor constitue toute la décision de sécurité. Le chat embed est un
widget navigateur : il échange une publishable key contre une session de courte durée, une
clé activée pour vendor se trouve donc nécessairement dans une page publique. Cela convient aux données
que vous acceptez de montrer à chaque visiteur du site — liste d’établissements, horaires,
tarifs publics. Ce n’est pas approprié pour des informations que vous ne publieriez pas. L’origin
allowlist protégeant l’échange est une convention du navigateur, pas une limite de confidentialité :
un appelant qui définit lui-même son header Origin n’est pas bloqué par elle.
Donc :
- Une clé par surface. Un site marketing, une page de démonstration et votre application destinée aux clients
ne doivent pas partager une clé. Seule la surface devant répondre à partir de vos données reçoit
vendor. - Ne placez jamais une grille tarifaire, une base de coûts ou quoi que ce soit de non publié derrière une
publishable key. Si la réponse vous embarrasserait sur une page publique, les données
n’ont pas leur place dans un embed avec scope
vendor. - Les sessions sont restreintes à leur produit, donc une session
tileouviewerne porte jamaisvendor, même si sa parent key le possède.
Pour le retirer, modifiez les scopes de la clé ou révoquez-la — les deux prennent effet dès la requête suivante, y compris pour les sessions déjà actives. Le retrait n’est pas reporté jusqu’à l’expiration de la session.
401 contre 403
Ils sont volontairement distincts :
- 401 Unauthorized — clé manquante / invalide / révoquée / expirée. Revérifiez
la valeur de la clé et qu’elle n’est pas révoquée. Également
publishable_requires_sessionlorsqu’une publishable key est envoyée comme raw bearer. - 403 Forbidden — la clé existe mais n’est pas admise ici. Subcodes fréquents :
insufficient_scope(jamais eu),tier_capability_not_allowed(avait la capacité, niveau ne l’autorise plus),session_origin_mismatch,ip_not_allowed(server keys),server_key_in_browser,product_not_allowed.
Les deux échouent de manière fermée : une clé sans scopes est refusée partout.
Session tokens
La session contre laquelle le SDK échange une publishable key ressemble à ceci :
kld_sess_{env}_{jwt}
par exemple kld_sess_live_eyJhbGciOi…. Présentée lors des appels runtime comme
Authorization: Bearer ou X-Api-Key. TTL par défaut de 900 secondes (15
minutes) ; maximum serveur de 30 minutes. Les sessions sont limitées au produit
pour lequel elles ont été créées, et chaque requête relit la live policy de la parent key.
Le retrait est immédiat ; l’octroi ne l’est pas. Les deux directions sont volontairement asymétriques et fail closed :
| Change to the parent key | Effect on a session already in flight |
|---|---|
| Revoked or deleted | Rejetée à la requête suivante |
| A scope removed | Supprimé à la requête suivante |
| Plan downgraded | Les capabilities limitées par niveau sont refusées à la requête suivante |
| Rate limit or monthly cap set to a new value | S’applique à la requête suivante |
| A scope added, plan upgraded, or a limit lifted entirely | Non visible — créez une nouvelle session |
Une session ne peut que restreindre son parent, jamais s’étendre au-delà des scopes avec lesquels elle a été créée ; un nouvel octroi nécessite donc un nouvel échange. Les sessions sont courtes (15 minutes par défaut) précisément pour que cet écart reste faible.
Consultez Errors pour le tableau complet des statuts.