Aller au contenu

Référence de l'API

Les points d'accès HTTP publics de Sextant.

Les bases#

URL de basehttps://api.example.com dans ces pages
AuthentificationAuthorization: Bearer sextant_... ou x-api-key: sextant_...
CorpsJSON; envoi de fichier en multipart/form-data
Identifiantssrc_ source, fld_ dossier, ev_ preuve, run_ run, thr_ thread, imp_ import, key_ clé
Région<source_id>:<id local>, par exemple src_…:p12
Spécification de sourceURL, spécification de connecteur (Formats), text:... ou src_…; dans les sources d'une question, aussi un dossier (fld_… ou son nom)
x-request-idsur chaque réponse (le vôtre si fourni); à citer pour signaler un problème
x-timezonel'heure de la personne qui demande, +02:00 ou Europe/Paris: les heures d'une question y sont lues; les SDK et l'application l'envoient, UTC sans lui
Erreurs{"error": {"code", "message", "details"}} (Erreurs)
OpenAPI/openapi.json

Questions#

POST /v1/ask#

Toutes les questions, un seul point d'accès: un fait, une comparaison, une liste sur plusieurs sources ou un rapport complet. Sextant choisit comment chercher (une recherche directe, ou le workflow de recherche pour une question en plusieurs parties, comparative ou une liste) et la longueur de la réponse (réponse adaptative).

ChampTypeRequisDescription
questionchaîne, sans limite de longueurouiune question, quelques mots ou un cahier des charges entier
sourceschaîne ou liste, jusqu'à 1 000nonsources et dossiers: src_…, URL, spécification, text:..., fld_… ou nom de dossier
budgetchaîne ou objetnonmode ou limites; défaut balanced
max_output_tokensentiernonplafond de taille de la réponse; défaut: aussi longue que la question le demande
answer_schemaobjetnonun schéma JSON: la réponse est aussi donnée sous cette forme, dans data (sortie structurée)
thread_idchaînenonrelance dans ce thread
streambooléennonServer-Sent Events

Sans sources: toute la bibliothèque (pour une relance, les sources du thread). Un dossier est remplacé par ses sources et celles de ses sous-dossiers. Tout autre champ est refusé (422).

JSON
{ "sources": "https://example.com/rapport-annuel.pdf", "question": "Quel âge a le PDG ?" }
JSON
{ "sources": ["Contrats 2025", "src_…"], "question": "Une revue complète de ces contrats : renouvellements, pénalités, risques." }

Réponse:

ChampDescription
answerMarkdown, citations [E1], [E2]... (E1 = evidence[0])
statusanswered ou insufficient_evidence
evidencepreuves
confidence, confidence_signals0 à 1, et ses signaux
candidatesmeilleurs passages (régions), à lire en entier avec POST /v1/regions/{id}/read; toujours remplis avec insufficient_evidence
sourcessources ouvertes
sources_inspected, regions_inspectedcompteurs
processingper_source (source_fraction_read, source_fraction_scanned, asr_seconds, ocr_pages, frames_processed...), timings_ms, budget (limites et consommation), adaptive_output (length: short, standard ou long; planned, reasons, sources, output_tokens), sufficiency, conflict
billing.price_usdprix de la question
run_id, environment_urlle run; lien signé vers sa page en lecture seule
thread_id, turnthread et numéro du tour
datala réponse sous la forme de answer_schema; null sans schéma

Erreurs: 400 (invalid_request, fetch_blocked), 402, 404 (identifiant, source ou dossier introuvable), 413, 415, 422, 502.

Sortie structurée#

Avec answer_schema, un programme lit directement les valeurs de la réponse. Sextant rédige sa réponse citée comme d'habitude, puis remplit le schéma à partir de cette réponse, avec les preuves qu'elle cite pour la forme exacte d'un nom ou d'un chiffre. Une valeur vient de la réponse seulement; ce que la réponse ne donne pas vaut null, ou est omis quand le schéma ne l'exige pas.

JSON
{
  "sources": "src_…",
  "question": "Combien de salariés l'entreprise comptait-elle en fin d'exercice, et où est son siège ?",
  "answer_schema": {
    "type": "object",
    "properties": {
      "salaries": { "type": "integer" },
      "siege": { "type": "string", "description": "ville" }
    },
    "required": ["salaries"]
  }
}

La réponse garde answer et evidence, et ajoute data, par exemple { "salaries": 79390, "siege": "San Francisco" }. processing.answer_schema indique si les données suivent le schéma (valid, et problems sinon). Tout schéma JSON (draft 2020-12) jusqu'à 20 000 caractères; un schéma invalide est refusé (400). Le remplir ajoute un court appel de modèle au prix de la question.

