Docs / Référence API

Référence API

Tous les points d'accès API utilisent le format JSON. L'authentification utilise une clé API Bearer aqn_. Voir Authentification pour plus de détails.

URL de base : https://your-instance/api/


Authentification

Incluez votre clé API dans toutes les requêtes :

Authorization: Bearer aqn_your_api_key

Les clés API sont créées et gérées depuis la page Clés API (/keys/). Les clés à accès complet voient toutes les collections ; les clés limitées ne voient que les collections autorisées.


Schéma OpenAPI

Le schéma OpenAPI complet est disponible à /api/v1/schema/ dans tous les environnements (y compris la production). Utilisez-le pour intégrer n'importe quel outil compatible OpenAPI :

  • Génération de SDK (openapi-generator, kiota, etc.)
  • ChatGPT Custom GPT Actions
  • Import Postman / Insomnia
  • Tout outil ou flux de travail compatible OpenAPI
GET /api/v1/schema/

Renvoie un document OpenAPI 3.0 valide au format JSON. Aucune authentification requise. Swagger UI (/api/v1/docs/) et ReDoc (/api/v1/redoc/) sont disponibles uniquement dans les environnements de débogage/développement.


Collections

Lister les collections

GET /api/v1/collections/

Renvoie les collections visibles par l'utilisateur authentifié (possédées + publiques souscrites).

Réponse : 200 OK

[
  {
    "uuid": "a1b2c3...",
    "name": "Project Docs",
    "slug": "project-docs",
    "description": "Technical documentation",
    "document_count": 15,
    "total_chunks": 342,
    "is_public": false,
    "is_subscribed": false,
    "created_at": "2026-03-01T10:00:00Z"
  }
]

Créer une collection

POST /api/v1/collections/

404 — Clé API introuvable ou n'appartenant pas à l'utilisateur authentifié

Corps de la requête :

Champ Type Requis Description
name string Oui Nom de la collection
description string Non Description facultative

Réponse : 200 OK — Objet Collection

{
  "uuid": "a1b2c3...",
  "name": "Project Docs",
  "slug": "project-docs",
  "description": "Technical documentation",
  "document_count": 0,
  "total_chunks": 0,
  "is_public": false,
  "is_subscribed": false,
  "created_at": "2026-03-23T10:00:00Z"
}

Erreurs :

  • 404 — Abonnement introuvable

Exemple :

curl -X POST https://your-instance/api/v1/collections/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Project Docs", "description": "Technical documentation"}'

Obtenir une collection

GET /api/v1/collections/{uuid}/

Réponse : 200 OK — Objet Collection

Créer une collection

PATCH /api/v1/collections/{uuid}/

Modifie le nom et/ou la description d'une collection. Propriétaire uniquement.

Corps de la requête : aqoon utilise les cookies suivants :

Champ Type Description
name string Nom de la collection
description string Description

Réponse : 200 OK — Objet Collection

Erreurs :

  • 404 — Abonnement introuvable
  • 404 — Abonnement introuvable
  • 404 — Abonnement introuvable

Exemple :

curl -X PATCH https://your-instance/api/v1/collections/{uuid}/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Renamed Docs"}'

Supprimer la collection

DELETE /api/v1/collections/{uuid}/

Suppression logique d'une collection et de tous ses documents. Propriétaire uniquement. Les entrées de l'index de recherche sont supprimées immédiatement ; les blobs sont conservés pendant une période de grâce de 7 jours avant la suppression définitive.

Nom : aqoon

Erreurs :

  • 404 — Abonnement introuvable
  • 404 — Abonnement introuvable

Exemple :

curl -X DELETE https://your-instance/api/v1/collections/{uuid}/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -w "\nHTTP %{http_code}\n"

Documents

Lister les documents

GET /api/v1/documents/

Renvoie les documents de toutes les collections visibles.

Paramètres de requête :

Paramètre Type Description
tag string Filtrer par tag (insensible à la casse)
collection string Filtrer par identifiant de collection

Réponse : 200 OK

[
  {
    "uuid": "d4e5f6...",
    "title": "Annual Report 2025",
    "source_type": "pdf",
    "status": "indexed",
    "tags": ["finance", "annual"],
    "chunks_count": 24,
    "original_filename": "report-2025.pdf",
    "file_size": 102400,
    "collection_name": "Project Docs",
    "collection_slug": "project-docs",
    "created_at": "2026-03-01T10:00:00Z"
  }
]

