GPT de Babi Developers
API Partner v1

Intégrez Compass
dans votre produit.

L’API GPT de Babi Partner expose notre harness d’assistance locale via REST et WebSocket. Vos utilisateurs restent authentifiés chez vous : vous nous transmettez uniquement un identifiant externe stable et opaque.

Architecture recommandée

Gardez toujours le client_secret sur votre serveur. Votre backend échange vos identifiants contre un token utilisateur court, puis le transmet à votre application mobile.

Un premier message en 3 étapes

Utilisez d’abord les identifiants sandbox disponibles dans votre console.

1 · Créer un token utilisateur
curl -X POST https://gpt-de-babi.perfproai.com/api/partners/v1/tokens \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"external_user_id":"user_8f2c","locale":"fr-CI"}'
2 · Créer une conversation
curl -X POST https://gpt-de-babi.perfproai.com/api/partners/v1/conversations \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Ma première conversation"}'
3 · Envoyer un message
curl -X POST https://gpt-de-babi.perfproai.com/api/partners/v1/conversations/$CONVERSATION_ID/messages \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client_message_id":"msg_001","message":"Où renouveler mon passeport à Abidjan ?"}'

Authentification à deux niveaux

1Identifiants applicationBasic client_id:client_secret — serveur uniquement
2Token utilisateurBearer court — limité à un utilisateur partenaire
3CompassConversations strictement isolées par partenaire

Préparer votre terminal

Copiez vos identifiants depuis la console, puis définissez ces variables. Elles seront réutilisées dans tous les exemples.

Terminal · Variables sandbox
export GPT_DE_BABI_BASE_URL="https://gpt-de-babi.perfproai.com"
export GPT_DE_BABI_CLIENT_ID="gdb_sandbox_REMPLACEZ_MOI"
export GPT_DE_BABI_CLIENT_SECRET="REMPLACEZ_MOI"

# Vérification locale — ne partagez jamais le secret
test -n "$GPT_DE_BABI_CLIENT_SECRET" && echo "Configuration prête"
Important

Le client_secret ne doit jamais être inclus dans une application mobile, un frontend web, un dépôt Git ou des logs. Seul votre backend l’utilise.

POST/api/partners/v1/tokens

Créer une session utilisateur

À chaque connexion dans votre application, votre backend échange un identifiant utilisateur interne contre un token GPT de Babi court. N’envoyez ni e-mail, ni téléphone, ni nom : un identifiant opaque suffit.

Auth Basic applicationRéponse 201 CreatedÀ appeler depuis Votre backend
ChampTypeObligatoireDescription
external_user_idstringouiStable, opaque, max. 255 caractères
localestringnonEx. fr-CI
timezonestringnonEx. Africa/Abidjan
cURL · Créer le token
curl --request POST "$GPT_DE_BABI_BASE_URL/api/partners/v1/tokens" \
  --user "$GPT_DE_BABI_CLIENT_ID:$GPT_DE_BABI_CLIENT_SECRET" \
  --header "Content-Type: application/json" \
  --data '{
    "external_user_id": "usr_8f32a9",
    "locale": "fr-CI",
    "timezone": "Africa/Abidjan"
  }'
Réponse 201
{
  "access_token": "eyJ...token_opaque...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "expires_at": "2026-08-28T21:30:00Z",
  "scopes": ["chat:read", "chat:write", "feedback:write"],
  "user": {"id": "7f70b5b8-..."}
}

Conservez access_token côté serveur ou transmettez-le temporairement à la session mobile. Demandez-en un nouveau à son expiration.

POST/api/partners/v1/conversations

Créer ou reprendre une conversation

Créez une conversation après avoir obtenu le token utilisateur. Vous pouvez générer un UUID côté client et le renvoyer lors d’une reprise : la même conversation sera retournée sans doublon.

Auth Bearer utilisateurScope chat:writeRéponse 201 Created
ChampTypeObligatoireDescription
titlestringnonNom affiché dans votre interface
conversation_idUUIDnonUUID généré par votre application pour une reprise idempotente
cURL · Créer une conversation
export USER_TOKEN="COLLEZ_LE_TOKEN_UTILISATEUR"

curl --request POST "$GPT_DE_BABI_BASE_URL/api/partners/v1/conversations" \
  --header "Authorization: Bearer $USER_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "title": "Démarches administratives"
  }'
Réponse 201
{
  "conversation_id": "0d1fc89d-bbb6-4826-a4e7-7e25738c2755",
  "title": "Démarches administratives",
  "created_at": "2026-08-28T20:31:12Z"
}
POST/api/partners/v1/conversations/{id}/messages

Envoyer un message

Le mode REST persiste puis met le traitement en file d’attente. Un statut 202 signifie que Compass travaille encore. Utilisez ensuite l’endpoint du turn ou le WebSocket pour recevoir le résultat.