Streaming#

ask envoie des Server-Sent Events avec "stream": true ou Accept: text/event-stream.

  • event: <nom>, puis data: <JSON> avec t_ms (millisecondes depuis le début du run).
  • Ouverture: commentaire : connected; : keepalive après 15 s de silence.
  • Fin: result puis done, ou error puis done. Fermer la connexion annule le run.
  • Authentification, 402, identifiant inconnu, champ hors bornes: erreur JSON ordinaire, avant le flux.
  • Ignorez les événements inconnus: la liste peut s'allonger.
ÉvénementChamps
source_discoveredsource_id, type, title, cached
metadata_readysource_id, title, type, pages, duration...
outline_readysource_id, method (bookmarks, headings, chapters...), sections, pages
sources_selectedconsidered, shortlisted, selected
source_refreshed (source dynamique)source_id, previous, snapshots
source_derived (source appelée par la question)source_id, spec, title
capture_started, capture_progress, capture_done (direct ou chat)source_id, seconds, target_s, kind
research_mode (une demande lue en plusieurs parties)mode, sources
planning (la demande en cours de découpage)sources
plan_readyintent, modality, answer_type, deep; en parties, sub_questions
output_planned (réponse adaptative)length, reason, sources
output_replanned (le plan de rédaction a changé selon ce qui a été lu)length, reason
section_rankedsource_id, region_id, title, score
candidate_foundsource_id, region_id, label, title, path, score
region_expanded (voisin ajouté)source_id, region_id, label
region_readsource_id, region_id, label
ocr_started, ocr_donesource_id, region_id, page
transcribe_started, transcribedsource_id, region_id, label, seconds
vision_started, frames_inspectedsource_id, region_id, frames
link_followed, link_skipped (ignoré: robots.txt)url
evidence_foundevidence_id, source_id, region_id, label, quote, confidence
evidence_relation (concordance, complément ou contradiction)relation, a, b, a_label, b_label
changes_compared (captures d'une source dynamique)source_id
follow_upthread_id, turn, message, query, scope
research_mode (question en plusieurs parties, comparative ou liste)mode (workflow, react), sources
react_stepstep, thought, tools
sql_executedsql, rows, error
provider_degradedaucun: une décision rapide s'est rabattue sur une méthode plus simple; le run continue
answer_deltatext
answer_resetaucun: oubliez le texte reçu, une meilleure réponse suit
structuring (avec answer_schema)fields
completerun_id, status, confidence, elapsed_ms
error (une source n'a pas pu être ouverte; le run continue)source, message
resultle résultat complet, comme sans streaming
error (le run a échoué)error (code, message)
doneaucun: fin du flux

Sources#

POST /v1/sources#

Enregistre un fichier ou une source.

ChampTypeRequisDescription
filefichier multipartfile ou sourcetaille maximale
sourcechaînefile ou sourceURL, spécification ou text:...
waitbooléennonattendre la source prête; défaut true
folder_idfld_…nondossier où l'ajouter une fois prête

source, wait et folder_id passent en JSON, en champ de formulaire ou (wait, folder_id) en paramètre de requête.

bash
curl -s "$SEXTANT_API/v1/sources" -H "authorization: Bearer $SEXTANT_API_KEY" \
  -F "file=@proces-verbal.pdf" -F "folder_id=fld_…" -F "wait=false"
  • wait=true: 200: source (objet source), outline, outline_text (plan en texte indenté), elapsed_ms, cached (source déjà connue).
  • wait=false: 202 {"import": {...}} dès la spécification validée ou le fichier stocké; la suite tourne en arrière-plan (Imports). Une source déjà en cours d'import renvoie le même import.

Erreurs: 400 invalid_request (ni file ni source, fichier trop gros), 400 fetch_blocked, 402 (stockage), 404 (dossier), 415 (vérifié avant l'import).

GET /v1/sources#

ParamètreDescription
limit, offsetdéfaut 100 (jusqu'à 5 000), 0
folder, recursivesources de ce dossier; avec recursive, aussi de ses sous-dossiers
unfiledsources hors de tout dossier
qfiltre sur titre, adresse ou identifiant (casse et accents ignorés)
sort, ordername, type, size, added, updated (défaut), status; asc ou desc (défaut)

Réponse: {"sources": [...], "total": n}; ligne: id, uri, type, title, state, length, length_unit, size_bytes, mime_type, created_at, updated_at, live (source dynamique).

GET /v1/sources/{source_id}#

Objet source: id, uri, type (pdf, video, audio, youtube, web_page, website, text, image, office, records), title, length et length_unit (pages, secondes, caractères...), processing_state, capabilities (native_text, bookmarks, subtitles, chapters...), metadata, stats, size_bytes, mime_type, media_url, created_at, updated_at, card (courte description pour choisir parmi les sources), excerpt (premiers mots), settings (source dynamique: refresh_s, window_s, valeurs actuelles et par défaut).

PATCH /v1/sources/{source_id}#

ChampDescription
titlejusqu'à 500 caractères; vide ou null rétablit l'original
configsource dynamique, champs envoyés seulement: refresh_s (60 à 604 800), window_s (direct ou chat, 5 à 300)

Réponse: la ligne de la source. Erreurs: 400 (réglage non applicable à cette source), 404.

Autres points d'accès#

Point d'accèsParamètresRéponse
DELETE /v1/sources/{source_id}{"deleted": true}; fichiers, analyse et places dans les dossiers supprimés
POST /v1/sources/deletesources (1 à 5 000){"deleted": [...], "not_found": [...]}
GET /v1/sources/{source_id}/outlinedepth (3), region_id (sous-plan), max_nodes (800){"outline": {...}, "text": "..."}
GET /v1/sources/{source_id}/regions/{region_id}text (true: texte déjà extrait)une région; region_id local ou complet
GET /v1/sources/{source_id}/evidence/{evidence_id}une preuve de cette source
GET /v1/sources/{source_id}/activitysource, runs (price_usd, unités lues), heat (lectures par partie), cached_units, total_units
GET /v1/sources/{source_id}/fileblob (capture antérieure d'une source dynamique)le fichier stocké, servi en ligne; 404 sans fichier stocké (média distant: lu à l'origine)
GET /v1/sources/{source_id}/pages/{page}scale (0,5 à 3, 1.5)page de PDF en PNG; 400 hors PDF, 404 hors limites
POST /v1/sources/{source_id}/keepblob_key (capture d'un run; défaut: capture actuelle)id, title, folder_id, captured_at: source fixe dans Kept from live sources (même capture, même source); 400 sur une source fixe

Imports#

Sources ajoutées avec wait=false.

Point d'accèsRéponse
GET /v1/imports{"imports": [...]}: actifs et terminés depuis moins de 24 h, plus récents d'abord
GET /v1/imports/{import_id}un import
DELETE /v1/imports/{import_id}annule (en attente ou en cours, données partielles supprimées) ou masque (terminé): {"import", "cancelled", "dismissed"}
POST /v1/imports/{import_id}/retryrelance un import échoué ou annulé: 202 {"import": ...}

Import: id (imp_…), kind (spec, upload), label (spécification ou nom de fichier, secrets masqués), type, connector, folder_id, status (queued, running, done, failed, cancelled), stage (queued, fetching, reading, outlining, done), progress (0 à 1 ou null), message, source_id, source (une fois terminé), error (code, message), created_at, updated_at, finished_at.

Connecteurs#

Point d'accèsParamètresRéponse
GET /v1/connectors{"connectors": [...]}: name, description, examples, enabled, requires, live (spécifications rafraîchies), live_examples, refresh_s, suggests
GET /v1/connectors/{name}/suggestq (2 caractères au moins), limit (8){"suggestions": [...]} si suggests; vide si le service distant échoue

Dossiers#

Point d'accèsCorpsRéponse
GET /v1/folders{"folders": [...], "n_sources": n}: l'arbre, la taille de la bibliothèque
POST /v1/foldersname (1 à 200, requis), description, color, parent_id, sources (identifiants, URL ou spécifications, jusqu'à 500)le dossier et ses sources
GET /v1/folders/{folder_id}le dossier, ses sources, son chemin path
PATCH /v1/folders/{folder_id}name, description, color, parent_id (null: premier niveau)le dossier
DELETE /v1/folders/{folder_id}{"deleted": true, "moved_up": [...], "parent_id": ...}
POST /v1/folders/{folder_id}/sourcessources (1 à 5 000; URL et spécifications enregistrées à la volée), from_folder (déplacer)le dossier
POST /v1/folders/{folder_id}/sources/removesourcesle dossier (sources gardées dans la bibliothèque)
DELETE /v1/folders/{folder_id}/sources/{source_id}le dossier

Dossier: id (fld_…), name, parent_id, description, color, source_ids, n_sources (directes), n_folders, n_total (sous-dossiers compris), types, types_total, created_at, updated_at. Erreurs: 400 (nom pris à côté, déplacement dans lui-même ou un de ses sous-dossiers), 404.

Régions#

Un passage en entier, par identifiant de région (region_id d'une preuve, id d'un candidat), pour vérifier une citation dans son contexte.

Point d'accèsRéponseFacturé
POST /v1/regions/{region_id}/readla région et son text complet (OCR ou transcription si besoin)opération; rien pour une page déjà lue

Erreurs: 402, 404.

Runs#

Point d'accèsParamètresRéponse
GET /v1/runslimit (50), kind (ask; research: le workflow de recherche a tourné){"runs": [...]}: id, kind, query, source_ids, status, price_usd, total_ms, confidence, thread_id, created_at, source_fraction_read
GET /v1/runs/{run_id}query, standalone_query, kind, status, answer, confidence, evidence, candidates, events, coverage, tables, metrics, price_usd, thread_id, turn, thread, horodatages
GET /v1/runs/{run_id}/tablesscope: run (défaut, ce qu'il a lu) ou sources (toutes ses sources)sandbox_id, scope, tables (schémas, aperçus)
POST /v1/runs/{run_id}/sqlsql (requis, un SELECT ou WITH en lecture seule), limit (200, jusqu'à 5 000), scopeok, columns, dtypes, rows, n_rows, n_rows_total, truncated, tables_used, elapsed_ms, error si refusée
POST /v1/runs/{run_id}/sharettl_days (30; 0: sans expiration)run_id, environment_url, token, expires_at
GET /v1/evidence/{evidence_id}une preuve de l'un de vos runs

Lien de partage: jeton dans l'en-tête x-sextant-share (ou ?share= pour les URL d'images et de vidéos). Il ouvre ce run, ses tableaux, son SQL et les sources lues, en lecture seule, rien d'autre (403); il ne crée pas d'autre lien.

Threads#

Point d'accèsParamètresRéponse
GET /v1/threadslimit (200, jusqu'à 1 000), offset, q (titre et questions){"threads": [...], "total": n}: id, title, turns, sources, last_question, last_status, price_usd, total_ms, created_at, updated_at
GET /v1/threads/{thread_id}turns (message, standalone_query, answer, status, evidence, price_usd), evidence fusionnées, sources (fraction_read), tables, totals
PATCH /v1/threads/{thread_id}title (1 à 300)le thread
DELETE /v1/threads/{thread_id}{"deleted": ...}
GET /v1/threads/{thread_id}/tablesscopecomme un run
POST /v1/threads/{thread_id}/sqlcomme un runcomme un run

Facturation et consommation#

Point d'accèsParamètresRéponse
GET /v1/billingenabled, payments_configured, pricing (min_balance_usd, welcome_credits_usd), topup (min_usd, max_usd, suggestions_usd), fx; facturation active: balance_usd, has_payment_method, card, recharge (enabled, below_usd, to_usd, currency, error), 50 dernières transactions (kind, amount_usd, balance_after, description, run_id, created_at), storage
POST /v1/billing/checkoutamount_usd (tout montant dans topup), currency (usd, eur)id, url (page de paiement), amount_usd, credits_usd, currency, amount_charged
PUT /v1/billing/rechargebelow_usd, to_usd (les deux null: désactivée), currencyle résumé de facturation; 400 sans carte enregistrée
POST /v1/billing/portal{"url": ...}: factures et reçus; 400 avant un premier achat
GET /v1/usagedays (30)requests, spend_usd, avg_price_per_request_usd, by_key (requests, spend_usd), by_day, by_kind

Paiement: 400 hors des bornes de topup, 503 provider_unavailable sans paiements configurés.

Compte et clés d'API#

Point d'accèsCorpsRéponse
POST /v1/auth/registeremail, password (8 caractères au moins), name{"user", "token"} et cookie de session
POST /v1/auth/loginemail, password{"user", "token"} et cookie de session; 401 si erreur
POST /v1/auth/logout{"ok": true}
GET /v1/auth/meuser_id, email, workspace, is_admin, api_key_id
GET /v1/api-keys{"keys": [...]}: id, name, prefix, created_at, expires_at, last_used_at, revoked, rate_limit_per_minute, monthly_budget_usd
POST /v1/api-keysname, expires_days (1 à 3 650), rate_limit_per_minute (1 à 100 000), monthly_budget_usd{"key": "sextant_...", "api_key": {...}}: key n'est affichée qu'ici
DELETE /v1/api-keys/{key_id}{"revoked": true}

Service#

Point d'accèsRéponse
GET /healthz{"ok": true, "version": ...}, sans authentification
GET /v1/infoversion, source_types, auth_required
GET /v1/decision-rulesrules: règles de décision typées appliquées dans vos runs récents