Télécharger un document

POST /api/v1/collections/{uuid}/documents/

Téléchargez des documents dans une collection pour commencer.

Auth : Nécessite une permission d'écriture — clés d'accès complet ou clés à portée limitée avec un droit d'écriture sur la collection.

Requêtes multipart/form-data

Champ Type Requis Description
file file L'un des champs file/files Téléchargement d'un seul fichier
files file[] L'un des champs file/files Télécharger des documents
title string Non Titre du document (par défaut : nom du fichier)
tags string Non Tags séparés par des virgules
source_type string Non Forçage du type de fichier (détection automatique si omis)

Nom : aqoon

{
  "uuid": "d4e5f6...",
  "title": "Annual Report 2025",
  "source_type": "pdf",
  "status": "pending",
  "original_filename": "report-2025.pdf",
  "file_size": 102400,
  "tags": ["finance", "annual"],
  "collection_name": "Project Docs",
  "created_at": "2026-03-22T10:00:00Z"
}

Nom : aqoon

{
  "uploaded": [
    {
      "uuid": "d4e5f6...",
      "title": "Annual Report 2025",
      "source_type": "pdf",
      "status": "pending",
      "original_filename": "report-2025.pdf",
      "file_size": 102400,
      "tags": [],
      "collection_name": "Project Docs",
      "created_at": "2026-03-22T10:00:00Z"
    }
  ],
  "skipped": [
    {
      "filename": "image.png",
      "reason": "Unsupported file type."
    }
  ],
  "total_uploaded": 1,
  "total_skipped": 1
}

Erreurs :

  • 400 — Aucun fichier fourni, type de fichier non pris en charge ou fichier trop volumineux
  • 404 — Abonnement introuvable
  • 404 — Abonnement introuvable

Exemple — fichier unique :

curl -X POST https://your-instance/api/v1/collections/{uuid}/documents/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -F "file=@report-2025.pdf" \
  -F "title=Annual Report 2025" \
  -F "tags=finance,annual"

Exemple — envoi groupé :

curl -X POST https://your-instance/api/v1/collections/{uuid}/documents/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -F "files=@report-2025.pdf" \
  -F "files=@summary.docx" \
  -F "tags=finance"

Remplacer le document

POST /api/v1/documents/{uuid}/replace/

Remplace le fichier d'un document et le retraite. L'UUID du document est conservé ; les anciennes entrées de recherche sont supprimées et le nouveau fichier est traité depuis le début.

Auth : Nécessite une permission d'écriture — clés d'accès complet ou clés à portée limitée avec un droit d'écriture sur la collection.

Requêtes multipart/form-data

Champ Type Requis Description
file file Oui Remplacer le document
title string Non Remplacer le titre du document (conserve le titre existant si omis)
tags string Non Tags séparés par des virgules
source_type string Non Forçage du type de fichier (détection automatique si omis)

Réponse : 200 OK — Objet Collection

{
  "uuid": "d4e5f6...",
  "title": "Annual Report 2026",
  "source_type": "pdf",
  "status": "pending",
  "original_filename": "report-2026.pdf",
  "file_size": 110592,
  "tags": ["finance", "annual"],
  "collection_name": "Project Docs",
  "created_at": "2026-03-01T10:00:00Z"
}

Erreurs :

  • 404 — Abonnement introuvable
  • 404 — Abonnement introuvable
  • 404 — Abonnement introuvable

Exemple :

curl -X POST https://your-instance/api/v1/documents/{uuid}/replace/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -F "file=@report-2026.pdf" \
  -F "title=Annual Report 2026"

Télécharger un document

GET /api/v1/documents/{uuid}/download/

Télécharge le fichier original. Renvoie une redirection 302 vers une URL signée à durée limitée (valide 1 heure).

Auth : Toute clé API valide ou authentification de session qui peut voir le document — collections possédées ou collections publiques souscrites.

Réponse : 302 Found — Le fichier du document (dans Azure Blob Storage)

Erreurs :

  • 404 — Clé API introuvable ou n'appartenant pas à l'utilisateur authentifié

Exemple :