Auth Bearer utilisateurScope chat:writeRéponse 202 ou 200
ChampTypeObligatoireDescription
client_message_idstringouiClé d’idempotence unique, générée par votre application
messagestringouiQuestion de l’utilisateur
locationobjectnonContexte géographique, par exemple ville et commune
metadataobjectnonplatform et app_version
cURL · Envoyer puis récupérer le résultat
export CONVERSATION_ID="0d1fc89d-bbb6-4826-a4e7-7e25738c2755"

RESPONSE=$(curl --silent --request POST \
  "$GPT_DE_BABI_BASE_URL/api/partners/v1/conversations/$CONVERSATION_ID/messages" \
  --header "Authorization: Bearer $USER_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "client_message_id": "msg_001",
    "message": "Où renouveler mon passeport à Abidjan ?",
    "location": {"city": "Abidjan", "commune": "Cocody"},
    "metadata": {"platform": "ios", "app_version": "2.4.0"}
  }')

echo "$RESPONSE"
# Copiez turn_id depuis la réponse, puis :
export TURN_ID="REMPLACEZ_PAR_TURN_ID"
curl "$GPT_DE_BABI_BASE_URL/api/partners/v1/turns/$TURN_ID" \
  --header "Authorization: Bearer $USER_TOKEN"
Réponse 202 pendant le traitement
{
  "turn_id": "13ae186f-...",
  "conversation_id": "0d1fc89d-...",
  "status": "queued",
  "created_at": "2026-08-28T20:32:05Z",
  "updated_at": "2026-08-28T20:32:05Z"
}

Streaming WebSocket

Ouvrez la connexion avec les sous-protocoles ["gpt-de-babi.partner.v1", token]. Les tokens dans l’URL ne sont pas acceptés.

JavaScript · Streaming prêt à coller
const socket = new WebSocket(
  "wss://gpt-de-babi.perfproai.com/api/partners/v1/chat",
  ["gpt-de-babi.partner.v1", userToken]
);

socket.addEventListener("open", () => {
  socket.send(JSON.stringify({
    type: "user.message",
    conversation_id: conversationId,
    client_message_id: crypto.randomUUID(),
    message: "Quelle pharmacie est de garde à Cocody ?",
    location: { city: "Abidjan", commune: "Cocody" }
  }));
});

socket.addEventListener("message", ({ data }) => {
  const event = JSON.parse(data);
  if (event.type === "assistant.status") showStatus(event.label);
  if (event.type === "assistant.delta") appendText(event.text);
  if (event.type === "assistant.completed") showAnswer(event.message);
  if (event.type === "assistant.error") showError(event.error.message);
});

socket.addEventListener("close", () => {
  // Récupérez le turn par REST après une déconnexion.
  reconnectWithBackoff();
});
turn.acceptedturn.snapshotturn.runningassistant.statusassistant.deltaassistant.completedassistant.errorpong
GET/api/partners/v1/conversations/{id}/messages

Restaurer l’historique

Récupérez les messages chronologiquement pour restaurer l’écran de conversation après une reconnexion. La pagination utilise limit (1 à 100) et offset.

Auth Bearer utilisateurScope chat:readRéponse 200 OK
cURL · Charger 50 messages
curl --get \
  "$GPT_DE_BABI_BASE_URL/api/partners/v1/conversations/$CONVERSATION_ID/messages" \
  --header "Authorization: Bearer $USER_TOKEN" \
  --data-urlencode "limit=50" \
  --data-urlencode "offset=0"
Réponse 200
{
  "messages": [{
    "message_id": "a9421d2c-...",
    "role": "assistant",
    "content": "Voici les informations disponibles…",
    "status": "completed",
    "cards": [],
    "visualizations": [],
    "suggested_actions": [],
    "created_at": "2026-08-28T20:32:12Z"
  }]
}
POST/api/partners/v1/messages/{id}/feedback

Envoyer un feedback

Enregistrez un pouce positif ou négatif sur un message assistant. Un nouvel envoi pour le même message remplace le feedback précédent.

Auth Bearer utilisateurScope feedback:writeRéponse 201 Created
ChampValeursObligatoire
ratingup ou downoui
reasonCatégorie courtenon
commentCommentaire, max. 2 000 caractèresnon
cURL · Pouce négatif
export MESSAGE_ID="ID_DU_MESSAGE_ASSISTANT"

curl --request POST \
  "$GPT_DE_BABI_BASE_URL/api/partners/v1/messages/$MESSAGE_ID/feedback" \
  --header "Authorization: Bearer $USER_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "rating": "down",
    "reason": "outdated_information",
    "comment": "L’adresse affichée n’est plus à jour."
  }'
