Public Conversations API
Documentation de l'API pour les conversations publiques et les agents embedables dans Devana.ai.
Base URL: https://api.devana.ai
Préfixe: /v1/chat/conversation
Authentification: Variable selon l'endpoint
📑 Table des matières
- Vue d'ensemble
- Système de tokens de sécurité
- Endpoints disponibles
- Streaming SSE
- Gestion des erreurs
- Exemples d'intégration
Vue d'ensemble
L'API Public Conversations permet d'intégrer des agents Devana.ai dans des applications tierces via :
- Widgets embedables : Chat widgets pour sites web
- Applications mobiles : SDK pour iOS/Android
- Intégrations custom : Via API REST avec tokens sécurisés
Caractéristiques principales :
- Conversations sans authentification utilisateur
- Streaming en temps réel (Server-Sent Events)
- Système de tokens sécurisés avec limite de tentatives
- Support du feedback (like/dislike)
Système de tokens de sécurité
Concept
Les conversations publiques utilisent un système de tokens pour sécuriser l'accès sans nécessiter d'authentification utilisateur :
- Token de sécurité : Généré par l'API, permet l'accès à une conversation
- Limite de tentatives : Maximum 5 tentatives suspectes avant blocage
- Validation : Chaque requête vérifie la validité du token
Cycle de vie d'un token
Loading diagram...
Endpoints disponibles
GET /v1/chat/conversation/messages/:id - Messages privés
Récupère les messages d'une conversation privée (nécessite OAuth).
Paramètres
| Paramètre | Type | Requis | Description |
|---|---|---|---|
id | String | Oui | Format: {conversationId}:{messageId} (messageId optionnel) |
Headers
Authorization: Bearer OAUTH_TOKEN
Requête - Conversation complète
GET /v1/chat/conversation/messages/cm4conv123abc
Authorization: Bearer YOUR_OAUTH_TOKEN
Requête - Message spécifique
GET /v1/chat/conversation/messages/cm4conv123abc:cm4msg456def
Authorization: Bearer YOUR_OAUTH_TOKEN
Réponse (200 OK) - Conversation complète
{
"messages": [
{
"id": "cm4msg123",
"role": "user",
"content": "Bonjour, comment puis-je optimiser mon code ?",
"timestamp": "2024-10-28T10:00:00.000Z"
},
{
"id": "cm4msg124",
"role": "assistant",
"content": "Voici quelques suggestions pour optimiser votre code...",
"timestamp": "2024-10-28T10:00:15.000Z",
"sources": ["doc1.pdf", "guide.md"]
}
]
}
Réponse (200 OK) - Message unique
{
"message": {
"id": "cm4msg124",
"role": "assistant",
"content": "Voici quelques suggestions pour optimiser votre code...",
"timestamp": "2024-10-28T10:00:15.000Z"
}
}
GET /v1/chat/conversation/public/messages/:token - Messages publics
Récupère les messages d'une conversation publique via token de sécurité.
Paramètres
| Paramètre | Type | Requis | Description |
|---|---|---|---|
token | String | Oui | Token de sécurité généré |
Requête
GET /v1/chat/conversation/public/messages/sec_token_abc123xyz789
Réponse (200 OK)
{
"messages": [
{
"id": "cm4msg789",
"role": "user",
"content": "Quelle est votre politique de retour ?",
"timestamp": "2024-10-28T14:30:00.000Z"
},
{
"id": "cm4msg790",
"role": "assistant",
"content": "Notre politique de retour est de 30 jours...",
"timestamp": "2024-10-28T14:30:10.000Z",
"sources": ["faq.pdf", "conditions-generales.docx"]
}
]
}
Erreurs spécifiques
| Code | Message | Description |
|---|---|---|
403 | Access denied | Token invalide ou trop de tentatives suspectes (>5) |
404 | Conversation not found | La conversation n'existe pas |
POST /v1/chat/conversation/public/message - Envoyer un message
Envoie un message dans une conversation publique avec streaming de la réponse.
Headers
Content-Type: application/json
X-Security-Token: sec_token_abc123xyz789
Body
{
"messages": [
{
"role": "user",
"content": "Comment fonctionne votre service ?"
}
],
"stream": true,
"custom": {
"temperature": 0.7,
"max_tokens": 500
},
"lang": "fr"
}
Paramètres du body
| Paramètre | Type | Requis | Description |
|---|---|---|---|
messages | Array | Oui | Historique des messages de la conversation |
stream | Boolean | Oui | Doit être true (streaming uniquement) |
custom | Object | Non | Paramètres personnalisés (temperature, max_tokens, etc.) |
lang | String | Non | Langue de la réponse (fr, en, es, etc.) |
Réponse (200 OK) - Server-Sent Events
Content-Type: text/event-stream
Bonjour ! Notre service fonctionne
de manière très simple.
Vous pouvez poser vos questions
et je vous répondrai en temps réel.
[DONE]
Format du streaming
Le streaming utilise le format Server-Sent Events (SSE) :
- Chaque fragment de texte est envoyé au fur et à mesure
- Le signal
[DONE]indique la fin de la réponse - La connexion reste ouverte pendant toute la durée du streaming
GET /v1/chat/conversation/public/message/token - Générer un token
Génère un token de sécurité pour accéder à une conversation publique.
Headers
Authorization: Bearer YOUR_API_KEY
Query Parameters
| Paramètre | Type | Requis | Description |
|---|---|---|---|
agentId | String | Oui | ID de l'agent public |
conversationId | String | Non | ID de conversation existante (pour reprendre) |
Requête - Nouvelle conversation
GET /v1/chat/conversation/public/message/token?agentId=cm4agent123
Authorization: Bearer YOUR_API_KEY
Requête - Conversation existante
GET /v1/chat/conversation/public/message/token?agentId=cm4agent123&conversationId=cm4conv456
Authorization: Bearer YOUR_API_KEY
Réponse (200 OK)
{
"token": "sec_token_new123abc456",
"conversationId": "cm4conv789xyz",
"agentId": "cm4agent123",
"expiresAt": "2024-10-29T10:00:00.000Z",
"remainingAttempts": 5
}
POST /v1/chat/conversation/public/message/fiability - Feedback
Permet aux utilisateurs de donner un feedback sur les réponses (like/dislike).
Headers
Content-Type: application/json
X-Security-Token: sec_token_abc123xyz789
Body
{
"messageId": "cm4msg790",
"fiability": "GOOD",
"comment": "Réponse très claire et précise"
}
Paramètres
| Paramètre | Type | Requis | Description |
|---|---|---|---|
messageId | String | Oui | ID du message à évaluer |
fiability | String | Oui | GOOD (like) ou BAD (dislike) |
comment | String | Non | Commentaire optionnel |
Réponse (200 OK)
{
"success": true,
"message": "Feedback enregistré avec succès"
}
Streaming SSE
Implémentation côté client
// Exemple JavaScript pour consommer le stream
async function sendMessageWithStreaming(token, message) {
const response = await fetch("/v1/chat/conversation/public/message", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Security-Token": token,
},
body: JSON.stringify({
messages: [{ role: "user", content: message }],
stream: true,
lang: "fr",
}),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let fullResponse = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// Vérifier si c'est la fin du stream
if (chunk.includes("[DONE]")) {
.();
;
}
fullResponse += chunk;
.(, chunk);
(chunk);
}
fullResponse;
}
Gestion des erreurs de streaming
class StreamHandler {
constructor(token) {
this.token = token;
this.retryCount = 0;
this.maxRetries = 3;
}
async sendMessage(message) {
try {
const response = await this.makeRequest(message);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await this.processStream(response);
} catch (error) {
if (this.retryCount < this.maxRetries) {
this.retryCount++;
console.log(`Retry ${this.retryCount}/${this.maxRetries}`);
await .( * .);
.(message);
}
error;
}
}
() {
reader = response..();
decoder = ();
result = ;
{
() {
{ done, value } = reader.();
(done) ;
chunk = decoder.(value, { : });
(chunk.()) {
;
}
result += chunk;
}
} {
reader.();
}
result;
}
() {
( (resolve, ms));
}
}
Gestion des erreurs
Codes d'erreur communs
| Code | Message | Description | Solution |
|---|---|---|---|
401 | Unauthorized | Token ou API key manquant/invalide | Vérifier les credentials |
403 | Access denied | Trop de tentatives ou accès refusé | Générer un nouveau token |
404 | Not found | Conversation/message introuvable | Vérifier l'ID |
429 | Too Many Requests | Rate limit dépassé | Implémenter un backoff |
500 | Internal Server Error | Erreur serveur | Réessayer plus tard |
Gestion des tentatives suspectes
Le système bloque automatiquement les tokens après 5 tentatives suspectes :
class TokenManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.tokens = new Map();
}
async getToken(agentId, conversationId = null) {
const key = `${agentId}-${conversationId || "new"}`;
// Vérifier si on a déjà un token valide
if (this.tokens.has(key)) {
const tokenData = this.tokens.get(key);
if (tokenData.remainingAttempts > 1) {
return tokenData.token;
}
}
// Générer un nouveau token
const response = await fetch("/v1/chat/conversation/public/message/token", {
method: "GET",
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
params: {
agentId,
conversationId,
},
});
data = response.();
..(key, data);
data.;
}
() {
( [key, value] ..()) {
(value. === token) {
..(key);
;
}
}
}
}
Exemples d'intégration
Widget de chat pour site web
<!DOCTYPE html>
<html>
<head>
<title>Chat Widget Devana.ai</title>
<style>
#chat-widget {
position: fixed;
bottom: 20px;
right: 20px;
width: 350px;
height: 500px;
border: 1px solid #ddd;
border-radius: 10px;
background: white;
display: flex;
flex-direction: column;
}
#chat-messages {
flex: 1;
overflow-y: auto;
padding: 10px;
}
.message {
margin: 10px 0;
padding: 8px 12px;
border-radius: 8px;
}
.user-message {
background: #007bff;
color: white;
: flex-end;
: auto;
}
{
: ;
: black;
}
{
: flex;
: ;
: solid ;
}
{
: ;
: ;
: solid ;
: ;
}
{
: ;
: ;
: ;
: white;
: none;
: ;
: pointer;
}
Envoyer
Application mobile React Native
import React, { useState, useEffect, useRef } from "react";
import {
View,
Text,
TextInput,
TouchableOpacity,
ScrollView,
StyleSheet,
ActivityIndicator,
} from "react-native";
const DevanaChat = ({ apiKey, agentId }) => {
const [messages, setMessages] = useState([]);
const [inputText, setInputText] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [token, setToken] = useState(null);
const scrollViewRef = useRef();
useEffect(() => {
initializeChat();
}, []);
const initializeChat = async () => {
try {
const response = await fetch(
`https://api.devana.ai/v1/chat/conversation/public/message/token?agentId=${agentId}`,
{
headers: {
Authorization: ,
},
}
);
data = response.();
(data.);
([
{
: ,
: ,
: ,
},
]);
} (error) {
.(, error);
}
};
= () => {
(!inputText.() || !token) ;
userMessage = {
: .().(),
: ,
: inputText,
};
( [...prev, userMessage]);
();
();
{
response = (
,
{
: ,
: {
: ,
: token,
},
: .({
: [...messages, userMessage].( ({
: m.,
: m.,
})),
: ,
: ,
}),
}
);
reader = response..();
decoder = ();
assistantMessage = ;
() {
{ done, value } = reader.();
(done) ;
chunk = decoder.(value);
(chunk.()) ;
assistantMessage += chunk;
( {
newMessages = [...prev];
lastMessage = newMessages[newMessages. - ];
(lastMessage. === ) {
lastMessage. = assistantMessage;
} {
newMessages.({
: .().(),
: ,
: assistantMessage,
});
}
newMessages;
});
}
} (error) {
.(, error);
( [
...prev,
{
: .().(),
: ,
: ,
},
]);
} {
();
}
};
(
);
};
styles = .({
: {
: ,
: ,
},
: {
: ,
: ,
},
: {
: ,
: ,
: ,
: ,
},
: {
: ,
: ,
},
: {
: ,
: ,
},
: {
: ,
},
: {
: ,
: ,
: ,
: ,
: ,
},
: {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
},
: {
: ,
: ,
: ,
: ,
: ,
},
: {
: ,
: ,
},
: {
: ,
},
});
;
Bonnes pratiques
-
Gestion des tokens
- Réutiliser les tokens tant qu'ils sont valides
- Régénérer après erreur 403
- Stocker de manière sécurisée côté client
-
Streaming
- Implémenter un timeout pour éviter les connexions pendantes
- Gérer proprement la fermeture des streams
- Afficher un indicateur de chargement
-
Gestion d'erreur
- Retry avec backoff exponentiel
- Messages d'erreur user-friendly
- Logging des erreurs pour debugging
-
Performance
- Limiter l'historique des messages envoyés
- Implémenter un cache local des réponses
- Utiliser la compression si disponible
Support et assistance
Pour toute question ou problème concernant l'API Public Conversations :
- Consultez la documentation générale de l'API
- Guide d'intégration iframe : iframe.md
- Contactez le support technique : support@devana.ai
- Reportez les bugs sur notre GitHub