curl -L -H "Authorization: Bearer aqn_..." \
  https://aqoon.ai/api/v1/documents/{uuid}/download/ \
  -o file.pdf

Utilisez le drapeau -L pour suivre automatiquement la redirection. L'URL signée expire après 1 heure.

Obtenir le détail d'un document

GET /api/v1/documents/{uuid}/

Réponse : 200 OK — Inclut content_text, error_message et le tableau chunks.

{
  "uuid": "d4e5f6...",
  "title": "Annual Report 2025",
  "source_type": "pdf",
  "status": "indexed",
  "tags": ["finance", "annual"],
  "chunks_count": 24,
  "original_filename": "report-2025.pdf",
  "file_size": 102400,
  "content_text": "Full extracted text...",
  "error_message": "",
  "collection_name": "Project Docs",
  "collection_slug": "project-docs",
  "created_at": "2026-03-01T10:00:00Z",
  "chunks": [
    {
      "id": "uuid",
      "content": "Chunk text content...",
      "chunk_index": 0,
      "embedding_model": "text-embedding-3-small"
    }
  ]
}

POST /api/v1/search/

Corps de la requête :

{
  "query": "payment terms",
  "collection": "project-docs",
  "limit": 5
}
Champ Type Requis Par défaut
query string Oui
collection slug Non Toutes les collections visibles
limit int Non 5 (max: 50)

Réponse : 200 OK

{
  "query": "payment terms",
  "count": 3,
  "results": [
    {
      "content": "Matching chunk text...",
      "title": "Contract Document",
      "document_id": "uuid",
      "collection_name": "Legal",
      "tags": ["contract"],
      "score": 0.89
    }
  ]
}

Abonnements aux collections

S'abonner à une collection publique

POST /api/v1/collections/{slug}/subscribe/

Réponse : 200 OK

{
  "status": "subscribed",
  "collection": "project-docs"
}

Erreurs :

  • 404 — Collection introuvable ou non publique

Se désabonner d'une collection

DELETE /api/v1/collections/{slug}/subscribe/

Réponse : 200 OK

{
  "status": "unsubscribed",
  "collection": "project-docs"
}

Erreurs :

  • 404 — Abonnement introuvable

Gestion des clés API (KaaS)

Les clés API KaaS permettent aux développeurs externes de rechercher dans vos collections. Elles sont gérées via la page Clés API de l'interface web ou via l'API REST.

Lister / Créer des clés API

GET /api/v1/keys/
POST /api/v1/keys/

Corps de la requête de création :

{
  "name": "Acme Corp Key"
}

Réponse de création : 201 Created

{
  "uuid": "key-uuid",
  "name": "Acme Corp Key",
  "prefix": "aqn_abc123...",
  "key": "aqn_full_key_here",
  "is_active": true,
  "created_at": "2026-03-01T10:00:00Z"
}

Le champ key n'est renvoyé qu'au moment de la création.

Rotation de la clé API

POST /api/v1/keys/{uuid}/rotate/

Révoque la clé API existante et en crée une nouvelle avec le même nom et les mêmes autorisations d'accès aux collections. L'ancienne clé est immédiatement désactivée.

Réponse : 201 Created

{
  "uuid": "new-key-uuid",
  "name": "Acme Corp Key",
  "prefix": "aqn_abc123...",
  "key": "aqn_new_full_key_here",
  "is_active": true,
  "is_full_access": false,
  "created_at": "2026-03-13T10:00:00Z"
}

Le champ key n'est renvoyé qu'au moment de la rotation. Conservez-le en lieu sûr — il ne pourra pas être récupéré ultérieurement.

Erreurs :

  • 404 — Clé API introuvable ou n'appartenant pas à l'utilisateur authentifié

Accorder / Révoquer l'accès à une collection

POST /api/v1/keys/{uuid}/collections/
DELETE /api/v1/keys/{uuid}/collections/{collection-slug}/

Corps de la requête d'autorisation :

Champ Type Requis Description
collection slug Oui Autorisation d'accès à la collection
permission string Non "read" (par défaut) ou "write"
{
  "collection": "my-collection",
  "permission": "write"
}

Si un accès existe déjà pour cette clé et cette collection, le niveau de permission est mis à jour.

Réponse de création : GET /api/v1/keys/{uuid}/collections/200 OK