Réponse 201
{"success": true, "feedback": {"rating": "down"}}
DELETE/api/partners/v1/users/{external_user_id}

Supprimer les données utilisateur

Déclenchez cette route depuis votre backend lorsqu’un utilisateur supprime son compte ou exerce son droit à l’effacement. Les conversations et données GPT de Babi liées à cette identité partenaire sont supprimées.

Auth Basic applicationÀ appeler depuis Votre backendRéponse 200 OK
cURL · Workflow de suppression
export EXTERNAL_USER_ID="usr_8f32a9"

curl --request DELETE \
  "$GPT_DE_BABI_BASE_URL/api/partners/v1/users/$EXTERNAL_USER_ID" \
  --user "$GPT_DE_BABI_CLIENT_ID:$GPT_DE_BABI_CLIENT_SECRET"
Réponse 200
{"deleted": true}

deleted: false signifie que cette identité n’existait déjà plus. L’opération reste considérée comme réussie.

GET/api/partners/v1/capabilities

Inspecter les capacités

Utilisez cette route au démarrage de votre intégration pour connaître l’environnement, les verticals autorisés et les limites actives. Votre interface peut masquer les fonctionnalités indisponibles.

Auth Bearer utilisateurScope chat:readRéponse 200 OK
cURL · Lire les capacités
curl "$GPT_DE_BABI_BASE_URL/api/partners/v1/capabilities" \
  --header "Authorization: Bearer $USER_TOKEN"
Réponse 200
{
  "api_version": "v1",
  "partner": {"id": "8cf7…", "name": "Expat d'Abidjan"},
  "environment": "sandbox",
  "locales": ["fr-CI"],
  "capabilities": ["administration", "local_life"],
  "limits": {
    "message_characters": 12000,
    "requests_per_minute": 20,
    "concurrent_turns": 2
  }
}

Votre authentification reste la source de vérité

Lorsqu’un utilisateur se connecte à votre application, votre serveur dérive son identifiant interne depuis la session authentifiée. Il ne doit jamais faire confiance à un external_user_id envoyé librement par le mobile. Nous créons une correspondance isolée dans votre tenant : le même identifiant utilisé par deux partenaires représente deux utilisateurs distincts.

Node.js · Route backend complète
app.post("/api/compass/session", requireAuthenticatedUser, async (req, res) => {
  // Source sûre : l’utilisateur authentifié par VOTRE middleware.
  const externalUserId = `user_${req.user.id}`;
  const basic = Buffer.from(
    `${process.env.GPT_DE_BABI_CLIENT_ID}:${process.env.GPT_DE_BABI_CLIENT_SECRET}`
  ).toString("base64");

  const response = await fetch(
    "https://gpt-de-babi.perfproai.com/api/partners/v1/tokens",
    {
      method: "POST",
      headers: {
        Authorization: `Basic ${basic}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        external_user_id: externalUserId,
        locale: req.user.locale || "fr-CI",
        timezone: "Africa/Abidjan"
      })
    }
  );

  const payload = await response.json();
  if (!response.ok) return res.status(502).json({ error: "compass_unavailable" });
  res.json(payload); // token court transmis à la session mobile
});

Erreurs, idempotence et nouvelles tentatives

Toutes les erreurs suivent le même contrat. Conservez le request_id pour le support et ne réessayez automatiquement que si retryable vaut true.

Format d’erreur
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "The partner rate limit was exceeded.",
    "retryable": true,
    "request_id": "f8971bc1-..."
  }
}
HTTPCode courantAction recommandée
401unauthorizedRenouveler le token ou vérifier les identifiants
403insufficient_scopeVérifier les scopes de l’application
404not_foundVérifier que la ressource appartient au même utilisateur
409idempotency_conflictGénérer un nouveau client_message_id
422invalid_requestCorriger le payload, sans nouvelle tentative automatique
429rate_limit_exceededBackoff exponentiel avec jitter
503queue_unavailableRéessayer progressivement
JavaScript · Retry avec backoff
async function compassFetch(url, options, maxAttempts = 4) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch(url, options);
    const payload = await response.json();
    if (response.ok) return payload;

    const canRetry = payload?.error?.retryable === true;
    if (!canRetry || attempt === maxAttempts) throw new Error(
      `${payload?.error?.code || "api_error"} (${payload?.error?.request_id || "no_request_id"})`
    );

    const delayMs = Math.min(1000 * 2 ** (attempt - 1), 8000) + Math.random() * 300;
    await new Promise(resolve => setTimeout(resolve, delayMs));
  }
}
Idempotence des messages

Réutilisez le même client_message_id uniquement pour rejouer exactement le même message. Si le contenu change, générez une nouvelle clé, sinon l’API répondra 409 idempotency_conflict.