ClaimTrace by AXIONYX.io Obtenir une clé

Référence API ClaimTrace (v1)

URL de base : https://claimtrace.dev. Authentification : header X-API-Key: afk_…. Le contrat de transport v1 est stable : aucun champ n'est retiré ni ne change de sémantique sans version majeure.

Endpoints

MéthodeCheminRôle
POST/v1/signupClé self-serve (email → clé afk_… envoyée par email, jamais dans la réponse, 50 crédits d'essai)
POST/v1/fetchAppel bloquant — JSON FetchResultV1 complet
GET/v1/fetch/streamFlux SSE — meta → entity… → done
GET/v1/requests/{request_id}Relecture d'un résultat (TTL 24 h, isolé par clé)
GET/v1/usageVotre tier, crédits restants, requêtes du jour
GET/v1/statsCompteurs publics du service du jour (sans clé)
GET/v1/healthÉtat du service + version du schéma

Requête — POST /v1/fetch

{
  "thematique": "restaurants menus du jour",
  "lieu": "Neuchâtel",
  "prompt": "le menu du jour réel, avec prix si publié",
  "depth": "standard",
  "max_entities": 8,
  "day": "2026-08-08"
}
ChampTypeContraintes
thematiquestringrequis, 2–200 caractères — quel type d'entités
promptstringrequis, 2–4000 caractères — le fait à établir
lieustringoptionnel, ≤ 200 caractères — périmètre géographique
depthstringfast · standard (défaut) · deep (Pack M+)
max_entitiesint1–30, défaut 8
daystringoptionnel, AAAA-MM-JJ — pour les données datées (ex. menus du jour)
deadline_snumberoptionnel, 1–900 — mur de temps global de la lecture : à l'échéance, les entités non finies sont rendues avec attributes.interrupt_reason = "deadline" (jamais « rien publié ») et la réponse arrive au plus tard deadline_s + 5 s
cache_modeauto · bypassbypass relit tout à froid (mesure de reproductibilité). Honoré uniquement pour une clé à scope * ; une clé free est ramenée à auto sans erreur — lisez usage.credits_charged pour savoir si le run était froid

Tous les paramètres acceptés

Générée depuis le modèle de requête v1 (FetchRequest) — tout autre champ est ignoré sans erreur (n'envoyez que les champs ci-dessus).

<!-- gen:params (scripts/claimtrace_api_reference.py) -->

ParamètreTypeDéfautBornesComportement
thematiquestringobligatoire≥ 2 car., ≤ 200 car.quel type d'entités
lieustring—≤ 200 car.périmètre géographique
promptstringobligatoire≥ 2 car., ≤ 4000 car.le fait à établir
sourceslist of web_search · places · website · social · files · images——restreint les familles de sources du planificateur ; par défaut : le planificateur décide
max_entitiesint8≥ 1, ≤ 30plafonné par la limite serveur ; les crédits sont réservés avant la lecture
depthfast · standard · deepstandard—deep exige un Pack M ou L (sinon 403)
output_hintobject——{"entity_fields": [...]} ajoute jusqu'à 14 champs attendus au plan ; ne change jamais le contrat de réponse
languagestringfr≤ 5 car.langue de la recherche et des noms de jours
countrystring—≥ 2 car., ≤ 2 car.ISO 3166-1 alpha-2 — locale de recherche
currencystring—≥ 3 car., ≤ 3 car.accepté, non utilisé en v1 : un prix porte la devise prouvée par sa source (ClaimV1.currency)
daystring—≤ 10 car.AAAA-MM-JJ — pour les données datées (ex. menus du jour)
radius_kmnumber—> 0, ≤ 25rayon autour de lat/lng
latnumber—≥ -90, ≤ 90point d'une liste de zone (avec lng, radius_km)
lngnumber—≥ -180, ≤ 180voir lat
backgroundboolfalse—réservé — honoré seulement pour une clé interne, ignoré sinon
known_contactslist of object——réservé — honoré seulement pour un appelant interne de confiance, ignoré sinon
cache_modeauto · bypassauto—bypass n'est honoré que pour une clé interne ; toute autre clé est ramenée à auto (lire usage.credits_charged)
deadline_snumber—> 0, ≤ 900budget global de la lecture ; les entités non terminées reviennent avec attributes.interrupt_reason = "deadline"
skip_image_curationboolfalse—fixé par le serveur — la valeur envoyée est ignorée
profilemenu_daily——menu_daily : profil menu du jour (sans curation d'images)
entity_namestring—≤ 120 car.recherche d'une entité NOMMÉE au lieu d'une liste de zone

<!-- /gen:params -->

Réponse — FetchResultV1

ChampTypeSignification
schema_version"1"Version du contrat
request_idstringPoignée de relecture pour /v1/requests/{id} (24 h)
queryQueryEchoV1Écho : thematique, lieu, day, depth, vertical
entitiesEntityV1[]Les entités résolues
verificationVerificationV1truth_rules_version, verified_live, checked_at, notes
usageUsageV1credits_charged, cache_hits, cost_class
warningsstring[]Les dégradations, dites plutôt que cachées — ex. phase_failed:<phase>:<Erreur> quand une étape (découverte, planification) a échoué : une réponse vide n'est jamais muette
attributionstring[]ex. © OpenStreetMap contributors (ODbL)

EntityV1

ChampTypeSignification
idstringIdentifiant stable de l'entité dans la réponse
titlestringNom de l'entité
summarystring \nullDescription courte si disponible
locationGeoV1 \nulladdress, city, country, lat, lng
contactContactV1 \nullphone, email, website
attributesobjectAttributs propres au vertical
claimsClaimV1[]Les faits vérifiés — voir ci-dessous
imagesImageV1[]url, role, caption
confidencefloat \nullConfiance au niveau entité, 0–1
not_foundNotFoundV1 \nullPrésent quand la donnée demandée n'est pas publiée

ClaimV1 — le cœur du produit

ChampTypeSignification
fieldstringQuel fait, ex. menu_du_jour
valueanyLe fait lui-même — null autorisé et assumé
currency"CHF" \"EUR" \"USD" \"GBP" \nullCode ISO 4217 d'un montant, prouvé par le verbatim de la source ou le nom de champ — jamais deviné, jamais converti. null = la source ne le prouve pas
match_level"exact" \"equivalent" \"comparable" \nullVertical produit, sur les claims de prix : exact = la référence demandée elle-même, equivalent = successeur/équivalent du même fabricant, comparable = produit similaire d'une autre gamme. Vocabulaire fermé
provenance.source_urlstring \nullLa page ou le document où le fait a été lu
provenance.fetched_atstring \nullQuand il a été lu (ISO 8601 UTC)
provenance.verbatimstring \nullCourt extrait de preuve, littéral depuis la source
provenance.page_kindstring \nullex. menu_du_jour, carte
provenance.domain_owned_by_entitybool \nullLa source appartient-elle à l'entité
confidencefloat \null0–1
verified_livebool \nullTri-état : confirmé live / démenti / non vérifié

NotFoundV1 — l'absence est une réponse

ChampTypeSignification
reasonenum, vocabulaire ferméExactement l'une de : not_published (la source a été lue, la donnée demandée n'y est pas publiée), wrong_page_kind (la source publie un autre type de contenu — ex. une carte permanente, pas un menu du jour), not_verifiable (la donnée n'a pas pu être extraite avec une preuve verbatim vérifiable — ou la lecture n'a pas eu lieu : attributes.interrupt_reason vaut alors deadline, cost_budget, llm_unavailable ou error ; source sociale derrière un mur de connexion ; site déclaré qui ne nomme pas l'entité), source_unreachable (la source n'a pas pu être lue). Ce vocabulaire fait partie du contrat : un switch exhaustif est possible. Toute nouvelle valeur implique une nouvelle schema_version — jamais un ajout silencieux
detailstring \nullExplication lisible
source_checkedstring \nullLa source réellement consultée

Ce que ClaimTrace lit — et ne lit pas

LectureÉtat
Page HTML du site de l'entité (y compris contenu servi dans un JSON embarqué type Inertia / Next, sans exécuter de JS)lue
Page rendue en JavaScript (coquille vide sans navigateur)rendue en navigateur headless
PDF lié, PDF dans une iframe, PDF multi-pages (≤ 6 pages)lu ; texte natif, sinon vision page par page (PDF scanné, police non décodable)
Image de menu publiée par le site (ardoise, affiche)lue en vision
Page hébergée par Google Siteslue comme une page HTML
Facebook / Instagramjamais téléchargés (mur de connexion) : seuls les extraits datés de l'index public comptent ; sinon not_verifiable
Google Business (fiche, posts)jamais une source — découverte interne seulement (conditions Google Maps Platform)
Annuaires et agrégateurs (listas.ch, TripAdvisor, TheFork, plateformes de commande…)jamais une source, jamais le « site » d'une entité

Un fait servi depuis un PDF est revalidé sur le texte natif du PDF (verified_live) ; un PDF scanné ou une image restent verified_live: null (tri-état honnête).

Reproductibilité — le harnais de rejeu

Même entrée → même sortie ? Vérifiez-le vous-même, sans rien d'autre que curl et jq :

# scripts/claimtrace-replay.sh (dépôt AXIONYX — fourni sur demande avec votre clé)
CLAIMTRACE_API_KEY=afk_… ./claimtrace-replay.sh -n 3 --stream requests.jsonl

requests.jsonl : une requête POST /v1/fetch par ligne ({"id":"…","body":{…}}). Sorties : summary.tsv (par run : durée, cold/cache, entités, claims, not_found par motif, interruptions, crédits, hash des faits, délai du 1er entity en flux), variance.tsv (par requête : k/N runs aux faits identiques, composition d'entités, latences) et divergences.txt (chaque fait qui diffère, avec les runs qui le servent). Le hash des faits ignore l'ordre, request_id et les horodatages : deux runs qui servent les mêmes faits ont le même hash.

Ce que la v1 ne renvoie jamais

Les champs dont la seule source est Google Places — notes, nombres d'avis, niveaux de prix, images hébergées par Google — sont exclus du payload pour des raisons juridiques (les conditions Google Maps Platform interdisent d'exporter ou repartager le contenu Places). Les claims proviennent exclusivement de sources appartenant à l'entité, garanties par une liste blanche de propriété de domaine.

Erreurs

CodeSignification
401Clé API absente ou invalide
402Crédits épuisés — rechargez ou attendez la recharge mensuelle
403Portée absente pour cette clé, ou depth: "deep" sans Pack M ou L — vérifié avant toute exécution, jamais facturé
404Sur /v1/requests/{id} : résultat inconnu ou expiré pour cette clé
409Sur /v1/signup : une clé active existe déjà pour cet email
422Erreur de validation — un champ viole les contraintes ci-dessus
429Limite de débit — la réponse porte Retry-After
405Mauvaise méthode HTTP sur une route documentée (ex. GET /v1/fetch)

Les refus ne sont jamais facturés.