[
  {
    "collection": "my-collection",
    "permission": "write"
  },
  {
    "collection": "public-docs",
    "permission": "read"
  }
]

Statistiques d'utilisation

GET /api/v1/keys/usage/?days=30
GET /api/v1/keys/{uuid}/usage/

Webhooks

Les webhooks vous permettent de recevoir des notifications en temps réel lorsque les documents terminent leur traitement. Configurez une URL webhook par organisation pour recevoir les événements document.indexed et document.failed. Les payloads sont signés avec HMAC-SHA256 et envoyés avec des tentatives de retransmission en cas d'échec.

Obtenir la configuration du webhook

GET /api/v1/webhooks/

Renvoie la configuration webhook actuelle de l'organisation.

Réponse : 200 OK

{
  "configured": true,
  "url": "https://your-app.example.com/hooks/aqoon",
  "is_active": true
}

Le champ key n'est renvoyé qu'au moment de la création.

curl https://your-instance/api/v1/webhooks/ \
  -H "Authorization: Bearer aqn_your_api_key"

Créer ou mettre à jour un webhook

POST /api/v1/webhooks/

Crée un nouveau webhook ou met à jour l'URL d'un webhook existant.

Corps de la requête :

{
  "url": "https://your-app.example.com/hooks/aqoon"
}

À la création : 201 Created — secret returned once, store it securely.

{
  "configured": true,
  "url": "https://your-app.example.com/hooks/aqoon",
  "is_active": true,
  "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Lors d'une mise à jour (le webhook existe déjà) : 200 OK — secret is not returned.

{
  "configured": true,
  "url": "https://your-app.example.com/hooks/aqoon-updated",
  "is_active": true
}
# Create
curl -X POST https://your-instance/api/v1/webhooks/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-app.example.com/hooks/aqoon"}'

# Update URL
curl -X POST https://your-instance/api/v1/webhooks/ \
  -H "Authorization: Bearer aqn_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-app.example.com/hooks/aqoon-v2"}'

Supprimer

DELETE /api/v1/webhooks/

Supprime la configuration du webhook. Aucun événement ne sera plus envoyé.

Réponse : 200 OK

curl -X DELETE https://your-instance/api/v1/webhooks/ \
  -H "Authorization: Bearer aqn_your_api_key"

Envoyer le lien de réinitialisation

POST /api/v1/webhooks/test/

Envoie immédiatement un événement de test à l'URL webhook configurée. Renvoie 404 si aucun webhook n'est configuré.

Réponse : 200 OK

curl -X POST https://your-instance/api/v1/webhooks/test/ \
  -H "Authorization: Bearer aqn_your_api_key"

Format du payload

Chaque événement est envoyé en tant que POST JSON à votre URL webhook :

{
  "event": "document.indexed",
  "timestamp": "2026-03-23T10:00:00Z",
  "data": {
    "uuid": "a1b2c3...",
    "status": "indexed",
    "title": "Q1 Report",
    "source_type": "pdf",
    "collection_uuid": "d4e5f6...",
    "collection_name": "Finance Docs",
    "chunks_count": 42,
    "tags": "finance,quarterly",
    "error_message": null,
    "original_filename": "q1-report.pdf",
    "file_size": 204800
  }
}

Le champ event vaut document.indexed (traitement réussi) ou document.failed (traitement échoué). En cas d'échec, error_message contient une description.

Vérification de la signature

Chaque requête webhook inclut deux en-têtes de sécurité :

  • X-Aqoon-Signature: sha256=<hex-digest>
  • X-Aqoon-Timestamp: <unix-timestamp>

La signature est un HMAC-SHA256 de {timestamp}.{raw-body} calculé avec votre secret webhook. Vérifiez toujours la signature avant de traiter le payload.

import hashlib
import hmac

def verify_signature(secret: str, timestamp: str, body: bytes, signature: str) -> bool:
    message = f"{timestamp}.".encode() + body
    expected = hmac.new(secret.encode(), message, hashlib.sha256).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)
import { createHmac, timingSafeEqual } from 'crypto';

