aethexDocs

Référence API

API Conversation (WebRTC)

Sessions vocales en temps réel entre un utilisateur (dans un navigateur ou une application mobile) et l'un de vos agents. WebRTC maintient la latence dans la même plage qu'un appel téléphonique, sans numéro de téléphone.Le handshake en termes simples :
1. Votre serveur ouvre une session pour un agent avec POST /conversation/connect. Vous obtenez un session_id et la configuration réseau (ice_config).
2. Le navigateur construit une offre SDP avec RTCPeerConnection et la soumet via votre serveur, qui la transfère à POST /conversation/:session_id/offer et retourne la réponse SDP. Le navigateur l'applique à la connexion pair et l'audio commence à circuler.
3. Retournez les résultats d'outil avec /tool-result ; terminez l'appel avec /end.La plupart des endpoints utilisent calls:write ; /status accepte calls:read. Le flux général est documenté dans WebRTC calls concept.

URL de base
https://api.aethexai.com/api/v1
Endpoints
7
Portées
calls:readcalls:write
POST/conversation/connect

Ouvrir une session pour un agent. Côté serveur ; utilise votre clé API directement.

Connecter

Démarre une session WebRTC pour l'agent donné. Vous obtenez un session_id et un ice_config. Passez ice_config.iceServers directement dans new RTCPeerConnection({ iceServers }) côté navigateur. Agents publics : si l'agent a public_access activé, un navigateur ou une application peut appeler ce point de terminaison avec uniquement l'agent_id et sans clé API. Restreignez les sites autorisés à l'intégrer avec le champ allowed_origins de l'agent.

Corps de la requête

2
  • agent_idstring (UUID)requis

    L'UUID de l'agent pour démarrer la session. Doit appartenir au compte appelant.

  • dynamic_variablesobjectoptionnel

    Valeurs des placeholders {{variable}} de l'agent, pour cette session uniquement — rien n'est enregistré sur l'agent. Même forme que POST /calls/trigger : un objet plat de chaînes, nombres ou booléens. Les valeurs envoyées remplacent les valeurs par défaut de l'agent ; un placeholder sans l'une ni l'autre reste tel quel. Les clés ne peuvent pas commencer par system__ — celles-là sont remplies pour vous, et system__caller_id / system__called_number sont vides sur un appel navigateur, faute de ligne téléphonique. Contrairement à POST /calls/trigger, un placeholder system__ non pris en charge reste tel quel au lieu d'être rejeté. Ignoré quand la session elle-même est sans clé — un agent public atteint sans clé d'API, ou un jeton d'appel — car ces identifiants vivent dans le navigateur ; ces sessions utilisent les valeurs par défaut de l'agent. Atteindre ce même agent public avec votre clé d'API personnalise normalement : ce qui décide, c'est l'identifiant, pas l'agent.

Erreurs

7
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La clé API n'a pas la portée calls:write.

Utilisez une clé avec la portée requise.

402Paiement requis

Le compte est bloqué : abonnement annulé après la période de grâce, ou solde nul sans moyen de paiement.

Réabonnez-vous, ajoutez un moyen de paiement, ou rechargez des crédits, puis réessayez.

404Agent introuvable

L'agent_id n'existe pas ou n'appartient pas à ce compte.

Vérifiez via GET /api/v1/agents.

422Corps de requête invalide

agent_id absent ou UUID invalide, ou dynamic_variables invalide — pas un objet plat de chaînes, nombres et booléens, ou une clé utilisant le préfixe réservé system__.

Envoyez un corps JSON avec un agent_id valide. Si vous envoyez dynamic_variables, gardez un objet plat de valeurs scalaires et retirez toute clé system__.

429À pleine capacité

Le compte ou le backend partagé n'a pas de slot disponible. La réponse inclut retry_after et l'en-tête Retry-After.

Respectez l'en-tête Retry-After et réessayez.

503Aucune capacité disponible

Aucun slot backend ne peut être réservé.

Réessayez sous peu. Si persistant, contactez [email protected].

POST/conversation/token

Jeton éphémère à agent unique pour la signalisation directe depuis le navigateur — sans proxy.

Générer un jeton d'appel

Génère un jeton éphémère (un JWT signé) limité à un seul agent, pour qu'un navigateur puisse appeler /connect, /offer, /ice, /status et /end directement avec un en-tête Authorization: Bearer <token> — au lieu de relayer chaque requête de signalisation via un proxy. Appelez ceci côté serveur avec votre clé API ; n'envoyez jamais la clé au navigateur. Le jeton dure assez longtemps pour couvrir tout l'appel (par défaut, la durée maximale d'appel de votre agent plus une courte marge, limité à 60–4 320 secondes), ne fonctionne que pour l'agent pour lequel il a été généré et ne porte que les portées calls de la clé émettrice. Le navigateur peut appeler depuis n'importe quelle origine : c'est le jeton (un identifiant bearer, pas un cookie) qui authentifie la requête, il n'y a donc aucune liste d'autorisation CORS à configurer.

