Toute la puissance de Qubly sans le widget : upload de documents, interrogation RAG en streaming, gestion de vos bases et dossiers. API REST + Server-Sent Events, JSON partout. Chaque appel documenté est testable en direct sur cette page : connectez une clé dans le Playground, puis utilisez les boutons « Tester ».
Chaque appel part de la console : créez un compte gratuit sur app.qubly.io, votre base « Base principale » et votre première clé API sont prêtes d'office.
POST /v1/chat ou le widgetToutes les routes passent par l'en-tête x-api-key.
Les clés ont la forme rag_<préfixe>_<secret> ; seul leur
SHA-256 est stocké, elles sont révocables instantanément.
curl https://api.qubly.io/v1/knowledge-bases \
-H "x-api-key: rag_votre_cle"
| Périmètre | Création | Accès |
|---|---|---|
FULL (défaut) | { "scope": "FULL" } | Tout, y compris la gestion (clés, bases, compte, facturation) |
CHAT | { "scope": "CHAT" } | Chat, recherche, upload, lecture et dossiers — jamais la gestion (403 forbidden_scope) |
CHAT : même volée, elle ne peut ni supprimer vos données ni gérer votre compte.Pipeline complet : vectorisation de la question → recherche dans la base → réponse générée uniquement à partir des extraits retrouvés, avec sources. La réponse arrive en Server-Sent Events. L'assistant connaît l'arborescence de dossiers de la base : demandez-lui « où se trouve le document X ».
| Champ | Type | Description |
|---|---|---|
| knowledgeBaseId | string | UUID de la base à interroger |
| messages | array | Historique ; le dernier message user est la question |
| topK | int (défaut 5) | Nombre d'extraits injectés dans le contexte |
| Type | Payload | Quand |
|---|---|---|
| sources | documents[] | Avant la réponse : documents (avec dossier) et scores utilisés |
| delta | content | Fragment de réponse (markdown) |
| done | messageId | Fin du flux |
| error | code, message | Erreur en cours de flux |
curl -N https://api.qubly.io/v1/chat \ -H "x-api-key: rag_votre_cle" \ -H "Content-Type: application/json" \ -d '{ "knowledgeBaseId": "90dfe604-…", "messages": [{ "role": "user", "content": "Quelles sont vos conditions de résiliation ?" }] }' data: {"type":"sources","documents":[{"id":"…","name":"CGV-2026.pdf","folder":"Factures / 2026","score":0.87}]} data: {"type":"delta","content":"Vos contrats sont résiliables"} data: {"type":"delta","content":" à tout moment après le 12ᵉ mois…"} data: {"type":"done","messageId":"…"}
error (le flux est déjà ouvert).
Consommez avec text/event-stream et fermez la connexion à done.Le cœur du RAG sans la génération : vectorise la question et renvoie les extraits les plus proches avec leur score. Idéal pour l'autocomplétion, la recherche interne, ou pour bâtir votre propre couche LLM — réponse JSON immédiate, aucun token de génération consommé.
| Champ | Type | Description |
|---|---|---|
| knowledgeBaseId | string | UUID de la base à interroger |
| query | string (2–2000) | La question / requête en langage naturel |
| topK | int (défaut 6, max 50) | Nombre d'extraits renvoyés |
curl https://api.qubly.io/v1/search \ -H "x-api-key: rag_votre_cle" \ -H "Content-Type: application/json" \ -d '{ "knowledgeBaseId": "90dfe604-…", "query": "conditions de résiliation", "topK": 3 }' → 200 { "results": [ { "documentId": "…", "documentName": "CGV-2026.pdf", "chunkIndex": 4, "score": 0.87, "content": "Les contrats sont résiliables à tout moment…" } ] }
429 + Retry-After).Multipart, champ file — 25 Mo max. Un second champ optionnel
folderId range le document dans un dossier dès l'upload. Formats acceptés :
| Famille | Formats | Traitement |
|---|---|---|
| Bureautique | .pdf .docx .xlsx | Parsing natif ; OCR automatique pour les PDF scannés |
| Texte & données | .txt .md .csv .json .xml .html | Structure conservée (titres, lignes, cellules) |
| Images | .png .jpg .webp .gif .bmp .tiff .heic | OCR Mistral (HEIC converti automatiquement) |
| Audio | .mp3 .wav .m4a .ogg .flac… | Transcription Voxtral |
| Vidéo | .mp4 .webm .mov .mkv .avi | Piste audio extraite (ffmpeg) puis transcription |
L'ingestion est asynchrone : la réponse
est immédiate (202, statut PENDING), le document est ensuite
parsé, découpé, vectorisé et indexé par le worker.
curl https://api.qubly.io/v1/knowledge-bases/90dfe604-…/documents \ -H "x-api-key: rag_votre_cle" \ -F "file=@CGV-2026.pdf;type=application/pdf" → 202 { "document": { "id": "…", "status": "PENDING", … } }
Importe une page web : le worker la scrape (rendu HTML nettoyé, tableaux
et titres conservés) et indexe son contenu. Seules les URL publiques
http/https sont acceptées (garde anti-SSRF : les adresses
internes sont refusées).
curl https://api.qubly.io/v1/knowledge-bases/90dfe604-…/import-url \ -H "x-api-key: rag_votre_cle" -H "Content-Type: application/json" \ -d '{"url": "https://exemple.fr/article"}' → 202 { "document": { "format": "URL", "status": "PENDING", … } }
Pour suivre l'avancement :
| Statut | Sens |
|---|---|
| PENDING | En file d'ingestion |
| INDEXED | Vectorisé et interrogeable (avec chunkCount) |
| FAILED | Échec (champ error explicatif) |
Liste des bases du tenant.
{ "name": "Support technique" }
Renomme la base ou active le rangement automatique : les nouveaux documents sont classés dans l'arborescence par l'IA après indexation.
{ "name": "Support technique", "autoClassify": true }
Supprime la base : purge de tous ses vecteurs puis cascade sur les documents.
Liste paginée (limit ≤ 100). Filtre optionnel
?folderId= (UUID d'un dossier, ou root pour les documents
non rangés). Réponse : { documents, total, limit, offset }.
Supprime le document et purge ses vecteurs immédiatement.
Chaque base possède une arborescence de dossiers (5 niveaux max). Les documents non rangés restent « à la racine ». L'IA peut classer automatiquement les documents (nom + extrait du contenu), et le chat connaît l'arborescence : il peut dire où se trouve un document.
Arborescence complète avec compteurs de documents par dossier, plus le nombre de documents non rangés.
→ { "tree": [{ "id": "…", "name": "Factures", "documentCount": 12,
"children": [{ "id": "…", "name": "2026", "documentCount": 5, … }] }],
"rootDocumentCount": 3 }
Crée, renomme ou déplace un dossier (les cycles sont refusés).
Supprime le dossier : ses documents et sous-dossiers remontent d'un niveau (aucun document n'est supprimé).
Déplace un document (null = retour à la racine).
Rangement automatique : l'IA classe les documents non rangés (ou toute la
base avec {"all":true}) par lots, en réutilisant les dossiers
existants. Réponse : { "summary": { "classified", "foldersCreated", "skipped" } }.
10 clés actives max par tenant. La clé créée s'affiche une seule fois
(seul le hash est conservé). Créez une clé dédiée par intégration — le widget,
par exemple, doit avoir la sienne (périmètre CHAT), révocable
indépendamment. Ces routes exigent une clé FULL ou la session console.
Consommation courante et limites du plan (bases, documents, chunks, chats du jour).
Au-delà : 402 quota_exceeded. Burst : 10 chats/min et
10 uploads/min par tenant (429 + en-tête Retry-After).
Pas une ligne d'intégration à écrire — un <script> sur votre site :
<script src="https://widget.qubly.io/widget.js" data-api-url="https://api.qubly.io" data-api-key="rag_cle_dediee_widget" data-kb-id="90dfe604-…" data-title="Assistant Qubly" data-greeting="Bonjour — comment puis-je vous aider ?" data-placeholder="Posez votre question…" data-color="#4f46e5" <!-- couleur d'accent (défaut zinc) --> data-position="right" <!-- left | right --> async ></script>
22 Ko (9,7 gzip), rendu markdown, aucune dépendance. La conversation du visiteur est conservée dans son navigateur (localStorage, par base de connaissances) : il retrouve son historique en revenant sur la page, et peut l'effacer d'un clic. Testez-le sur la page de démo.
Cliquez sur « Utiliser ma session Qubly » (si vous êtes
connecté à la console) : tous les boutons « Tester » de cette page
fonctionnent immédiatement via votre session. Sans session, collez une clé
API (périmètre CHAT suffit pour lecture/chat/upload) — elle reste
dans votre navigateur (localStorage, jamais envoyée ailleurs
qu'à api.qubly.io).
Les clés existantes sont hachées côté serveur : leur valeur complète ne peut pas être relue (cette liste est indicative). Vos appels « Tester » passent déjà par votre session ; pour un usage hors navigateur (curl, backend), créez une clé Playground dédiée ci-dessus.
| HTTP | error | Cause |
|---|---|---|
| 400 | bad_request | Corps invalide (détails dans details) |
| 401 | unauthorized | Clé absente, invalide ou révoquée |
| 402 | quota_exceeded | Quota du plan atteint |
| 403 | forbidden_scope | Route de gestion appelée avec une clé CHAT |
| 404 | not_found | Ressource inconnue ou hors de votre tenant |
| 413 | payload_too_large | Fichier > 25 Mo |
| 415 | unsupported_media_type | Format non supporté (bureautique, texte, données, image, audio, vidéo) |
| 429 | rate_limited | Burst dépassé — respecter Retry-After |
| 501 | billing_not_configured | Fonctionnalité non activée sur l'instance |
Une question, un cas d'usage non couvert ? La console affiche vos identifiants et l'état de vos bases en temps réel.