Aller au contenu principal

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 :

FormCredentialSent 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 :

ScopeRoute familyUsed by
ai/inference-api/b2b/v1/chat/*, /retrieval/*chat embed
design/inference-api/b2b/v1/design/*editor embed
mapsdesigned basemapsthe 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 tile ou viewer ne porte jamais vendor, 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_session lorsqu’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 keyEffect on a session already in flight
Revoked or deletedRejetée à la requête suivante
A scope removedSupprimé à la requête suivante
Plan downgradedLes capabilities limitées par niveau sont refusées à la requête suivante
Rate limit or monthly cap set to a new valueS’applique à la requête suivante
A scope added, plan upgraded, or a limit lifted entirelyNon 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.