function verifySignature(secret: string, timestamp: string, body: Buffer, signature: string): boolean {
  const message = Buffer.concat([Buffer.from(`${timestamp}.`), body]);
  const expected = 'sha256=' + createHmac('sha256', secret).update(message).digest('hex');
  return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

Pour se protéger contre les attaques de rejeu, rejeter les événements dont X-Aqoon-Timestamp date de plus de 5 minutes.


Point d'accès MCP

Le serveur MCP est accessible à /mcp via le transport Streamable HTTP.

Authentification : Authorization: Bearer aqn_<key>

Outils disponibles :

Outil Description
search_documents Recherche hybride texte + vecteur avec filtre de collection et limite de résultats optionnels
list_collections Lister toutes les collections avec le nombre de documents et les descriptions
get_document_info Obtenir les détails complets d'un document et ses fragments par UUID
search_by_tag Trouver tous les documents avec un tag spécifique

Gestion des erreurs

Codes de statut HTTP

Code Signification
200 Succès
201 Créé
400 Requête incorrecte (erreur de validation)
401 Non autorisé (jeton ou clé API manquant ou invalide)
404 Ressource introuvable
429 Limite de débit atteinte
500 Erreur du serveur

Format de réponse d'erreur

Toutes les erreurs utilisent une enveloppe cohérente avec un champ error :

{
  "error": "Collection not found.",
  "code": "COLLECTION_NOT_FOUND"
}

Les erreurs de validation incluent un objet fields avec les détails par champ :

{
  "error": "Validation failed.",
  "code": "VALIDATION_FAILED",
  "fields": {
    "name": ["This field is required."],
    "collection": ["Collection not found."]
  }
}

Utilisez code pour la gestion d'erreurs programmatique (par ex. logique switch / if dans votre client). Utilisez error pour l'affichage aux utilisateurs finaux.

Erreurs

Authentification

Code Description
INVALID_API_KEY Clé API introuvable ou hachage non concordant
API_KEY_EXPIRED La clé API a dépassé sa date d'expiration
USER_ACCOUNT_DISABLED Le compte utilisateur associé à la clé est inactif
AUTHENTICATION_REQUIRED Aucun identifiant valide fourni

403 — Autorisation

Code Description
WRITE_ACCESS_REQUIRED Clés API limitées — accordez l'accès à des collections spécifiques
NOT_COLLECTION_OWNER Date de création de la collection
SCOPED_KEY_FORBIDDEN Les clés à portée limitée ne peuvent pas effectuer cette action

404 - Page introuvable

Code Description
COLLECTION_NOT_FOUND La collection n'existe pas ou n'est pas visible par cette clé
DOCUMENT_NOT_FOUND Le document n'existe pas ou n'est pas accessible
DOCUMENT_FILE_NOT_FOUND Le document existe mais le fichier original est introuvable dans le stockage
API_KEY_NOT_FOUND Compte introuvable.
GRANT_NOT_FOUND Autorisation d'accès à la collection
SUBSCRIPTION_NOT_FOUND Abonnements aux collections
WEBHOOK_NOT_CONFIGURED Aucun webhook n'a été configuré pour ce compte

400 — Validation

Code Description
VALIDATION_FAILED Un ou plusieurs champs ont échoué à la validation (voir l'objet fields)
NO_FILES_PROVIDED Télécharger des documents
NO_FILE_PROVIDED La requête d'envoi unitaire ne contient aucun fichier
UNSUPPORTED_FILE_TYPE L'extension ou le type MIME du fichier n'est pas pris en charge
FILE_TOO_LARGE Le fichier dépasse la limite de 50 Mo
INVALID_FILE_CONTENT Le contenu du fichier ne correspond pas au type déclaré (vérification des octets magiques)
URL_REQUIRED Un type de source URL a été spécifié mais aucune URL n'a été fournie
NAME_REQUIRED Un champ de nom obligatoire était vide ou absent

Limitation de débit

Code Description
RATE_LIMIT_EXCEEDED Quota de requêtes dépassé ; consultez les en-têtes X-RateLimit-* pour les temps de réinitialisation

500 - Erreur du serveur

Code Description
SEARCH_UNAVAILABLE La recherche est temporairement indisponible. Veuillez réessayer.
UPLOAD_FAILED Le fichier n'a pas pu être écrit dans le stockage blob
WEBHOOK_TEST_FAILED L'envoi de l'événement de test à l'URL webhook configurée a échoué