Codici di errore dell'API EnConvert#
Questo riferimento elenca i codici di stato HTTP e i messaggi di errore restituiti dall'API EnConvert, da 200 OK per le conversioni sincrone e 202 Accepted per i job asincroni e batch, fino alle risposte di errore documentate di seguito. Ogni sezione di errore elenca le stringhe di messaggio esatte, la condizione che le attiva e come correggere la richiesta. I corpi di errore non hanno tutti la stessa forma: ne esistono sei, e la sezione Formato della risposta di errore le mostra una per una.
Un job che fallisce dopo essere stato accettato non è un errore HTTP. Il 202 resta valido e il fallimento compare nel payload di stato del job quando lo interroghi in polling, come descritto in Job sincroni e asincroni.
Codici di stato HTTP#
| Code | Status | Description |
|---|---|---|
200 |
OK | Conversione completata con successo (modalità sincrona). |
202 |
Accepted | Il job batch o asincrono è stato accettato per l'elaborazione in background. |
400 |
Bad Request | Parametri non validi, campi obbligatori mancanti, corpo della richiesta malformato o contenuto del file non valido. |
401 |
Unauthorized | Chiave API o token JWT mancante, non valido o scaduto. |
402 |
Payment Required | Quota mensile di ops esaurita, nessun periodo di fatturazione attivo, tetto dei watcher raggiunto, limite di archiviazione raggiunto oppure un endpoint V2 disattivato sul tuo piano. |
403 |
Forbidden | Restrizione su tipo di chiave, dominio o allowlist degli endpoint, un gate di funzionalità V1 (async, webhook, output ZIP, autenticazione di base, batch) oppure accesso a una risorsa di un altro progetto. |
404 |
Not Found | La risorsa richiesta (job, batch, operation, file, watcher o widget) non esiste, oppure il percorso non è una route. |
405 |
Method Not Allowed | Il percorso esiste, ma non per il metodo HTTP che hai usato. |
409 |
Conflict | Un job_id fornito dal client è già in uso, oppure è stato richiesto un nuovo invio del webhook per un job di ingest non ancora completato. |
410 |
Gone | Un artefatto V2 o un archivio batch ha superato la finestra di conservazione dei file del tuo piano e non è più nell'archiviazione. |
413 |
Payload Too Large | Il file caricato supera il limite di dimensione del tuo piano di abbonamento. |
415 |
Unsupported Media Type | L'URL di destinazione ha restituito un contenuto che questo convertitore non può renderizzare (ad es. JSON su url-to-pdf). |
422 |
Unprocessable Entity | Il corpo della richiesta non ha superato la validazione dello schema (inclusi i campi sconosciuti sugli endpoint V2), oppure una precondizione di rendering non è stata soddisfatta, ad esempio un wait_for_selector che non è mai comparso. |
429 |
Too Many Requests | È scattato un limite di frequenza delle richieste su finestra breve. Non è il codice della quota: l'esaurimento della quota mensile risponde 402. |
500 |
Internal Server Error | Errore imprevisto durante la conversione (il nostro motore ha avuto un guasto). |
502 |
Bad Gateway | Non è stato possibile raggiungere il sito di destinazione, un provider upstream ha avuto un guasto, oppure la destinazione ha restituito una challenge anti-bot senza contenuto di pagina (/v2/perceive, a meno che non sia impostato allow_degraded). |
503 |
Service Unavailable | Un convertitore non è disponibile, il pool di rendering o il gate di ammissione delle conversioni è al massimo della capacità, oppure una dipendenza upstream è fuori servizio. |
504 |
Gateway Timeout | Il sito di destinazione ha impiegato troppo tempo a rispondere o a completare il caricamento, oppure la richiesta ha superato il budget di 300 secondi del gateway. |
Formato della risposta di errore#
Esistono sei forme di corpo. Quale ricevi dipende da dove si è verificato il guasto, non dal solo codice di stato: controlla quindi il tipo di detail prima di leggerlo.
1. detail di tipo stringa. Il caso comune, e l'unica forma che la maggior parte delle integrazioni incontra.
{
"detail": "Authentication required"
}
2. detail di tipo oggetto. Il 413 sulla dimensione del file prevista dal piano. L'oggetto strutturato è il valore di detail, quindi leggi body.detail.max_size, non body.max_size. Consulta 413 Payload Too Large.
{
"detail": {
"error": "File too large",
"file_size": 10485760,
"max_size": 5242880,
"tier": "free",
"key_type": "private"
}
}
3. detail di tipo array più errors. La validazione dello schema (422) restituisce entrambi: detail è l'output grezzo del validatore, errors è un array parallelo di stringhe leggibili dalle persone. Consulta 422 Unprocessable Entity.
4. Envelope di conversione tipizzato. {"error", "code", "detail"}, con un code leggibile dalla macchina. Emesso solo dai tre endpoint V1 di conversione da URL. Consulta Errori di conversione del browser.
5. Eccezione non gestita. Un 500 che non proviene da un convertitore non ha alcun detail:
{
"error": "Internal server error",
"event_id": "a1b2c3d4"
}
6. Timeout della richiesta al gateway. Il budget di 300 secondi del gateway stesso produce un 504 senza detail e senza code:
{
"error": "Request timeout"
}
400 Bad Request#
Restituito quando la richiesta contiene parametri non validi, campi mancanti o dati malformati.
Validazione dell'input#
| Message | Condition |
|---|---|
'url' must be provided |
Campo url mancante o vuoto sugli endpoint basati su URL. |
Invalid file format '{ext}' for {endpoint}. Allowed: {list} |
L'estensione del file caricato non corrisponde ai formati accettati dall'endpoint. |
File content does not match the '{endpoint}' input type. |
L'estensione è stata accettata, ma i magic byte del file appartengono a un formato diverso. |
Invalid pdf_options: {error} |
JSON malformato nel campo form pdf_options. |
Validazione di batch e modalità#
| Message | Condition |
|---|---|
Public keys only support a single URL input |
Una chiave pubblica/dashboard ha tentato di inviare più URL. |
output_format=True requires multiple URLs |
Bundling ZIP richiesto con un solo URL. |
direct_download not supported for multiple URLs |
direct_download=true con un array di URL. |
direct_download only works in sync mode |
direct_download=true combinato con async_mode=true. |
Validazione di auth, cookie e header#
| Message | Condition |
|---|---|
'auth' must be an object with 'username' and 'password' |
Il parametro auth ha una struttura errata. |
'cookies' must be an array of cookie objects |
cookies non è un array. |
'cookies' array must not exceed 50 entries |
Sono stati forniti più di 50 cookie. |
Cookie at index {i} must be an object |
La voce del cookie non è un dizionario. |
Cookie at index {i} must have 'name' and 'value' |
Al cookie mancano campi obbligatori. |
Cookie at index {i} must have 'domain' or 'url' |
Al cookie mancano sia domain che url. |
'headers' must be an object of header name/value pairs |
headers non è un dizionario. |
'headers' must not exceed 20 entries |
Più di 20 header personalizzati. |
Header '{name}' cannot be overridden |
Tentativo di impostare un header bloccato. L'insieme bloccato è host, content-length, transfer-encoding, connection, upgrade, te, trailer. |
Header '{name}' value must be a string |
Il valore dell'header non è una stringa. |
Cannot use both 'auth' and an 'Authorization' header. Use 'auth' for HTTP Basic Auth or 'headers' for Bearer/custom auth, not both. |
Forniti sia l'oggetto auth sia un header personalizzato Authorization. |
Sicurezza degli URL (SSRF)#
Ogni endpoint basato su URL esamina l'url di destinazione prima di recuperarlo. Questi messaggi vengono restituiti come 400 quando l'URL non è un indirizzo pubblico http(s).
| Message | Condition |
|---|---|
Only http:// and https:// URLs are supported. |
L'URL usa uno schema diverso da http o https. |
URLs with embedded credentials are not allowed. Use the 'auth' field for HTTP Basic Auth. |
L'URL incorpora un nome utente/password (https://user:pass@host/). |
URL has no hostname. |
Non è stato possibile analizzare l'URL per estrarre un host. |
This hostname is not allowed. |
L'host è localhost o un hostname di metadati cloud. |
URLs resolving to private or internal addresses are not allowed. |
L'URL è, o si risolve in, un IP privato, di loopback, link-local, riservato o comunque non pubblico. |
Non-standard IP address notation is not allowed. |
L'host usa una notazione IP ottale, esadecimale o a intero compatto che potrebbe risolversi in modo ambiguo. |
Could not resolve hostname '{hostname}'. |
La risoluzione DNS per l'host è fallita. |
This URL is blocked by the site's threat policy. |
L'host di destinazione è nella denylist della threat policy, verificata insieme al controllo SSRF. |
Validazione delle opzioni di rendering#
| Message | Condition |
|---|---|
'wait_for_selector' must be a string |
wait_for_selector non era una stringa. |
'wait_for_selector' is too long (max 1000 chars) |
Il selettore supera i 1000 caratteri. |
'wait_for_selector_timeout' must be a positive integer (ms) |
Il timeout è mancante, zero, negativo o non è un intero. |
'wait_for_selector_timeout' must not exceed 60000 ms |
Il timeout supera il limite massimo di 60 secondi. |
'block_ads' must be a boolean / 'block_media' must be a boolean |
Il flag di blocco non era un boolean. |
Errori di sitemap e crawl#
| Message | Condition |
|---|---|
No URLs found in sitemap: {url} |
La sitemap è stata analizzata ma non contiene URL. |
Timeout fetching sitemap: {url} |
Il recupero della sitemap ha superato il timeout di 30 secondi. |
Could not fetch sitemap: {url} returned {status} |
L'URL della sitemap ha restituito uno stato HTTP diverso da 200. |
Invalid XML in sitemap: {url} |
Non è stato possibile analizzare l'XML della sitemap. |
Unrecognized sitemap format at {url}: root element is <{tag}> |
L'elemento radice della sitemap non è <urlset> né <sitemapindex>. |
No pages discovered on {base_url} |
Il crawl completo è terminato ma non ha trovato alcuna pagina. |
Errori di contenuto nella conversione#
| Message | Condition |
|---|---|
Invalid JSON: {error} |
Il file JSON contiene una sintassi JSON non valida. |
Invalid YAML: {error} |
Il file YAML contiene una sintassi YAML non valida. |
Invalid TOML: {error} |
Il file TOML contiene una sintassi TOML non valida. |
Invalid HTML encoding (expected UTF-8) |
Il file HTML non è codificato in UTF-8. |
Invalid Markdown encoding (expected UTF-8) |
Il file Markdown non è codificato in UTF-8. |
JSON must be an array of objects for CSV conversion |
L'input di json-to-csv non è un array. |
JSON array is empty |
L'input di json-to-csv è un array vuoto. |
CSV file is empty or has no valid rows |
Il file CSV non contiene righe di dati. |
XML structure cannot be converted to CSV |
L'XML non è tabellare (xml-to-csv). |
Turnstile verification failed |
La sfida bot Cloudflare Turnstile non è andata a buon fine. |
Turnstile token required |
Richiesta del widget senza un token Turnstile. |
401 Unauthorized#
Restituito quando l'autenticazione è mancante o non valida.
| Message | Condition |
|---|---|
Authentication required |
Nessuna chiave API e nessun token JWT fornito nella richiesta. |
Invalid API Key format |
La chiave API è troppo corta o non inizia con sk_ o pk_. |
Invalid API Key |
L'hash della chiave API non è stato trovato nel database. |
API Key revoked |
La chiave API è stata disattivata dalla dashboard. |
Token has expired |
Il token di accesso JWT è scaduto (durata di 1 ora). |
Invalid token |
Il JWT è malformato, manomesso o comunque non valido. |
Refresh token has expired |
Il refresh token è scaduto (durata di 7 giorni). |
Invalid refresh token |
Il refresh token è malformato o non valido. |
Invalid token type |
Il token è stato decodificato con successo ma non è del tipo previsto (refresh). |
No refresh token |
L'endpoint di refresh del widget è stato chiamato senza un cookie refresh_token. |
Refresh token not found |
Il refresh token presentato non è memorizzato per nessuna sessione. |
User not found or invalid |
Il token è stato decodificato, ma il suo subject non corrisponde più a un account utilizzabile. |
Project not found |
Non è stato possibile analizzare l'id del progetto sulla chiave o sul token durante la verifica della quota di ops. |
402 Payment Required#
Restituito quando un limite di utilizzo viene superato. La divisione tra 402 e 403 non è simmetrica, e coglie molti di sorpresa. Ogni condizione di quota risponde 402, e lo stesso vale per un endpoint V2 disattivato sul tuo piano. I gate di funzionalità V1 rispondono 403 (async, webhook, output ZIP, autenticazione di base, batch). Il rate limiting è un meccanismo separato che risponde 429, mai 402.
| Message | Condition |
|---|---|
Monthly operations limit reached ({used}/{limit}). Upgrade your plan to continue. |
Il contatore mensile unificato di ops ha raggiunto la quota del piano. Piano Founding: 500 ops. Ogni endpoint attinge da questo unico contatore. Su qualsiasi piano a pagamento con eccedenza attivata, le richieste proseguono a $0.02/op invece di fallire. |
This request needs {units} operations but only {remaining} of your {limit} monthly operations remain. Upgrade your plan to continue. |
La richiesta batch supererebbe la quota mensile di ops residua. L'intero batch viene rifiutato in anticipo. |
No active billing period found for this project. Contact support to restore your subscription. |
Il progetto non ha un periodo di utilizzo e non è stato possibile crearne uno dal suo abbonamento. Il gate fallisce in modo chiuso invece di concedere un'operazione gratuita. |
Storage limit reached. Delete files or upgrade your storage plan to continue. |
L'utilizzo dell'archiviazione del progetto ha raggiunto l'allocazione di archiviazione del piano. |
Active watcher limit reached ({active_count}/{limit}). Delete an existing watcher or upgrade your plan to add more. |
Il progetto ha già il numero massimo di watcher attivi previsto dal suo piano. I watcher non consumano ops: questo è un tetto su quanti possono esistere contemporaneamente. |
{Feature} is not available on your current plan. Upgrade to a V2-inclusive plan to access this endpoint. |
Un endpoint V2 è disabilitato per il piano. |
Esaurire i crediti AI mensili non produce un 402. L'estrazione tramite schema ricade sul risultato euristico e CSS e la richiesta va comunque a buon fine. Quote, prezzi e cosa conta come una singola operazione sono in Rate limit e quote.
403 Forbidden#
Restituito quando l'accesso è negato a causa di restrizioni su tipo di chiave, dominio, funzionalità del piano V1 o endpoint. I gate degli endpoint V2 sono l'eccezione: rispondono 402, non 403.
Restrizioni su chiavi API e token#
| Message | Condition |
|---|---|
Private API keys cannot be used from browsers |
Una chiave privata (sk_...) è stata usata in una richiesta con un header Origin del browser. Usa invece una chiave pubblica con JWT. |
Domain {origin} not authorized |
L'origine della richiesta non corrisponde ad alcun dominio nell'elenco dei domini consentiti della chiave API. |
Public API keys can only be used to generate JWT tokens or fetch widget branding. Please exchange your public key for a JWT token at /v1/auth/token, then use the token for API calls. |
Una chiave pubblica è stata usata su un percorso diverso da /auth/token o /auth/branding. Scambiala prima per un JWT. |
Endpoint '{path}' not allowed for this API key |
L'elenco allowed_endpoints della chiave API non include il percorso richiesto. |
Endpoint '{path}' not allowed for this token |
L'elenco allowed_endpoints del token JWT non include il percorso richiesto. |
Token issued for different origin |
L'origine della richiesta non corrisponde all'origine registrata nel JWT (previene il furto del token). |
Parent origin does not match token |
L'header X-Parent-Origin non corrisponde a quanto convalidato all'emissione del token. |
Restrizioni delle funzionalità del piano#
| Message | Condition |
|---|---|
Async processing is not available on your current plan. Please upgrade to access this feature. |
async_mode=true su un piano senza accesso asincrono. |
Webhook callbacks is not available on your current plan. Please upgrade to access this feature. |
callback_url fornito su un piano senza accesso ai webhook. |
ZIP output bundling is not available on your current plan. Please upgrade to access this feature. |
output_format=true su un piano senza accesso all'output ZIP. |
Basic authentication, cookies & custom headers is not available on your current plan. Please upgrade to access this feature. |
auth, cookies o headers usati su un piano senza accesso all'autenticazione di base. |
Batch processing is not available on your current plan. Please upgrade to access this feature. |
URL multipli inviati su un piano con batch_limit pari a 0. |
Batch size {N} exceeds your plan's limit of {M} URLs per batch. |
Il numero di URL supera il limite di dimensione del batch del piano. |
Website crawling is not available on your current plan. Please upgrade to access this feature. |
Endpoint di acquisizione del sito web usato su un piano con crawl_mode "none" (piano Founding). |
Full website crawling requires a Studio plan or higher. Your plan supports sitemap-based crawling only. |
crawl_mode=full richiesto su un piano Indie che supporta solo il crawling basato su sitemap. |
Restrizioni dei widget#
| Message | Condition |
|---|---|
Widget API key has been revoked |
La chiave API interna collegata al widget è stata disattivata. |
Domain {origin} is not authorized for this widget |
Il dominio di embedding del widget non è nell'elenco dei domini consentiti del widget. |
Refresh token does not match widget |
L'ID progetto del refresh token non corrisponde al progetto del widget. |
Batch status requires a private API key |
Una chiave pubblica o dashboard ha tentato di accedere a GET /v1/convert/batch/{batch_id}. |
Access denied |
Tentativo di accedere a una risorsa (stato del job, file) appartenente a un progetto diverso. |
Altri due messaggi 403 non riguardano né le chiavi né i piani: Account suspended, restituito per ogni richiesta quando l'account dietro la chiave o il token è sospeso, e robots.txt disallows fetching this URL (request sent respect_robots=true)., restituito da perceive quando hai chiesto la conformità a robots e la destinazione non consente quel percorso.
404 Not Found#
| Message | Condition |
|---|---|
Job not found |
ID del job di conversione non trovato nel database (polling dello stato). |
Batch not found |
L'ID del batch non ha righe di attività corrispondenti per questo progetto. |
File not found |
Il file richiesto non esiste nell'archiviazione (endpoint di download). |
Widget not found |
ID del widget non trovato o widget disattivato. |
Operation not found, Ingest job not found, Watcher not found |
Un id di risorsa V2 che non esiste, oppure appartiene a un altro progetto. L'esistenza non viene mai rivelata tra progetti diversi. |
Not Found |
Il percorso non è una route dell'API. Controlla il percorso e il prefisso di versione. |
409 Conflict#
| Message | Condition |
|---|---|
job_id already in use |
Un job_id fornito dal client è già assegnato a un altro progetto. Scegli un id diverso, oppure lascia che sia l'API a generarlo. |
A completion webhook is only delivered for completed jobs. |
È stato richiesto un nuovo invio del webhook per un job di ingest che non ha raggiunto lo stato completed. |
410 Gone#
L'artefatto esisteva, ma ha superato la finestra di conservazione dei file del tuo piano e non è più nell'archiviazione. La conservazione dipende dal piano; consulta Rate limit e quote.
| Message | Condition |
|---|---|
The artifact is no longer in storage (it may have passed your plan's file-retention window). Re-run the perceive request to regenerate it. |
Download dell'artefatto su GET /v2/perceive/{operation_id}. |
The batch archive is no longer in storage (it may have passed your plan's file-retention window). |
Download dello ZIP su GET /v2/perceive/batch/{job_id}. |
Considera il 410 come definitivo per quell'oggetto. Rieseguire la richiesta produce un artefatto nuovo; ritentare il download no.
413 Payload Too Large#
Restituito quando il file caricato supera la dimensione massima del file del piano.
detail, non un oggetto di primo livello. Leggi body.detail.max_size.
{
"detail": {
"error": "File too large",
"file_size": 10485760,
"max_size": 5242880,
"tier": "free",
"key_type": "private"
}
}
| Field | Description |
|---|---|
error |
Sempre "File too large". |
file_size |
La dimensione del file caricato in byte. |
max_size |
La dimensione massima del file consentita per il tuo piano in byte. |
tier |
Lo slug del tuo piano di abbonamento (ad es. "free", "starter", "pro"), con ripiego su "free" quando nessun piano viene risolto. Gli slug sono identificatori API stabili; i nomi commerciali sono Founding (free), Indie (starter), Studio (pro) e Production (business). |
key_type |
Il tipo di chiave API usata: "private", "public" o "unknown". |
Il limite viene verificato sul conteggio esatto dei byte della parte caricata prima che inizi qualsiasi lavoro di conversione. Un file di dimensione esattamente pari a max_size viene accettato; viene rifiutato solo un file più grande. L'header Content-Length è un ripiego per i vecchi punti di chiamata che non passano al controllo il proprio oggetto di upload.
POST /v2/ingest/files non usa questa forma. Risponde 413 con un detail di tipo stringa semplice: File '{filename}' exceeds the {max_size}-byte limit.
I tetti per piano sono elencati in Rate limit e quote, e i percorsi di upload a cui questo si applica sono in Ingestione dei file.
Errori di conversione del browser (415 / 422 / 502 / 504)#
Le conversioni da URL distinguono un guasto nel sito di destinazione o nell'input (un 4xx, 502 o 504 su cui puoi intervenire) da un guasto nel nostro motore (un 500). I tre endpoint V1 di conversione da URL (url-to-pdf, url-to-screenshot, url-to-markdown) restituiscono questi guasti tipizzati con un code leggibile dalla macchina accanto a detail:
{
"error": "Gateway Timeout",
"code": "upstream_timeout",
"detail": "The target site took too long to respond while rendering PDF for https://example.com."
}
| Code | code field |
Condition |
|---|---|---|
415 |
unsupported_content_type |
La destinazione ha restituito un contenuto che il convertitore non può renderizzare, ad esempio application/json inviato su url-to-pdf o url-to-screenshot. Usa url-to-markdown per il JSON. |
422 |
selector_not_found |
Un wait_for_selector fornito dal chiamante non è mai comparso entro wait_for_selector_timeout. |
502 |
upstream_unreachable |
Non è stato possibile raggiungere il sito di destinazione (guasto DNS o di connessione). |
502 |
empty_render |
La navigazione è terminata ma la pagina non ha prodotto alcun contenuto catturabile. |
504 |
upstream_timeout |
Il sito di destinazione ha impiegato troppo tempo a rispondere o a completare il caricamento. |
Questi cinque sono l'intero vocabolario. Nessun'altra famiglia di endpoint emette un code, V2 inclusa: un guasto V2 torna come una semplice stringa detail. La classe base dell'envelope definisce un sesto slug, conversion_error, ma nulla lo solleva, quindi non ti raggiunge mai. Ramifica sui cinque qui sopra e tratta qualsiasi altro valore come sconosciuto.
Un 504 può arrivare anche in due forme non tipizzate: {"error": "Request timeout"} quando la richiesta supera il budget di 300 secondi del gateway, e un detail di tipo stringa semplice che porta il messaggio di timeout quando una conversione di documento (LibreOffice) va in timeout. Nessuna delle due porta un code.
422 Unprocessable Entity#
I fallimenti di validazione dello schema restituiscono due array paralleli. detail è l'output grezzo del validatore, ed è quello che rimappi sui campi del form. errors è una stringa leggibile per ogni problema, ed è quella che mostri all'utente.
{
"detail": [
{
"loc": ["body", "max_pages"],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"type": "int_parsing"
}
],
"errors": [
"body.max_pages: Input should be a valid integer, unable to parse string as an integer (you sent 'ten')"
]
}
Vale la pena gestire per nome tre valori di type:
type |
Meaning |
|---|---|
extra_forbidden |
Campo sconosciuto. Gli schemi di richiesta V2 rifiutano le chiavi sconosciute invece di ignorarle, quindi un parametro scritto male è un 422 che nomina il campo, invece di un'opzione scartata in silenzio. |
missing |
Un campo obbligatorio non è stato inviato. |
json_invalid |
Il corpo della richiesta non era JSON valido. |
POST /v2/perceive/batch restituisce un 422 il cui detail è un semplice elenco di oggetti {"loc", "msg"}, senza chiave type e senza array errors di primo livello. I parser che danno per scontata la presenza di errors si rompono lì.
Un 422 con code selector_not_found è un'altra cosa: una precondizione di rendering non soddisfatta, trattata in Errori di conversione del browser.
429 Too Many Requests#
Il rate limiting è un controllo di equità su finestra breve ed è separato dalla quota mensile di ops. Esaurire la quota risponde 402; solo il rate limiter risponde 429.
| Message | Condition |
|---|---|
Rate limit exceeded. Please slow down and retry shortly. |
È stata superata una finestra di frequenza delle richieste per il progetto. I bucket sono per progetto e hanno un namespace per tipo di chiave, quindi il traffico pubblico e quello privato non ne condividono uno. |
Un 429 porta con sé quattro header:
| Header | Meaning |
|---|---|
RateLimit-Limit |
Richieste consentite nella finestra che è scattata. |
RateLimit-Remaining |
Richieste rimaste in quella finestra, 0 in caso di rifiuto. |
RateLimit-Reset |
Secondi che mancano al reset della finestra. |
Retry-After |
Lo stesso valore di RateLimit-Reset. Attendi questo tempo prima di riprovare. |
Questi header compaiono solo sul 429. Le risposte andate a buon fine non portano header di rate limit né header di ops residue, quindi non puoi leggere il budget rimanente da una risposta: controlla l'utilizzo nella dashboard. Consulta Rate limit e quote.
500 Internal Server Error#
| Message | Condition |
|---|---|
Conversion failed: {error} |
Un errore imprevisto durante la conversione di un file caricato. Le conversioni da URL non usano questo messaggio: emergono come envelope tipizzato qui sopra, oppure come corpo generico qui sotto. |
Perception failed. Reference operation_id '{id}' when contacting support. |
Un guasto imprevisto all'interno di un'esecuzione di /v2/perceive. Gli altri endpoint V2 hanno equivalenti, come Distillation failed. Reference operation_id ... e Could not start ingest job. Reference job_id .... Cita l'id quando contatti il supporto. |
Tutto ciò che va in errore fuori da un convertitore non ti raggiunge mai come testo. Torna del tutto privo di detail:
{
"error": "Internal server error",
"event_id": "a1b2c3d4"
}
Un caso coglie di sorpresa: un corpo JSON malformato inviato a un endpoint URL V1 (url-to-pdf, url-to-screenshot, url-to-markdown, website-to-pdf, website-to-screenshot) restituisce questo 500 invece di un 422, perché quegli endpoint leggono il corpo grezzo. Lo stesso corpo malformato su un endpoint V2 restituisce un 422 con type: json_invalid.
Se riscontri errori 500 persistenti, il problema è probabilmente legato al file o all'URL di input. Prova con un input diverso per isolare il problema.
503 Service Unavailable#
| Message | Condition |
|---|---|
Converter not available: {endpoint} |
Il convertitore richiesto non è registrato o non è in esecuzione. |
Converter not available |
Il convertitore basato su URL per l'endpoint richiesto non è disponibile. |
The conversion service is at capacity. Please retry shortly. |
Il pool di rendering del browser non ha slot liberi. Inviato con Retry-After: 30. |
Server is at capacity. Please retry shortly. |
Il gate di ammissione delle conversioni CPU è pieno: troppe conversioni di file, o troppi byte, già in corso. Inviato con Retry-After: 10. |
Search is temporarily unavailable. Please try again later. |
Il provider di ricerca upstream dietro lookup è irraggiungibile o configurato in modo errato. |
Turnstile verification unavailable |
Il servizio di verifica Cloudflare Turnstile è irraggiungibile. |
Esistono due gate di capacità diversi che chiedono attese diverse, quindi leggi Retry-After invece di darne per scontata una. Per il resto questi errori sono transitori: riprova dopo una breve attesa.
Errori degli endpoint V2#
Gli endpoint di web intelligence V2 riutilizzano i codici di stato sopra indicati, con alcune condizioni specifiche di V2 che vale la pena segnalare.
Quota e piano (402 / 403)#
Le operazioni V2 vengono conteggiate sulla stessa quota mensile unificata di ops delle conversioni V1: una op per unità di lavoro. Qualsiasi piano a pagamento con eccedenza attivata ($0.02/op) permette di superare la quota; altrimenti il limite è rigido.
| Code | Condition |
|---|---|
402 |
La quota mensile di ops è esaurita. Tutti gli endpoint V2 (perceive, discover, lookup, distill, ingest) addebitano questo unico contatore insieme alle conversioni V1. |
402 |
Il limite di watcher attivi (max_watchers) è stato raggiunto (watch). I watcher sono un tetto separato e non consumano mai ops. |
402 |
L'endpoint è disattivato per il piano. I gate V2 rispondono 402, a differenza dei gate di funzionalità V1, che rispondono 403. |
403 |
L'endpoint non è nell'allowlist allowed_endpoints della chiave API. |
Due comportamenti V2 non sono errori, deliberatamente. Esaurire il saldo di crediti AI non fa fallire la richiesta: l'estrazione tramite schema ricade sul risultato euristico e CSS. E un'esecuzione distill su più URL che supera il limite di ops a metà strada non produce nemmeno un 402: si ferma lì, restituisce gli URL che ha completato e aggiunge un avviso che indica quanti sono stati saltati.
Validazione (422)#
Ogni schema di richiesta V2 rifiuta le chiavi sconosciute, quindi un parametro scritto male è un 422 che nomina il campo. La forma del corpo è descritta in 422 Unprocessable Entity.
| Endpoint | Condition |
|---|---|
| perceive | È stato inviato proxy_url, geolocation o action_chain; questi campi sono riservati a una release successiva. |
| distill | Non è stato fornito né schema né prompt (inviarli entrambi va bene, vince schema); nessuno o entrambi tra urls e discover_from sono stati forniti; un campo CSS non valido, un tipo di campo non supportato o una regex che rischia un backtracking catastrofico. |
| watch | frequency_minutes al di sotto del minimo orario di 60 minuti; un corpo PATCH vuoto. |
| ingest | Il mode non corrisponde alla sorgente (modalità urls senza urls, oppure sitemap/crawl senza un url di partenza). |
Provider di ricerca (502 / 503)#
L'endpoint lookup dipende da un provider di ricerca upstream. Il testo grezzo dell'errore del provider non raggiunge mai il client.
| Code | Message | Condition |
|---|---|---|
502 |
The search provider returned an error. Please try again. |
Il provider ha restituito una risposta di errore o un guasto di trasporto non ritentabile. |
503 |
Search is temporarily unavailable. Please try again later. |
Il provider è configurato in modo errato (chiave mancante) o temporaneamente irraggiungibile. Riprova più tardi. |
Non trovato (404)#
GET e DELETE su un operation_id, job_id o watcher_id V2 che non esiste, o che appartiene a un progetto diverso, restituiscono 404. L'esistenza non viene mai rivelata tra progetti diversi.
Accettato (202)#
Ingest è sempre asincrono: POST /v2/ingest risponde 202 con un job_id da interrogare in polling. I batch di perceive con più di 10 URL rispondono 202 con stato queued. Un batch di 10 URL o meno normalmente risponde inline, ma se supera la finestra inline degrada a 202 con stato processing e un avviso: gestisci quindi il 202 per qualsiasi dimensione del batch.
Un 202 significa anche che i fallimenti successivi non sono errori HTTP. Interroga il job in polling e leggi il suo payload di stato, come descritto in Job sincroni e asincroni.
Risoluzione dei problemi#
Problemi di autenticazione#
- Ricevi un 401? Verifica che la tua chiave API sia valida e attiva nella dashboard. Se usi JWT, assicurati che il token non sia scaduto (durata di 1 ora).
- Ricevi un 403 relativo all'uso nel browser? Stai usando una chiave privata (
sk_...) dal codice lato client. Passa a una chiave pubblica con JWT per le richieste dal browser. - Ricevi un 403 relativo al dominio? Aggiungi il tuo dominio all'elenco dei domini consentiti della chiave API nella dashboard.
Problemi di conversione#
- Ricevi un 400 relativo al formato del file? Assicurati che l'estensione del file caricato corrisponda all'endpoint (ad es.
.jsonper json-to-xml,.docxper doc-to-pdf). - Ricevi un 413? Il tuo file supera il limite di dimensione del piano. Leggi
detail.max_sizedalla risposta, poi controlla la dimensione massima del file del tuo piano o esegui l'upgrade. - Ricevi un 402? Hai raggiunto la quota mensile di ops, il tetto dei watcher o il limite di archiviazione, oppure il progetto non ha un periodo di fatturazione attivo. Controlla l'utilizzo nella dashboard e consulta Rate limit e quote.
Problemi di accesso alle funzionalità#
- Ricevi un 403 relativo alle funzionalità del piano? La funzionalità V1 che stai cercando di usare (async, batch, webhook, output ZIP, autenticazione di base) richiede un piano di livello superiore. Consulta la tabella di gating delle funzionalità.
- Ricevi un 402 su un endpoint V2 che non riguarda la quota? I gate degli endpoint V2 rispondono
402, non403. Il messaggio recita... is not available on your current plan. Upgrade to a V2-inclusive plan to access this endpoint.
Domande frequenti#
Perché l'API restituisce 402 Payment Required per una conversione di file?#
Un 402 indica che un limite di utilizzo è esaurito: la tua quota mensile unificata di ops (500 ops sul piano Founding), il tetto dei watcher attivi o l'allocazione di archiviazione del tuo progetto. Copre anche due casi che non riguardano la quota: un progetto senza periodo di fatturazione attivo e un endpoint V2 disattivato sul tuo piano. Le richieste batch che supererebbero la quota mensile di ops residua vengono rifiutate in anticipo con un 402 per l'intero batch. Le conversioni V1 e le operazioni V2 attingono dalla stessa quota; qualsiasi piano a pagamento con eccedenza attivata ($0.02/op) permette di superarla. Il rate limiting è un meccanismo diverso e risponde 429.
Come risolvo un errore 401 Unauthorized dell'API di conversione?#
Verifica che la chiave API sia presente, inizi con sk_ o pk_ e sia ancora attiva nella dashboard, perché le chiavi revocate restituiscono API Key revoked. Se ti autentichi con un JWT, tieni presente che i token di accesso scadono dopo 1 ora (Token has expired) e i refresh token dopo 7 giorni.
Perché ricevo 413 Payload Too Large quando carico un file?#
Il file caricato supera la dimensione massima del tuo piano, misurata sul conteggio esatto dei byte della parte caricata prima che inizi qualsiasi lavoro di conversione. Un file esattamente al limite viene accettato. Il corpo del 413 annida un oggetto strutturato sotto detail, con file_size, max_size (entrambi in byte), tier e key_type: leggilo quindi come detail.max_size e non come un campo di primo livello.
Posso usare una chiave API privata da JavaScript nel browser?#
No. Una chiave privata (sk_...) usata in una richiesta con un header Origin del browser restituisce 403 Private API keys cannot be used from browsers. Scambia una chiave pubblica con un JWT su /v1/auth/token e usa quel token per le chiamate API dal browser.
Un errore 503 Service Unavailable dell'API è permanente?#
No, gli errori 503 come Converter not available: {endpoint} o Turnstile verification unavailable sono in genere transitori. Riprova la richiesta dopo una breve attesa.