Ingestion
POST /v2/ingest transforme un site — ou une liste explicite d'URL — en
chunks prêts pour le RAG et produit un seul fichier JSONL qui se charge
directement dans LangChain JSONLoader, LlamaIndex SimpleDirectoryReader,
ou un import en masse vers une base vectorielle. Il remplace la pile en deux
étapes que vous construiriez sinon : Firecrawl /crawl pour découvrir et
scraper, plus votre propre chunker pour découper le Markdown. EnConvert fait
la découverte, le rendu en Chrome headless, le chunking sensible aux titres
et l'assemblage du JSONL en un seul job.
Voici l'appel utile le plus minimal. Crawlez un site et chunkez chaque page qu'il découvre :
curl -X POST https://api.enconvert.com/v2/ingest \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"mode": "crawl",
"url": "https://example.com/docs"
}'
La réponse est l'enregistrement du job, renvoyé avec 202 Accepted. Notez
que le statut est queued, et que output_url est absent tant que le job
n'est pas terminé :
{
"job_id": "ing_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7",
"status": "queued",
"mode": "crawl",
"pages_discovered": 0,
"pages_processed": 0,
"pages_failed": 0,
"total_chunks": 0,
"webhook_delivered": false,
"created_at": "2026-06-24T09:14:02.118Z"
}
L'ingestion est toujours asynchrone. Chaque page est rendue dans un vrai
navigateur, ce qui prend 10–30 secondes par URL — bien au-delà de la fenêtre
de requête de 300 secondes pour tout job non trivial. Donc POST répond
202 avec un job_id, et un worker local au droplet vide le job hors bande.
Vous interrogez GET /v2/ingest/{job_id} pour suivre la progression, ou vous
enregistrez un webhook_url pour être averti quand il se termine.
À signaler d'emblée.
/v2/ingestest un endpoint V2 avec son propre compteur de quota,ingest_pages. Les plans de conversion V1 n'incluent aucune allocation d'ingestion — il vous faut un plan incluant V2 pour l'appeler. Une page est facturée pour chaque URL dont l'étape de rendu, de chunking et de JSONL s'achève ; les pages qui échouent ou sont ignorées ne sont pas facturées. Voir la page tarifs pour les allocations par palier, et l'aperçu V2 pour comprendre en quoi les compteurs V2 diffèrent des conversions V1.
Endpoints
| Méthode | Chemin | Objet |
|---|---|---|
POST |
/v2/ingest |
Crée un job d'ingestion. Répond 202 avec un job_id. |
GET |
/v2/ingest |
Liste des jobs de ce projet, du plus récent au plus ancien, avec pagination skip/limit. |
GET |
/v2/ingest/{job_id} |
Statut de cycle de vie d'un job, avec un output_url fraîchement signé une fois terminé. |
DELETE |
/v2/ingest/{job_id} |
Annule un job. Le worker voit le statut annulé et s'arrête entre deux pages. |
POST |
/v2/ingest/{job_id}/retry-webhook |
Re-signe et re-POST le webhook de complétion pour un job terminé. |
GET |
/v2/ingest/webhook-secret |
Révèle le secret de signature de webhook du projet (canal dashboard). |
POST |
/v2/ingest/webhook-secret/rotate |
Effectue la rotation du secret de signature. Les anciennes signatures cessent de se vérifier immédiatement. |
Content-Type : application/json sur chaque POST.
Authentification
Authentifiez-vous avec une clé privée dans l'en-tête X-API-Key pour les
appels serveur-à-serveur. C'est la voie qu'empruntent les exemples
ci-dessous.
X-API-Key: sk_live_your_private_key
Les clés publiques avec un jeton bearer JWT fonctionnent aussi, en utilisant
le même flux que tous les autres endpoints — générez un jeton avec votre clé
pk_, puis envoyez-le sous la forme Authorization: Bearer <token>. Le flux
complet, y compris le verrouillage de domaine et le rafraîchissement du jeton,
figure dans le guide d'authentification.
Chaque clé d'API porte une liste blanche d'endpoints autorisés. Si
/v2/ingest n'est pas sur la liste de la clé, la requête est rejetée avec
403. Une clé limitée à /v2/ingest atteint quand même les jobs qu'elle a
créés — GET et DELETE /v2/ingest/{job_id} ainsi que
POST /v2/ingest/{job_id}/retry-webhook sont toujours autorisés pour un
job_id (la forme ing_… est reconnue explicitement). L'endpoint de liste
statique et les deux routes de gestion webhook-secret n'héritent pas de
ce contournement ; ils requièrent un jeton plus large ou limité au dashboard.
Fonctionnement de l'ingestion
Un job parcourt cinq phases, toutes durables et résistantes aux redémarrages. Si le processus worker redémarre en plein job, le job est ré-enfilé au démarrage et reprend à la page sur laquelle il s'était arrêté — les pages déjà terminées conservent leur sortie en attente et ne sont jamais re-rendues ni re-facturées.
- File d'attente.
POSTvalide la requête, exécute un contrôle de quota rapideunits=1(le plan a l'ingestion activée et un peu de marge mensuelle), insère la ligne du job, et répond202. Rien n'est persisté si la barrière de quota échoue — un402ne laisse aucune ligne derrière lui. - Découverte. Pour les modes
sitemapetcrawl, le worker exécute la même passe de découverte que l'endpoint discover, plafonnée àmax_pages, et applique un filtrage SSRF sur l'URL de départ. Pour le modeurls, la liste explicite est dédupliquée dans l'ordre ; aucune découverte ne s'exécute. - Rendu et chunking. Chaque URL est rendue via le singleton Chrome headless partagé — le même pipeline de rendu que derrière l'endpoint perceive — puis le HTML rendu est converti en Markdown ajusté et découpé par le chunker sensible aux titres. Les rendus s'exécutent séquentiellement, une page à la fois.
- Mise en attente. Les chunks de chaque page sont écrits dans un objet
JSONL par page dans le stockage, indexé de façon déterministe par
(project, job, url). C'est ce qui rend un redémarrage peu coûteux : un job repris réutilise les pages en attente au lieu de les re-rendre. - Assemblage. Une fois chaque page terminée, les objets par page sont
concaténés dans le fichier final
v2-ingest/{job_id}.jsonl, les objets en attente sont supprimés, le job bascule surcompleted, et — si unwebhook_urlétait défini — le webhook de complétion signé se déclenche.
Le compteur de quota est revérifié par page à l'intérieur du worker, pas
seulement au moment de la soumission. Un job crawl dont le nombre de pages
est inconnu d'avance s'arrête proprement à votre plafond mensuel : les pages
déjà rendues sont facturées et conservées, et les pages restantes sont
marquées skipped plutôt que de dépasser le budget.
Les rendus d'ingestion sont sans identifiants par conception.
Contrairement à /v2/perceive, l'ingestion n'accepte pas auth, cookies,
ni headers personnalisés — rien de secret n'est persisté pour la reprise
durable, donc l'état du job sur disque ne porte jamais d'identifiants.
Paramètres de requête
Source et mode
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
mode |
string |
"urls" |
urls, sitemap, ou crawl. Sélectionne la façon dont l'ensemble d'URL est construit. |
url |
string |
null |
URL de départ pour le mode sitemap/crawl. Doit commencer par http:// ou https://. Max 2 048 caractères. Requis pour ces modes ; rejeté en mode urls. |
urls |
string[] |
null |
URL explicites à ingérer en mode urls. Non vide, max 1 000 entrées, chacune en http(s) et ≤ 2 048 caractères. Requis pour le mode urls ; rejeté en mode sitemap/crawl. |
url et urls sont mutuellement exclusifs — exactement une source. Le mode
urls requiert urls ; sitemap et crawl requièrent une url de départ.
Envoyer le mauvais pour le mode donne un 422.
Découverte (modes sitemap / crawl)
Ces paramètres sont transmis à la passe de découverte et ignorés en mode
urls.
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
max_pages |
integer |
50 |
Plafond d'URL découvertes et ingérées. 1–1 000. |
max_depth |
integer |
2 |
Profondeur de liens du crawl depuis l'URL de départ. 1–5. |
same_domain_only |
boolean |
true |
Restreint la découverte au domaine de l'URL de départ. |
include_patterns |
string[] |
[] |
Motifs regex qu'une URL doit satisfaire pour être conservée. Max 50. Chacun est compilé à la soumission ; un motif erroné donne un 422. |
exclude_patterns |
string[] |
[] |
Motifs regex qui écartent une URL correspondante. Max 50. |
respect_robots |
boolean |
false |
Quand true, une URL interdite par le robots.txt du site est ignorée. |
Rendu
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
wait_for |
string |
null |
Attend après la navigation un sélecteur CSS ou une expression JS avant la capture. Max 1 024 caractères. |
wait_timeout_ms |
integer |
30000 |
Durée maximale d'attente de wait_for, en millisecondes. 0–60 000. |
Remarque. L'ingestion n'accepte pas
auth,cookies, niheaders. Si une page a besoin d'identifiants pour s'afficher, l'ingestion n'est pas le bon outil — utilisez l'endpoint perceive, qui porte la surface complète des requêtes authentifiées, pour cette page unique.
Chunking (objet chunk)
| Paramètre | Type | Défaut | Contraintes | Description |
|---|---|---|---|---|
max_words |
integer |
512 |
32–4 000 | Plafond souple de mots par chunk. Sensible aux titres. Les blocs de code et les tableaux à pipes restent atomiques et peuvent dépasser cette valeur. |
sentence_overlap |
integer |
1 |
0–10 | Phrases répétées entre chunks de prose consécutifs d'une même section. 0 désactive le chevauchement. Le chevauchement ne franchit jamais une limite de titre. |
Le chunker découpe sur les titres #, ##, et ### — chaque chunk
appartient à exactement une section et porte son chemin de titres complet.
Les titres plus profonds (####–######) restent inline comme du contenu.
Les blocs de code délimités et les tableaux Markdown ne sont jamais découpés,
même quand un seul bloc dépasse max_words ; les éléments de liste sont
découpés entre éléments, jamais en plein élément.
Webhook
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
webhook_url |
string |
null |
Endpoint destiné à recevoir le callback de complétion signé en HMAC. Max 2 048 caractères. Schéma vérifié à la soumission ; filtré SSRF au moment de la livraison, pas à la soumission. |
Réponse
POST, GET /v2/ingest/{job_id}, et DELETE renvoient tous le même objet
IngestJobResponse.
| Champ | Type | Description |
|---|---|---|
job_id |
string |
ID opaque (ing_…). Utilisez-le avec les endpoints GET/DELETE et citez-le au support. |
status |
string |
queued, discovering, processing, completed, failed, ou canceled. |
mode |
string |
Le mode que vous avez soumis : urls, sitemap, ou crawl. |
pages_discovered |
integer |
URL que le job ingérera (la liste explicite, ou le résultat de la découverte). |
pages_processed |
integer |
URL dont le rendu → chunk → mise en attente s'est achevé. |
pages_failed |
integer |
URL qui n'ont pas pu être rendues ou qui ont été ignorées (par ex. quota épuisé). |
total_chunks |
integer |
Total de chunks écrits sur toutes les pages terminées — correspond au nombre de lignes du JSONL. |
output_url |
string |
URL de téléchargement pré-signée pour le JSONL final. Présent uniquement lorsque status vaut completed ; expire après 15 minutes. |
error_message |
string |
Défini lorsque status vaut failed (par ex. découverte rejetée, toutes les pages en échec). |
webhook_url |
string |
La cible du webhook de complétion enregistrée pour ce job, le cas échéant. |
webhook_delivered |
boolean |
true une fois que le webhook de complétion signé a reçu un 2xx. |
created_at |
string |
Date de création du job (UTC). |
completed_at |
string |
Date à laquelle le job a atteint un statut terminal (UTC). |
warnings |
string[] |
Notes non fatales. |
Remarque.
POSTet lesGET/DELETEpar job utilisentresponse_model_exclude_none, donc les champs encorenull(commeoutput_urlavant la complétion) sont omis du JSON plutôt qu'envoyés en tant quenull.
La forme de l'enregistrement JSONL
Le fichier final est du JSON délimité par des sauts de ligne. Chaque ligne est un chunk :
{"id":"9f2b8c1ad4e5-0000","content":"Pricing is usage-based...","metadata":{"source_url":"https://example.com/pricing","title":"Pricing","headings_path":["Pricing","Plans"],"section":"Plans","word_count":118,"chunk_index":0}}
| Champ | Type | Description |
|---|---|---|
id |
string |
Déterministe par (source_url, chunk_index) : <md5(url)[:12]>-<index:04d>. Une ré-exécution produit des ids identiques. |
content |
string |
Le texte du chunk récupérable. Correspond à Document.page_content dans LangChain. |
metadata.source_url |
string |
La page d'où provient le chunk. |
metadata.title |
string |
Le <title> de la page, à défaut le premier <h1>, plafonné à 512 caractères. |
metadata.headings_path |
string[] |
Le chemin h1 → h2 → h3 sous lequel se trouve le chunk. |
metadata.section |
string |
Le texte du titre le plus interne (la dernière entrée de headings_path). |
metadata.word_count |
integer |
Nombre de mots de content, délimités par des espaces. |
metadata.chunk_index |
integer |
L'index du chunk au sein de sa page. |
Le fichier est en UTF-8, écrit avec ensure_ascii=false, donc l'unicode
reste lisible. Comme content est une chaîne de premier niveau et que
metadata est un objet frère, le même fichier se charge via LangChain
JSONLoader(content_key="content", json_lines=True), LlamaIndex
SimpleDirectoryReader, et tout import de base vectorielle orienté ligne
sans remise en forme.
Cycle de vie du job et polling
Un job traverse ces états :
queued → discovering → processing → completed | failed | canceled
| Statut | Signification |
|---|---|
queued |
Accepté et en attente du worker. |
discovering |
Exécution de la passe de découverte sitemap/crawl (sitemap/crawl uniquement). |
processing |
Rendu et chunking des pages. pages_processed et total_chunks montent en direct. |
completed |
Le JSONL final est assemblé ; output_url est signé et prêt. |
failed |
La découverte a été rejetée, ou toutes les pages ont échoué ou ont été ignorées. error_message explique. |
canceled |
Un DELETE a atteint le job avant qu'il ne se termine. |
Interrogez le statut avec le GET par job. C'est en lecture seule — il ne
consomme aucun quota et re-signe l'output_url à partir de la clé d'objet
stockée à chaque appel :
curl https://api.enconvert.com/v2/ingest/ing_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7 \
-H "X-API-Key: sk_live_your_private_key"
Un job_id inconnu, ou appartenant à un autre projet, renvoie 404 —
l'existence n'est jamais divulguée entre projets.
Lister les jobs
GET /v2/ingest renvoie les jobs de ce projet du plus récent au plus ancien,
avec les paramètres de requête skip et limit. limit vaut 20 par
défaut et est plafonné à 100. La réponse porte un drapeau has_more plutôt
qu'un comptage total :
curl "https://api.enconvert.com/v2/ingest?skip=0&limit=20" \
-H "X-API-Key: sk_live_your_private_key"
{
"jobs": [
{
"job_id": "ing_3f9a...",
"status": "completed",
"mode": "crawl",
"pages_discovered": 42,
"pages_processed": 41,
"pages_failed": 1,
"total_chunks": 1187,
"output_url": "https://spaces.example.com/...signed...",
"webhook_configured": true,
"webhook_delivered": true,
"created_at": "2026-06-24T09:14:02.118Z",
"completed_at": "2026-06-24T09:31:55.402Z"
}
],
"skip": 0,
"limit": 20,
"has_more": false
}
Les lignes de la liste réduisent webhook_url à un booléen
webhook_configured — la liste ne renvoie jamais l'endpoint brut dans le
tableau.
Annuler un job
DELETE /v2/ingest/{job_id} met le statut du job sur canceled. Le worker
lit ce statut entre deux pages et s'arrête sans assembler de sortie.
L'annulation est idempotente et insensible aux conditions de course : si
l'assemblage est déjà acté, le DELETE ne correspond à rien et le job est
renvoyé inchangé comme completed — un job terminé n'est jamais ramené de
force à canceled.
curl -X DELETE \
https://api.enconvert.com/v2/ingest/ing_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7 \
-H "X-API-Key: sk_live_your_private_key"
Webhooks de complétion
Définissez webhook_url sur le POST et EnConvert envoie un seul POST signé
en HMAC quand le job se termine. La charge utile est du JSON compact, trié
par clé :
{"job_id":"ing_3f9a...","output_url":"https://spaces.example.com/...signed...","pages_processed":41,"status":"completed","total_chunks":1187}
La livraison réessaie jusqu'à trois fois après la première tentative, avec des délais de back-off de 1, 4, et 16 secondes — quatre POST au pire des cas. Chaque tentative est re-signée avec un nouvel horodatage, donc une chaîne de réessais lente ne dérive jamais hors de la fenêtre de fraîcheur du consommateur. Une réponse 2xx vaut succès ; un endpoint mort est enregistré comme une non-livraison (et lève une alerte dans le dashboard), il ne fait jamais échouer un job par ailleurs terminé.
Le webhook_url est filtré SSRF au moment de la livraison, pas à la
soumission. Une URL qui se résout en une adresse privée, de loopback, ou de
métadonnées est stockée inertement et seulement rejetée lorsque EnConvert
tente de la POST.
Vérifier la signature
Chaque livraison porte deux en-têtes :
| En-tête | Valeur |
|---|---|
X-Enconvert-Signature |
sha256=<hex> — le HMAC-SHA256 de <timestamp>.<raw body>. |
X-Enconvert-Timestamp |
L'horodatage en secondes unix lié dans la signature. |
L'entrée de signature est l'horodatage, un . littéral, puis le corps brut
de la requête. Lier l'horodatage dans le MAC signifie qu'un consommateur qui
rejette les horodatages périmés obtient gratuitement une protection contre le
rejeu — la fenêtre de fraîcheur par défaut est de 300 secondes. Vérifiez
dans votre handler :
import hashlib
import hmac
import time
SECRET = "whsec_your_signing_secret" # from GET /v2/ingest/webhook-secret
TOLERANCE_SECONDS = 300
def verify(raw_body: bytes, signature_header: str, timestamp_header: str) -> bool:
if not signature_header or not timestamp_header:
return False
try:
ts = int(timestamp_header)
except ValueError:
return False
if abs(time.time() - ts) > TOLERANCE_SECONDS:
return False # replayed or badly skewed clock
provided = signature_header.removeprefix("sha256=")
expected = hmac.new(
SECRET.encode("utf-8"),
f"{ts}.".encode("utf-8") + raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, provided)
Gérer le secret de signature
GET /v2/ingest/webhook-secret révèle le secret du projet (en le créant au
premier appel) ainsi que les noms d'en-têtes et la tolérance dont votre
consommateur a besoin. Il est sensible et exposé uniquement via le canal
dashboard authentifié :
{
"secret": "whsec_...",
"signature_header": "X-Enconvert-Signature",
"timestamp_header": "X-Enconvert-Timestamp",
"signature_scheme": "sha256",
"replay_tolerance_seconds": 300,
"rotated": false
}
POST /v2/ingest/webhook-secret/rotate émet un nouveau secret et met
rotated sur true. Toute signature calculée avec le secret précédent cesse
de se vérifier dès que la rotation est actée — effectuez la rotation après
une fuite suspectée, puis mettez à jour votre consommateur.
Re-livrer un webhook
Si votre endpoint était hors service quand le job s'est terminé,
POST /v2/ingest/{job_id}/retry-webhook re-signe et re-POST avec la même
politique de réessais :
curl -X POST \
https://api.enconvert.com/v2/ingest/ing_3f9a.../retry-webhook \
-H "X-API-Key: sk_live_your_private_key"
{
"job_id": "ing_3f9a...",
"delivered": true,
"attempts": 1,
"status_code": 200,
"detail": "Delivered (HTTP 200)."
}
Il renvoie 404 pour un job_id inconnu ou étranger, 400 quand aucun
webhook_url n'est configuré (ou que l'URL stockée se résout désormais en
une adresse privée/interne), et 409 quand le job n'a pas atteint
completed.
Exemples de code
curl — liste explicite d'URL
curl -X POST https://api.enconvert.com/v2/ingest \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"mode": "urls",
"urls": [
"https://example.com/docs/intro",
"https://example.com/docs/quickstart",
"https://example.com/docs/api"
]
}'
curl — crawl avec chunking et un webhook
curl -X POST https://api.enconvert.com/v2/ingest \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"mode": "crawl",
"url": "https://example.com/docs",
"max_pages": 200,
"max_depth": 3,
"include_patterns": ["/docs/"],
"chunk": {"max_words": 700, "sentence_overlap": 2},
"webhook_url": "https://your-app.example.com/hooks/ingest"
}'
Python — soumettre, interroger, télécharger
import time
import requests
BASE = "https://api.enconvert.com"
HEADERS = {"X-API-Key": "sk_live_your_private_key"}
# 1. Submit (always 202).
job = requests.post(
f"{BASE}/v2/ingest",
headers=HEADERS,
json={"mode": "crawl", "url": "https://example.com/docs", "max_pages": 100},
).json()
job_id = job["job_id"]
# 2. Poll until terminal.
while True:
job = requests.get(f"{BASE}/v2/ingest/{job_id}", headers=HEADERS).json()
if job["status"] in ("completed", "failed", "canceled"):
break
time.sleep(5)
# 3. Download the JSONL from its signed URL.
if job["status"] == "completed":
jsonl = requests.get(job["output_url"]).text
print(f"{job['total_chunks']} chunks across "
f"{job['pages_processed']} pages")
print(jsonl.splitlines()[0])
Node.js — soumettre et interroger
const BASE = "https://api.enconvert.com";
const HEADERS = {
"Content-Type": "application/json",
"X-API-Key": "sk_live_your_private_key"
};
// 1. Submit.
const submit = await fetch(`${BASE}/v2/ingest`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
mode: "crawl",
url: "https://example.com/docs",
max_pages: 100
})
});
let job = await submit.json();
// 2. Poll until terminal.
while (!["completed", "failed", "canceled"].includes(job.status)) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await fetch(`${BASE}/v2/ingest/${job.job_id}`, {
headers: { "X-API-Key": HEADERS["X-API-Key"] }
});
job = await poll.json();
}
// 3. Download the JSONL.
if (job.status === "completed") {
const jsonl = await fetch(job.output_url).then((r) => r.text());
console.log(`${job.total_chunks} chunks`);
console.log(jsonl.split("\n")[0]);
}
Encadrement par le plan
L'ingestion V2 est mesurée par son propre compteur, ingest_pages — distinct
des conversions V1 et des autres compteurs V2. Une page est facturée pour
chaque URL dont l'étape de rendu, de chunking et de JSONL s'achève ; les
pages qui échouent ou sont ignorées ne sont pas facturées.
Le contrôle à la soumission est une barrière rapide units=1 : votre plan
doit avoir l'ingestion activée, avec un peu de marge mensuelle. Le vrai
limiteur de dépense est le contrôle par page à l'intérieur du worker — un
job crawl s'arrête proprement à votre plafond mensuel et marque les pages
restantes skipped plutôt que de le dépasser.
| Barrière | Comportement |
|---|---|
| Plan sans ingestion activée | 402 à la soumission — passez à un plan incluant V2. |
Quota mensuel ingest_pages épuisé |
402 à la soumission ; ou, si épuisé en plein job, les pages restantes sont marquées skipped. |
| Illimité (entreprise / admin) | Une limite de 0 avec le drapeau activé signifie aucun plafond mensuel. |
MAX_PAGES_PER_JOB (1 000) est un plafond par requête qui borne un seul job ;
ce n'est pas votre allocation mensuelle. Le quota mensuel ingest_pages est
le vrai limiteur de dépense. Les chiffres actuels par palier se trouvent sur
la page tarifs ; voir aussi comment les opérations perceive
sont mesurées pour le compteur V2 voisin.
Réponses d'erreur
| Statut | Condition |
|---|---|
202 Accepted |
Le job a été créé et mis en file. C'est le résultat normal d'un POST. |
401 Unauthorized |
Clé d'API / jeton JWT manquant ou invalide. |
402 Payment Required |
L'ingestion n'est pas sur votre plan actuel, ou votre quota mensuel ingest_pages est épuisé. |
403 Forbidden |
/v2/ingest n'est pas dans les endpoints autorisés de la clé d'API. |
404 Not Found |
job_id inconnu, ou détenu par un autre projet. |
409 Conflict |
retry-webhook appelé sur un job qui n'a pas atteint completed. |
400 Bad Request |
retry-webhook appelé sans webhook_url configuré, ou son URL stockée se résout désormais en une adresse privée/interne. |
422 Unprocessable Entity |
La source ne correspond pas au mode (urls sans urls, ou une url de départ en mode urls) ; un paramètre est hors plage ; ou une regex include_patterns/exclude_patterns ne se compile pas. |
500 Internal Server Error |
Le job n'a pas pu être créé. Le message inclut le job_id à citer au support. |
Un échec de rendu au niveau d'une page ne fait pas échouer la requête ni
le job — il incrémente pages_failed, place l'erreur de la page dans sa
propre ligne, et le job continue. Un job ne fails que lorsque la découverte
est rejetée ou que toutes les pages échouent ou sont ignorées. La référence
complète des codes de statut figure dans
le guide des codes d'erreur.
Limites
| Limite | Valeur |
|---|---|
URL par requête en mode urls |
1 000 |
Longueur de url / de chaque entrée urls |
2 048 caractères |
max_pages (plafond de découverte) |
1–1 000 |
max_depth |
1–5 |
include_patterns / exclude_patterns |
50 chacun |
Longueur de wait_for |
1 024 caractères |
wait_timeout_ms |
0–60 000 ms |
chunk.max_words |
32–4 000 (défaut 512) |
chunk.sentence_overlap |
0–10 (défaut 1) |
Longueur de webhook_url |
2 048 caractères |
Plafond de pages par job (MAX_PAGES_PER_JOB) |
1 000 |
limit de la liste GET /v2/ingest |
1–100 (défaut 20) |
Expiration de l'output_url signée |
15 minutes |
| Tentatives de livraison du webhook | 4 (initiale + 3 réessais) |
| Tolérance au rejeu du webhook | 300 secondes |
ingest_pages mensuel |
Dépend du plan — voir tarifs |