Ingest
POST /v2/ingest trasforma un sito — o un elenco esplicito di URL — in
chunk pronti per il RAG ed emette un solo file JSONL che si carica
direttamente in LangChain JSONLoader, LlamaIndex SimpleDirectoryReader
o un import massivo in un vector-DB. Sostituisce lo stack in due fasi che
altrimenti dovresti costruire: Firecrawl /crawl per scoprire ed estrarre
i contenuti, più il tuo chunker per affettare il Markdown. EnConvert si
occupa della discovery, del rendering headless-Chrome, del chunking
consapevole delle intestazioni e dell'assemblaggio del JSONL in un solo
job.
Ecco la chiamata utile più piccola. Fai il crawl di un sito e chunka ogni pagina che scopre:
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 risposta è il record del job, restituito con 202 Accepted. Nota che
lo status è queued, e output_url è assente finché il job non si
completa:
{
"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"
}
Ingest è sempre asincrono. Ogni pagina viene renderizzata in un
browser reale, il che richiede 10–30 secondi per URL — ben oltre la
finestra di richiesta di 300 secondi per qualsiasi job non banale. Quindi
POST risponde 202 con un job_id, e un worker locale sul droplet
svuota il job fuori banda. Fai il polling di
GET /v2/ingest/{job_id} per i progressi, oppure registra un
webhook_url per essere avvisato al completamento.
Vale la pena segnalarlo subito.
/v2/ingestè un endpoint V2 con il proprio contatore di quota,ingest_pages. I piani di conversione V1 non includono alcun budget di ingest — serve un piano che includa V2 per chiamarlo. Viene addebitata una pagina per ogni URL il cui stage di render, chunk e JSONL si completa; le pagine che falliscono o vengono saltate non vengono addebitate. Vedi la pagina dei prezzi per i budget per livello, e la panoramica V2 per come i contatori V2 differiscono dalle conversioni V1.
Endpoints
| Method | Path | Scopo |
|---|---|---|
POST |
/v2/ingest |
Crea un job di ingest. Risponde 202 con un job_id. |
GET |
/v2/ingest |
Elenco dei job di questo progetto, dal più recente, con paging skip/limit. |
GET |
/v2/ingest/{job_id} |
Stato del ciclo di vita di un job, con un output_url appena firmato una volta completato. |
DELETE |
/v2/ingest/{job_id} |
Annulla un job. Il worker vede lo status canceled e si ferma tra una pagina e l'altra. |
POST |
/v2/ingest/{job_id}/retry-webhook |
Ri-firma e ri-invia in POST il webhook di completamento per un job completato. |
GET |
/v2/ingest/webhook-secret |
Rivela il segreto di firma dei webhook del progetto (canale dashboard). |
POST |
/v2/ingest/webhook-secret/rotate |
Ruota il segreto di firma. Le vecchie firme smettono di verificarsi immediatamente. |
Content-Type: application/json su ogni POST.
Autenticazione
Autenticati con una chiave privata nell'header X-API-Key per le chiamate
server-to-server. Questo è il percorso usato dagli esempi seguenti.
X-API-Key: sk_live_your_private_key
Funzionano anche le chiavi pubbliche con un token bearer JWT, usando lo
stesso flusso di ogni altro endpoint — genera un token con la tua chiave
pk_, poi invialo come Authorization: Bearer <token>. Il flusso
completo, inclusi il domain locking e il refresh del token, è ne la guida
all'autenticazione.
Ogni chiave API porta con sé una allowlist di endpoint consentiti. Se
/v2/ingest non è nell'elenco della chiave, la richiesta viene rifiutata
con 403. Una chiave con scope su /v2/ingest raggiunge comunque i job
che ha creato — GET e DELETE
/v2/ingest/{job_id} e POST /v2/ingest/{job_id}/retry-webhook sono
sempre consentiti per un job_id (la forma ing_… viene confrontata in
modo esplicito). L'endpoint di elenco statico e le due route di gestione
webhook-secret non ereditano quel bypass; richiedono un token più
ampio o con scope dashboard.
Come funziona l'ingest
Un job attraversa cinque fasi, tutte durevoli e a prova di riavvio. Se il processo worker si riavvia a metà job, il job viene ri-accodato all'avvio e riprende dalla pagina su cui si era fermato — le pagine già completate mantengono il loro output in staging e non vengono mai ri-renderizzate né ri-addebitate.
- Queue.
POSTvalida la richiesta, esegue un veloce controllo di quotaunits=1(il piano ha ingest abilitato e un po' di margine mensile), inserisce la riga del job e risponde202. Nulla viene persistito se il gate di quota fallisce — un402non lascia alcuna riga dietro di sé. - Discover. Per le modalità
sitemapecrawlil worker esegue lo stesso passaggio di discovery di l'endpoint discover, limitato amax_pages, e applica lo screening SSRF all'URL seed. Per la modalitàurlsl'elenco esplicito viene deduplicato nell'ordine dato; nessuna discovery viene eseguita. - Render and chunk. Ogni URL viene renderizzato attraverso il singleton headless Chrome condiviso — la stessa pipeline di rendering dietro l'endpoint perceive — poi l'HTML renderizzato viene convertito in fit-Markdown e affettato dal chunker consapevole delle intestazioni. I rendering vengono eseguiti in sequenza, una pagina alla volta.
- Stage. I chunk di ogni pagina vengono scritti in un oggetto JSONL
per pagina nello storage, con chiave deterministica basata su
(project, job, url). È questo che rende economico un riavvio: un job ripreso riutilizza le pagine in staging invece di ri-renderizzarle. - Assemble. Una volta che ogni pagina è pronta, gli oggetti per pagina
vengono concatenati nel
v2-ingest/{job_id}.jsonlfinale, gli oggetti di staging vengono eliminati, il job passa acompletede — se era impostato unwebhook_url— scatta il webhook di completamento firmato.
Il contatore di quota viene ri-controllato per pagina dentro il
worker, non solo al momento dell'invio. Un job crawl il cui conteggio di
pagine è ignoto in partenza si ferma in modo pulito al tuo limite mensile:
le pagine già renderizzate vengono addebitate e conservate, e le pagine
rimanenti vengono marcate skipped invece di sforare la spesa.
I rendering di ingest sono privi di credenziali per progettazione. A
differenza di /v2/perceive, non accetta auth, cookies o headers
personalizzati — nulla di segreto viene persistito per il resume durevole,
quindi lo stato del job su disco non porta mai con sé credenziali.
Parametri della richiesta
Sorgente e modalità
| Parameter | Type | Default | Descrizione |
|---|---|---|---|
mode |
string |
"urls" |
urls, sitemap o crawl. Seleziona come viene costruito l'insieme di URL. |
url |
string |
null |
URL seed per la modalità sitemap/crawl. Deve iniziare con http:// o https://. Massimo 2.048 caratteri. Richiesto per quelle modalità; rifiutato in modalità urls. |
urls |
string[] |
null |
URL espliciti da ingerire in modalità urls. Non vuoto, massimo 1.000 voci, ciascuna http(s) e ≤ 2.048 caratteri. Richiesto per la modalità urls; rifiutato in modalità sitemap/crawl. |
url e urls si escludono a vicenda — esattamente una sorgente. La
modalità urls richiede urls; sitemap e crawl richiedono un url
seed. Inviare quello sbagliato per la modalità è un 422.
Discovery (modalità sitemap / crawl)
Questi vengono inoltrati al passaggio di discovery e ignorati in modalità
urls.
| Parameter | Type | Default | Descrizione |
|---|---|---|---|
max_pages |
integer |
50 |
Limite sugli URL scoperti e ingeriti. 1–1.000. |
max_depth |
integer |
2 |
Profondità dei link nel crawl a partire dal seed. 1–5. |
same_domain_only |
boolean |
true |
Restringe la discovery al dominio del seed. |
include_patterns |
string[] |
[] |
Pattern regex che un URL deve soddisfare per essere mantenuto. Massimo 50. Ciascuno viene compilato all'invio; un pattern errato è un 422. |
exclude_patterns |
string[] |
[] |
Pattern regex che scartano un URL corrispondente. Massimo 50. |
respect_robots |
boolean |
false |
Quando è true, un URL non consentito dal robots.txt del sito viene saltato. |
Rendering
| Parameter | Type | Default | Descrizione |
|---|---|---|---|
wait_for |
string |
null |
Dopo la navigazione, attende un selettore CSS o un'espressione JS prima di catturare. Massimo 1.024 caratteri. |
wait_timeout_ms |
integer |
30000 |
Per quanto tempo wait_for può attendere, in millisecondi. 0–60.000. |
Nota. Ingest non accetta
auth,cookiesoheaders. Se una pagina ha bisogno di credenziali per essere renderizzata, ingest è lo strumento sbagliato — usa l'endpoint perceive, che porta con sé l'intera superficie di richiesta autenticata, per quella singola pagina.
Chunking (oggetto chunk)
| Parameter | Type | Default | Vincoli | Descrizione |
|---|---|---|---|---|
max_words |
integer |
512 |
32–4.000 | Limite soft di parole per chunk. Consapevole delle intestazioni. I blocchi di codice e le tabelle pipe restano atomici e possono superarlo. |
sentence_overlap |
integer |
1 |
0–10 | Frasi ripetute tra chunk di prosa consecutivi della stessa sezione. 0 disabilita l'overlap. L'overlap non attraversa mai un confine di intestazione. |
Il chunker divide sulle intestazioni #, ## e ### — ogni chunk
appartiene a esattamente una sezione e porta con sé il proprio percorso
completo di intestazioni. Le intestazioni più profonde (####–######)
restano inline come contenuto. I blocchi di codice recintati e le tabelle
Markdown non vengono mai divisi, anche quando un singolo blocco supera
max_words; gli elementi di lista si dividono tra le voci, mai a metà
voce.
Webhook
| Parameter | Type | Default | Descrizione |
|---|---|---|---|
webhook_url |
string |
null |
Endpoint che riceve la callback di completamento firmata con HMAC. Massimo 2.048 caratteri. Lo schema viene controllato all'invio; lo screening SSRF avviene al momento della consegna, non dell'invio. |
Response
POST, GET /v2/ingest/{job_id} e DELETE restituiscono tutti lo stesso
oggetto IngestJobResponse.
| Field | Type | Descrizione |
|---|---|---|
job_id |
string |
ID opaco (ing_…). Usalo con gli endpoint GET/DELETE e citalo al supporto. |
status |
string |
queued, discovering, processing, completed, failed o canceled. |
mode |
string |
La modalità che hai inviato: urls, sitemap o crawl. |
pages_discovered |
integer |
URL che il job ingerirà (l'elenco esplicito, o il risultato della discovery). |
pages_processed |
integer |
URL il cui render → chunk → stage si è completato. |
pages_failed |
integer |
URL che non sono riusciti a renderizzare o sono stati saltati (es. quota esaurita). |
total_chunks |
integer |
Totale dei chunk scritti su tutte le pagine completate — corrisponde al conteggio di righe del JSONL. |
output_url |
string |
URL di download pre-firmato per il JSONL finale. Presente solo quando status è completed; scade dopo 15 minuti. |
error_message |
string |
Impostato quando status è failed (es. discovery rifiutata, tutte le pagine fallite). |
webhook_url |
string |
Il target del webhook di completamento registrato per questo job, se presente. |
webhook_delivered |
boolean |
true una volta che il webhook di completamento firmato ha ricevuto un 2xx. |
created_at |
string |
Quando il job è stato creato (UTC). |
completed_at |
string |
Quando il job ha raggiunto uno status terminale (UTC). |
warnings |
string[] |
Note non fatali. |
Nota.
POSTe ilGET/DELETEper singolo job usanoresponse_model_exclude_none, quindi i campi ancoranull(comeoutput_urlprima del completamento) vengono omessi dal JSON anziché inviati comenull.
La forma del record JSONL
Il file finale è JSON delimitato da newline. Ogni riga è 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}}
| Field | Type | Descrizione |
|---|---|---|
id |
string |
Deterministico per (source_url, chunk_index): <md5(url)[:12]>-<index:04d>. Una ri-esecuzione produce id identici. |
content |
string |
Il testo del chunk recuperabile. Mappa su Document.page_content in LangChain. |
metadata.source_url |
string |
La pagina da cui proviene il chunk. |
metadata.title |
string |
Il <title> della pagina, con fallback sul primo <h1>, limitato a 512 caratteri. |
metadata.headings_path |
string[] |
Il percorso h1 → h2 → h3 sotto cui si trova il chunk. |
metadata.section |
string |
Il testo dell'intestazione più interna (l'ultima voce di headings_path). |
metadata.word_count |
integer |
Conteggio di parole di content, delimitate da spazi bianchi. |
metadata.chunk_index |
integer |
L'indice del chunk all'interno della sua pagina. |
Il file è UTF-8, scritto con ensure_ascii=false, quindi l'unicode resta
leggibile. Poiché content è una stringa di primo livello e metadata è
un oggetto fratello, lo stesso file si carica tramite LangChain
JSONLoader(content_key="content", json_lines=True), LlamaIndex
SimpleDirectoryReader e qualsiasi import vector-DB orientato alle righe
senza alcuna ristrutturazione.
Ciclo di vita del job e polling
Un job attraversa questi stati:
queued → discovering → processing → completed | failed | canceled
| Status | Significato |
|---|---|
queued |
Accettato e in attesa del worker. |
discovering |
Esegue il passaggio di discovery sitemap/crawl (solo sitemap/crawl). |
processing |
Rendering e chunking delle pagine. pages_processed e total_chunks salgono in tempo reale. |
completed |
Il JSONL finale è assemblato; output_url è firmato e pronto. |
failed |
La discovery è stata rifiutata, oppure ogni pagina è fallita o è stata saltata. error_message spiega. |
canceled |
Un DELETE ha raggiunto il job prima che terminasse. |
Fai il polling dello status con il GET per singolo job. È in sola
lettura — non consuma quota e ri-firma l'output_url dalla chiave
dell'oggetto memorizzato a ogni chiamata:
curl https://api.enconvert.com/v2/ingest/ing_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7 \
-H "X-API-Key: sk_live_your_private_key"
Un job_id sconosciuto, o uno che appartiene a un progetto diverso,
restituisce 404 — l'esistenza non viene mai rivelata tra progetti.
Elenco dei job
GET /v2/ingest restituisce i job di questo progetto dal più recente, con
i query param skip e limit. limit ha default 20 ed è limitato a
100. La risposta porta un flag has_more invece di un conteggio totale:
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
}
Le righe dell'elenco riducono webhook_url a un booleano
webhook_configured — l'elenco non rimanda mai l'endpoint grezzo nella
tabella.
Annullamento di un job
DELETE /v2/ingest/{job_id} imposta lo status del job a canceled. Il
worker legge quello status tra una pagina e l'altra e si ferma senza
assemblare l'output. L'annullamento è idempotente e a prova di race: se
l'assemblaggio è già stato confermato, il DELETE non corrisponde a nulla
e il job viene restituito invariato come completed — un job concluso non
viene mai riportato indietro a canceled.
curl -X DELETE \
https://api.enconvert.com/v2/ingest/ing_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7 \
-H "X-API-Key: sk_live_your_private_key"
Webhook di completamento
Imposta webhook_url sul POST ed EnConvert invia un POST firmato con
HMAC quando il job si completa. Il payload è JSON compatto, con chiavi
ordinate:
{"job_id":"ing_3f9a...","output_url":"https://spaces.example.com/...signed...","pages_processed":41,"status":"completed","total_chunks":1187}
La consegna ritenta fino a tre volte dopo il primo tentativo, con ritardi di back-off di 1, 4 e 16 secondi — quattro POST nel caso peggiore. Ogni tentativo viene ri-firmato con un timestamp fresco, così una catena di retry lenta non va mai oltre la finestra di freschezza del consumer. Una risposta 2xx è un successo; un endpoint morto viene registrato come mancata consegna (e fa scattare un alert nella dashboard), non affossa mai un job altrimenti completato.
Il webhook_url viene sottoposto a screening SSRF al momento della
consegna, non all'invio. Un URL che risolve a un indirizzo privato, di
loopback o di metadata viene memorizzato in modo inerte e rifiutato solo
quando EnConvert prova a inviarci un POST.
Verifica della firma
Ogni consegna porta due header:
| Header | Valore |
|---|---|
X-Enconvert-Signature |
sha256=<hex> — l'HMAC-SHA256 di <timestamp>.<raw body>. |
X-Enconvert-Timestamp |
Il timestamp in unix-seconds legato alla firma. |
L'input di firma è il timestamp, un . letterale, poi il corpo grezzo
della richiesta. Legare il timestamp nel MAC significa che un consumer che
rifiuta i timestamp scaduti ottiene gratis la protezione dal replay — la
finestra di freschezza di default è 300 secondi. Verifica nel tuo
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)
Gestione del segreto di firma
GET /v2/ingest/webhook-secret rivela il segreto del progetto (creandolo
alla prima chiamata) insieme ai nomi degli header e alla tolleranza di cui
il tuo consumer ha bisogno. È sensibile ed esposto solo sul canale
autenticato della dashboard:
{
"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 emette un nuovo segreto e imposta
rotated a true. Ogni firma calcolata con il segreto precedente smette
di verificarsi nel momento in cui la rotazione viene confermata — ruota
dopo un sospetto leak, poi aggiorna il tuo consumer.
Riconsegna di un webhook
Se il tuo endpoint era giù quando il job è terminato,
POST /v2/ingest/{job_id}/retry-webhook ri-firma e ri-invia in POST con la
stessa policy di retry:
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)."
}
Restituisce 404 per un job_id sconosciuto o estraneo, 400 quando
nessun webhook_url è configurato (o l'URL memorizzato ora risolve a un
indirizzo privato/interno), e 409 quando il job non ha raggiunto
completed.
Esempi di codice
curl — elenco esplicito di 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 con chunking e 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 — invio, polling, download
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 — invio e polling
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]);
}
Gating del piano
L'ingest V2 è misurato dal proprio contatore, ingest_pages — separato
dalle conversioni V1 e dagli altri contatori V2. Viene addebitata una
pagina per ogni URL il cui stage di render, chunk e JSONL si completa; le
pagine che falliscono o vengono saltate non vengono addebitate.
Il controllo al momento dell'invio è un veloce gate units=1: il tuo piano
deve avere ingest abilitato, con un po' di margine mensile. Il vero
limitatore di spesa è il controllo per pagina dentro il worker — un job
crawl si ferma in modo pulito al tuo limite mensile e marca le pagine
rimanenti skipped invece di sforarlo.
| Gate | Comportamento |
|---|---|
| Piano senza ingest abilitato | 402 all'invio — passa a un piano che include V2. |
Quota mensile ingest_pages esaurita |
402 all'invio; oppure, se esaurita a metà job, le pagine rimanenti vengono marcate skipped. |
| Illimitato (enterprise / admin) | Un limite di 0 con il flag abilitato significa nessun limite mensile. |
MAX_PAGES_PER_JOB (1.000) è un tetto per richiesta che delimita un
singolo job; non è il tuo budget mensile. La quota mensile ingest_pages è
il vero limitatore di spesa. I numeri attuali per livello sono su
la pagina dei prezzi; vedi anche come vengono misurate le
operazioni perceive per il contatore V2
gemello.
Risposte di errore
| Status | Condizione |
|---|---|
202 Accepted |
Il job è stato creato e accodato. Questo è l'esito normale del POST. |
401 Unauthorized |
Chiave API / token JWT mancante o non valido. |
402 Payment Required |
L'ingest non è nel tuo piano attuale, oppure la tua quota mensile ingest_pages è esaurita. |
403 Forbidden |
/v2/ingest non è negli endpoint consentiti della chiave API. |
404 Not Found |
job_id sconosciuto, o uno posseduto da un altro progetto. |
409 Conflict |
retry-webhook chiamato su un job che non ha raggiunto completed. |
400 Bad Request |
retry-webhook chiamato senza alcun webhook_url configurato, oppure il suo URL memorizzato ora risolve a un indirizzo privato/interno. |
422 Unprocessable Entity |
La sorgente non corrisponde alla modalità (urls senza urls, o un url seed in modalità urls); un parametro è fuori range; oppure una regex di include_patterns/exclude_patterns non compila. |
500 Internal Server Error |
Impossibile creare il job. Il messaggio include il job_id da citare al supporto. |
Un fallimento di render a livello di pagina non fa fallire la richiesta
né il job — incrementa pages_failed, deposita l'errore della pagina nella
sua riga e il job continua. Un job fails solo quando la discovery viene
rifiutata oppure ogni pagina fallisce o viene saltata. Il riferimento
completo dei codici di stato è ne la guida ai codici di errore.
Limiti
| Limite | Valore |
|---|---|
URL per richiesta in modalità urls |
1.000 |
Lunghezza di url / di ciascuna voce urls |
2.048 caratteri |
max_pages (limite di discovery) |
1–1.000 |
max_depth |
1–5 |
include_patterns / exclude_patterns |
50 ciascuno |
Lunghezza di wait_for |
1.024 caratteri |
wait_timeout_ms |
0–60.000 ms |
chunk.max_words |
32–4.000 (default 512) |
chunk.sentence_overlap |
0–10 (default 1) |
Lunghezza di webhook_url |
2.048 caratteri |
Tetto di pagine per job (MAX_PAGES_PER_JOB) |
1.000 |
limit dell'elenco GET /v2/ingest |
1–100 (default 20) |
Scadenza dell'output_url firmato |
15 minuti |
| Tentativi di consegna del webhook | 4 (iniziale + 3 retry) |
| Tolleranza di replay del webhook | 300 secondi |
ingest_pages mensili |
Dipende dal piano — vedi prezzi |