Corps de la requête

2
  • agent_idstring (UUID)requis

    L'UUID de l'agent autorisé par le jeton. Doit appartenir au compte appelant.

  • ttl_secondsintegeroptionnel

    Durée de vie du jeton en secondes. Optionnel ; par défaut, la durée maximale d'appel de l'agent plus une courte marge, limité à 60–4 320.

Erreurs

5
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La clé API n'a pas la portée calls:write.

Utilisez une clé avec la portée requise.

404Agent introuvable

L'agent_id n'existe pas ou n'appartient pas à ce compte.

Vérifiez via GET /api/v1/agents.

422Corps de requête invalide

agent_id absent ou UUID invalide, ou ttl_seconds n'est pas un nombre entier.

Envoyez un corps JSON avec un agent_id valide. Omettez ttl_seconds pour obtenir la durée d'appel de l'agent plus une marge, ou envoyez des secondes entières — une valeur hors de 60–4 320 est ramenée dans la plage, pas refusée.

429Débit limité

Générer un jeton est un POST classique avec clé API : cela compte dans la limite de débit de votre clé. Trop de générations dans un court laps de temps renvoient 429.

Générez un seul jeton par appel et réutilisez-le pour la signalisation de cet appel ; respectez l'en-tête Retry-After avant de réessayer.

POST/conversation/:session_id/offer

Envoyer votre offre SDP client ; recevoir la réponse SDP serveur et un pc_id pour les requêtes suivantes.

Soumettre l'offre SDP

Soumet une offre SDP pour la session créée par /connect. La réponse contient la réponse SDP et un pc_id à réutiliser pour la renégociation et l'ICE trickle.

Chemin & Requête

1
  • session_idstring (UUID)requis

    L'ID de session retourné par /connect.

Corps de la requête

4
  • sdpstringrequis

    La chaîne d'offre SDP générée par le RTCPeerConnection client.

  • typestringrequis

    Type SDP. "offer" pour les requêtes initiales.

  • pc_idstringoptionnel

    Identifiant PeerConnection retourné par la première réponse d'offre. Omis sur la toute première offre ; requis pour la renégociation.

  • restart_pcbooleanoptionnel

    Si true, force le serveur à recréer la connexion peer. Utilisé pour récupérer d'un état ICE bloqué.

Erreurs

7
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La session appartient à un compte différent.

Utilisez une clé du compte propriétaire.

404Session introuvable ou expirée

Aucun enregistrement pour ce session_id. La session n'a jamais été créée, a expiré, ou a déjà été terminée.

Appelez à nouveau /connect pour créer une nouvelle session et réessayez l'offre.

422Corps SDP invalide

Le corps est manquant sdp ou type, ou échoue la validation.

Générez l'offre via RTCPeerConnection.createOffer() et passez le { sdp, type } résultant tel quel.

429À pleine capacité

Le compte ou le backend est à pleine capacité. La réponse inclut retry_after.

Respectez l'en-tête Retry-After et réessayez.

500Échec du démarrage de la session

La connexion peer a été créée mais le pipeline agent a échoué à démarrer. La capacité est libérée automatiquement.

Réessayez l'offre. Si persistant, contactez [email protected].

503Aucune capacité disponible

Aucun slot backend ne peut être réservé.

Réessayez sous peu.

PATCH/conversation/:session_id/ice

Streamer les candidats ICE au fur et à mesure de leur découverte. Exemptés des limites de débit par compte.

Trickle ICE Candidates

Streame les candidats ICE découverts par le RTCPeerConnection client après l'échange SDP initial. Ces requêtes sont exemptées du limiteur de débit car l'ICE trickle est sensible au temps.

Chemin & Requête

1
  • session_idstring (UUID)requis

    L'ID de session. Utilisé pour le routage.

Corps de la requête

2
  • pc_idstringrequis

    Identifiant PeerConnection depuis la réponse /offer. Requis sur chaque PATCH.

  • candidatesIceCandidate[]requis

    Tableau de candidats ICE. Chaque élément a candidate (string), sdp_mid (string), et sdp_mline_index (entier). Tous les noms de champs sont en snake_case.

Erreurs

6
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La clé API n'a pas la portée calls:write.

Utilisez une clé avec la portée requise.

400Connexion peer introuvable

Aucune connexion peer active ne correspond au pc_id. La session s'est probablement terminée ou le pipeline a planté.

Redémarrez le handshake en appelant /connect puis /offer à nouveau.

400Candidat ICE invalide

Fragment SDP malformé, sdp_mid invalide, etc.

Passez les candidats tels quels depuis RTCPeerConnection.onicecandidate ; ne les synthétisez pas.

422Corps de requête invalide

Le corps échoue la validation (pc_id manquant, tableau candidates malformé).

Respectez exactement la forme, y compris sdp_mid et sdp_mline_index en snake_case.

502Amont indisponible

