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.
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.
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"}'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"}'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
Préparer votre terminal
Copiez vos identifiants depuis la console, puis définissez ces variables. Elles seront réutilisées dans tous les exemples.
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"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.
/api/partners/v1/tokensCré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.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
external_user_id | string | oui | Stable, opaque, max. 255 caractères |
locale | string | non | Ex. fr-CI |
timezone | string | non | Ex. Africa/Abidjan |
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"
}'{
"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-..."}
}/api/partners/v1/conversationsCré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.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
title | string | non | Nom affiché dans votre interface |
conversation_id | UUID | non | UUID généré par votre application pour une reprise idempotente |
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"
}'{
"conversation_id": "0d1fc89d-bbb6-4826-a4e7-7e25738c2755",
"title": "Démarches administratives",
"created_at": "2026-08-28T20:31:12Z"
}/api/partners/v1/conversations/{id}/messagesEnvoyer 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.
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
client_message_id | string | oui | Clé d’idempotence unique, générée par votre application |
message | string | oui | Question de l’utilisateur |
location | object | non | Contexte géographique, par exemple ville et commune |
metadata | object | non | platform et app_version |
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"{
"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.
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/api/partners/v1/conversations/{id}/messagesRestaurer 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.
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"{
"messages": [{
"message_id": "a9421d2c-...",
"role": "assistant",
"content": "Voici les informations disponibles…",
"status": "completed",
"cards": [],
"visualizations": [],
"suggested_actions": [],
"created_at": "2026-08-28T20:32:12Z"
}]
}/api/partners/v1/messages/{id}/feedbackEnvoyer 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.
| Champ | Valeurs | Obligatoire |
|---|---|---|
rating | up ou down | oui |
reason | Catégorie courte | non |
comment | Commentaire, max. 2 000 caractères | non |
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."
}'{"success": true, "feedback": {"rating": "down"}}/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.
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"{"deleted": true}/api/partners/v1/capabilitiesInspecter 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.
curl "$GPT_DE_BABI_BASE_URL/api/partners/v1/capabilities" \
--header "Authorization: Bearer $USER_TOKEN"{
"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.
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.
{
"error": {
"code": "rate_limit_exceeded",
"message": "The partner rate limit was exceeded.",
"retryable": true,
"request_id": "f8971bc1-..."
}
}| HTTP | Code courant | Action recommandée |
|---|---|---|
| 401 | unauthorized | Renouveler le token ou vérifier les identifiants |
| 403 | insufficient_scope | Vérifier les scopes de l’application |
| 404 | not_found | Vérifier que la ressource appartient au même utilisateur |
| 409 | idempotency_conflict | Générer un nouveau client_message_id |
| 422 | invalid_request | Corriger le payload, sans nouvelle tentative automatique |
| 429 | rate_limit_exceeded | Backoff exponentiel avec jitter |
| 503 | queue_unavailable | Réessayer progressivement |
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));
}
}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.