Aller au contenu

API REST

Tout ce que fait l’interface passe par l’API REST : l’interface n’a pas de route privée. Un script, un outil de reporting ou votre propre application l’appellent de la même façon, sous les droits du jeton qu’ils présentent.

AdresseRôle
https://bi.exemple.fr/api/v1/…l’API, servie derrière Caddy (en développement : http://localhost:4100, ou http://localhost:3100, qui relaie /api/*)
/api/v1/openapi.jsonla spécification OpenAPI 3.1, générée depuis les schémas des routes
/api/healthl’état de l’API et de Trino, sans authentification

La page API et MCP de l’application présente la même référence, filtrable, avec un exemple curl et fetch pour chaque endpoint et un bouton pour télécharger la spécification.

Un jeton d’intégration commence par eoi_ et se passe dans l’en-tête Authorization :

Fenêtre de terminal
curl https://bi.exemple.fr/api/v1/me \
-H "Authorization: Bearer $EODIA_TOKEN"

Il se crée depuis Mon profil ou la page API et MCP, avec :

  • un nom, qui dit où il sert (« Script de reporting », « Claude Desktop ») ;
  • ses surfaces : API REST, MCP, ou les deux. Un jeton n’est accepté que sur les surfaces qu’il déclare : un jeton MCP seul est refusé par l’API REST ;
  • une expiration : 30 jours, 90 jours, 1 an, ou jamais.

Le jeton n’est affiché qu’une fois : seule son empreinte est gardée. La liste de vos jetons montre leur dernière utilisation, et Révoquer les coupe aussitôt. Un jeton ne peut pas créer d’autre jeton, et il cesse de fonctionner si son propriétaire est désactivé. Créations et révocations sont inscrites au journal d’audit.

L’interface s’authentifie par un cookie de session. Avec ce cookie, toute requête qui écrit (POST, PUT, PATCH, DELETE) doit porter l’en-tête X-Eodia-Csrf: 1, sans quoi elle est refusée (CSRF). Un jeton Bearer n’en a pas besoin.

POST /api/v1/query exécute une requête — SQL Trino, éditeur visuel ou SQL natif — dans Trino, sous l’identité de l’appelant :

Fenêtre de terminal
curl -X POST https://bi.exemple.fr/api/v1/query \
-H "Authorization: Bearer $EODIA_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"kind": "sql",
"sql": "SELECT region, count(*) AS clients FROM boutique.public.clients GROUP BY 1"
}
}'

La réponse donne les colonnes (name, label, type…), les lignes, un indicateur truncated, la durée et le SQL exécuté. limit fixe le nombre de lignes lues (100 000 au plus), parameters donne les valeurs des variables, et fresh: true ignore le cache.

EndpointRôle
POST /api/v1/queryexécuter une requête
POST /api/v1/query/cancelannuler une exécution, par son execution_id
POST /api/v1/query/exporttélécharger un résultat en CSV, JSON ou XLSX
POST /api/v1/questions/{id}/runexécuter une question enregistrée, avec ses variables
POST /api/v1/questions/{id}/exportexporter le résultat d’une question
POST /api/v1/dashboards/{id}/cards/{card}/runexécuter une carte avec les valeurs des filtres

Le niveau de requête compte : sans le niveau SQL sur aucune source, POST /api/v1/query refuse une requête SQL. Voir Droits.

GroupeExemples
ProfilGET /api/v1/me, vos jetons (/api/v1/me/tokens)
Sourcesmoteurs disponibles, sources, test de connexion, synchronisation, état d’un job (aussi en SSE)
Structuretables, colonnes, métadonnées, valeurs, relations, copier-coller de configuration
Exécutionrequêtes, annulation, export, historique, snippets
Questionsquestions, modèles (/api/v1/models), métriques (/api/v1/metrics), duplication
Tableaux de bordlecture, création, modification, duplication, exécution d’une carte
Dossiersdossiers et leur contenu, recherche, favoris, accueil, partages d’éléments
Partageliens de partage (/api/v1/share-links)
Copilotconversation en SSE (POST /api/v1/copilot), conversations enregistrées
Administrationpersonnes, invitations, groupes, permissions, journal d’audit, cache, secrets d’intégration

Les routes d’administration demandent les droits correspondants (Gérer les sources, Gérer les métadonnées, Gérer les permissions) ou d’être administrateur. Quelques routes publiques, sans jeton, servent la connexion (/api/auth/…) et les contenus partagés (/api/public/…).

Une erreur renvoie un statut HTTP et un corps de la forme :

{ "error": { "code": "DATA_ACCESS_DENIED", "message": "Accès aux données refusé : …" } }

Le code est stable et lisible par une machine ; le message est en français, prêt à afficher.

CodeStatutSens
UNAUTHENTICATED401jeton absent, invalide, expiré, ou non autorisé sur cette surface
FORBIDDEN, CSRF403droit manquant ; écriture par cookie sans X-Eodia-Csrf
DATA_ACCESS_DENIED403Trino a refusé l’accès à une table ou une colonne
NOT_FOUND404introuvable — ou invisible pour vous
INVALID_INPUT400corps ou paramètres invalides
CONFLICT409conflit : adresse ou catalogue déjà pris
QUERY_FAILED400Trino a rejeté la requête ; details.location situe l’erreur
QUERY_TIMEOUT408délai dépassé (QUERY_TIMEOUT_MS)
QUERY_CANCELLED499requête annulée
CONNECTION_FAILED400test de connexion d’une source en échec
ENGINE_UNAVAILABLE503Trino ou le fournisseur d’identité injoignable
AI_DISABLED, AI_QUOTA400, 429copilot non configuré ; quota atteint
INTERNAL500erreur interne

eodia insights est un logiciel libre d’Eodia.