L'hôte de session est temporairement inaccessible.

Réessayez une fois. Si persistant, redémarrez le handshake.

GET/conversation/:session_id/status

Inspecter une session : statut, durée, nombre de tours. Fonctionne pour les sessions actives et récemment terminées.

Obtenir le statut de la session

Retourne le statut actuel, la durée horloge murale, et le nombre de tours d'une session. Fonctionne pour les sessions actives et récemment terminées. Auth : calls:read.

Chemin & Requête

1
  • session_idstring (UUID)requis

    L'ID de session retourné par /connect.

Erreurs

3
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La clé API n'a pas la portée calls:read, ou la session appartient à un compte différent.

Utilisez une clé avec la portée requise sur le compte propriétaire.

404Session introuvable ou expirée

Aucun enregistrement de cette session : jamais créée, expirée, ou évincée.

Pour les enregistrements historiques, utilisez GET /api/v1/conversations/{id} et GET /api/v1/calls/{id}.

POST/conversation/:session_id/end

Terminer gracieusement une session active. Draine l'audio en transit et exécute les hooks post-appel.

Terminer la session

Termine gracieusement une session active. L'agent finit tout audio TTS en transit, puis les hooks post-appel s'exécutent (finalisation de transcription, upload d'enregistrement, facturation). Ce point de terminaison est idempotent pour les sessions terminales : si la session a déjà atteint un statut terminal (failed ou completed) et est toujours conservée dans le store de session (par défaut 1 heure après la terminaison), la terminer à nouveau renvoie 200 avec l'instantané terminal (session_id, status, reason) — pas une erreur. Après éviction du store de session, la terminaison renvoie 404. Appeler /end sur une session created (réservée mais jamais soumise) la fait passer à failed avec reason: "abandoned_before_offer" et renvoie 200.

Chemin & Requête

1
  • session_idstring (UUID)requis

    L'ID de session.

Erreurs

5
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La session appartient à un compte différent.

Utilisez une clé du compte propriétaire.

404Session introuvable ou expirée

Aucun enregistrement pour cette session : déjà terminée ou jamais existée.

Considérez comme déjà terminée.

409Session non active (aucun propriétaire actif)

La session n'a pas de propriétaire de pipeline actif et n'a pas encore atteint un état terminal (détail : "Session has no active pipeline owner and has not reached a terminal state (status='<'status'>')." ). Cause courante : session bloquée en offering après un crash du pipeline. Une seconde chaîne de détail — "Session is not active. The pipeline may have already ended." — est renvoyée sur le chemin de route obsolète lorsque l'entrée de routage pointe vers le pod local mais que la tâche de pipeline a déjà disparu. Terminer à nouveau une session terminale ne renvoie pas cette erreur — cela renvoie 200 avec l'instantané terminal.

La session est dans un état de blocage non terminal sans propriétaire de pipeline actif. Renvoyer /end renverra le même 409 jusqu'à ce que la session transite ou soit nettoyée. Utilisez GET /conversation/{session_id}/status pour surveiller l'état (nécessite le scope calls:read ; une clé API limitée à calls:write reçoit 403 Missing scope: 'calls:read'). Une fois que la session atteint un état terminal, /end devient idempotent et renvoie 200 avec l'instantané terminal.

502Amont indisponible

L'hôte de session est temporairement inaccessible.

Réessayez une fois. Si persistant, considérez comme déjà terminée.

POST/conversation/:session_id/tool-result

Retourner un résultat d'exécution d'outil côté client à l'agent pour continuer la conversation.

Soumettre le résultat d'outil

Retourne le résultat d'une invocation d'outil côté client à l'agent. Quand l'agent émet un appel d'outil, votre client l'exécute et POST le résultat ici. Le champ result doit être une chaîne, donc sérialisez tout payload structuré avant l'envoi.

Chemin & Requête

1
  • session_idstring (UUID)requis

    L'ID de session.

Corps de la requête

2
  • tool_call_idstringrequis

    Le tool_call_id depuis l'appel d'outil de l'agent. Requis pour que l'agent puisse associer la réponse à l'appel d'origine.

  • resultstringrequis

    Le résultat de l'outil, sérialisé. Les payloads JSON doivent être JSON.stringify-és avant l'envoi.

Erreurs

6
401Non autorisé

Clé API manquante ou invalide.

Envoyez un en-tête X-API-Key valide ou un bearer token.

403Interdit

La session appartient à un compte différent.

Utilisez une clé du compte propriétaire.

404Session introuvable ou expirée

Aucun enregistrement pour cette session.

Vérifiez l'ID de session.

409Session non active

La session ne fonctionne plus.

Soumettez le résultat avant la fin de la session.

422Corps invalide

Le champ tool_call_id ou result est manquant ou n'est pas une chaîne.

Passez les deux champs comme chaînes ; sérialisez les résultats structurés.

502Amont indisponible

L'hôte de session est temporairement inaccessible.

Réessayez une fois.