Ingestion de fichiers#
Il y a deux façons d'envoyer des octets à EnConvert : téléverser le fichier vous-même en multipart/form-data, ou passer une url et laisser l'API récupérer la ressource. Celle que vous pouvez utiliser dépend de l'endpoint, pas de votre plan.
Quel endpoint accepte quoi#
| Famille d'endpoints | Comment arrivent les octets | Nom du champ |
|---|---|---|
| Formats de données, documents, images | Téléversement multipart/form-data, un fichier par requête |
file |
Pages web (url-to-pdf, url-to-screenshot, url-to-markdown, website-to-pdf, website-to-screenshot) |
Corps JSON, EnConvert récupère la page | url |
POST /v2/ingest/files |
multipart/form-data, plusieurs fichiers par job |
files |
POST /v2/perceive, POST /v2/ingest |
Corps JSON, EnConvert récupère la page | url |
Il n'y a pas de troisième voie. Les endpoints de téléversement ne récupèrent pas d'URL à votre place, y compris les routes fourre-tout anything-to-pdf et anything-to-markdown. Pour transformer une page en ligne en PDF, appelez plutôt url-to-pdf. Pour savoir quels formats accepte chaque endpoint, voir formats pris en charge.
Téléverser un fichier local#
Le champ de formulaire s'appelle file, et chaque endpoint de téléversement V1 en accepte exactement un. Tout le reste du formulaire est facultatif.
| Champ de formulaire | Type | Description |
|---|---|---|
file |
file | Le fichier à convertir. Son extension doit être acceptée par l'endpoint. |
output_filename |
string |
Nom de base personnalisé pour la sortie. L'extension cible est ajoutée pour vous. |
job_id |
string |
ID de tâche fourni par le client pour la reprise après timeout. Interrogez GET /v1/convert/status/{job_id} si la connexion est coupée. |
pdf_options |
string |
Chaîne JSON d'options PDF, sur les endpoints qui produisent un PDF. |
direct_download |
boolean |
Accepté pour garder la même forme de requête que les endpoints URL. Sans effet ici : un téléversement répond toujours avec l'enveloppe JSON ci-dessous, quoi que vous envoyiez. |
curl#
curl -X POST https://api.enconvert.com/v1/convert/anything-to-pdf \
-H "X-API-Key: sk_your_private_key" \
-F "[email protected]" \
-F "direct_download=false"
La réponse est du JSON avec un lien de téléchargement pré-signé :
{
"presigned_url": "https://spaces.example.com/...signed...",
"object_key": "env/files/{project_id}/anything-to-pdf/quarterly-report_20260714_101530123.pdf",
"filename": "quarterly-report_20260714_101530123.pdf",
"file_size": 51240,
"conversion_time_seconds": 2.1,
"job_id": null
}
Les mêmes valeurs sont reprises dans les en-têtes de réponse X-Object-Key, X-File-Size, X-Conversion-Time et X-Filename, vous pouvez donc les lire sans analyser le corps. Récupérez le fichier rapidement : le lien est de courte durée, et URLs signées précise exactement à quel point.
Python#
import requests
with open("quarterly-report.docx", "rb") as f:
response = requests.post(
"https://api.enconvert.com/v1/convert/anything-to-pdf",
headers={"X-API-Key": "sk_your_private_key"},
files={"file": ("quarterly-report.docx", f)},
data={"direct_download": "false"},
)
response.raise_for_status()
result = response.json()
# Download the PDF from the pre-signed URL.
pdf = requests.get(result["presigned_url"]).content
with open("quarterly-report.pdf", "wb") as out:
out.write(pdf)
Node.js#
import { readFile, writeFile } from "node:fs/promises";
const form = new FormData();
form.append(
"file",
new Blob([await readFile("quarterly-report.docx")]),
"quarterly-report.docx"
);
form.append("direct_download", "false");
const response = await fetch(
"https://api.enconvert.com/v1/convert/anything-to-pdf",
{ method: "POST", headers: { "X-API-Key": "sk_your_private_key" }, body: form }
);
const result = await response.json();
const pdf = await fetch(result.presigned_url).then((r) => r.arrayBuffer());
await writeFile("quarterly-report.pdf", Buffer.from(pdf));
Plusieurs fichiers en un seul appel#
POST /v2/ingest/files est le seul endpoint qui accepte plus d'un fichier. Répétez le champ files, jusqu'à 200 fichiers par job :
curl -X POST https://api.enconvert.com/v2/ingest/files \
-H "X-API-Key: sk_your_private_key" \
-F "[email protected]" \
-F "[email protected]" \
-F "[email protected]" \
-F "max_words=700" \
-F "webhook_url=https://your-app.example.com/hooks/ingest"
Chaque fichier est converti en Markdown, découpé en chunks et assemblé dans un seul livrable JSONL. Le job est toujours asynchrone et répond 202 Accepted avec un job_id. Tous les détails sont sur la page de l'endpoint ingest.
Laisser EnConvert récupérer le fichier#
Sur les endpoints URL, vous envoyez un corps JSON au lieu d'un formulaire, et c'est l'API qui effectue la récupération :
curl -X POST https://api.enconvert.com/v1/convert/url-to-markdown \
-H "X-API-Key: sk_your_private_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/report"}'
url accepte une chaîne ou un tableau de chaînes. Un tableau bascule la requête en asynchrone, ce que couvre Traitement par lot.
Sources derrière une authentification#
Trois champs facultatifs permettent à la récupération de porter des identifiants. Les trois nécessitent un plan avec accès à l'authentification basique (Indie et au-dessus).
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
auth |
object |
null |
Identifiants HTTP Basic Auth : {"username": "...", "password": "..."}. |
cookies |
array |
null |
Tableau d'objets cookie injectés avant la navigation. 50 maximum par requête. Chacun exige name, value, et soit domain, soit url. |
headers |
object |
null |
En-têtes HTTP personnalisés envoyés avec les requêtes. 20 maximum par requête. Ne peuvent pas inclure les en-têtes bloqués : host, content-length, transfer-encoding, connection, upgrade, te, trailer. |
auth, ainsi qu'un en-tête Authorization (par exemple un jeton Bearer) passé via headers, sont envoyés uniquement à l'origine cible, jamais aux sous-ressources tierces que la page demande. Cela évite toute fuite d'identifiants vers des hôtes publicitaires, d'analytics ou de CDN.
Adresses privées et internes#
L'url doit être une adresse publique http:// ou https://. Avant toute récupération, elle est filtrée et rejetée avec 400 Bad Request lorsqu'elle :
- utilise un schéma autre que
http/https; - intègre des identifiants comme
https://user:pass@host/(utilisez plutôt le champauth) ; - vise
localhost, un nom d'hôte de métadonnées cloud, ou une IP qui se résout dans une plage privée, loopback, link-local, réservée ou non publique d'une autre manière ; - utilise une notation IP non standard (octale, hexadécimale ou entier compact) qui pourrait se résoudre de façon ambiguë.
Cela s'applique à l'URL de départ, à chaque URL d'un lot, et aux pages découvertes par les endpoints de crawl website-to-*.
Dit simplement : EnConvert s'exécute en dehors de votre réseau. Il ne peut pas atteindre http://10.0.0.5/report.docx, un nom d'hôte .internal, ni quoi que ce soit qui ne se résout qu'à l'intérieur de votre VPC. Soit vous rendez le fichier joignable depuis l'internet public, soit vous lisez les octets vous-même et vous les téléversez.
Ce qu'il advient de votre nom de fichier#
Le nom que vous envoyez remplit deux rôles.
Il choisit le convertisseur. L'extension décide quel chemin d'entrée s'exécute : nommez donc le fichier correctement. Un fichier appelé report sans extension est rejeté par tout endpoint doté d'une liste d'extensions autorisées.
Il amorce le nom de sortie. Le nom du fichier de sortie est construit ainsi :
{base}_{YYYYMMDD_HHMMSSmmm}.{ext}
L'horodatage UTC est toujours ajouté, si bien que deux conversions du même fichier n'entrent jamais en collision. base est résolu dans cet ordre :
output_filename, si vous en avez envoyé un. Si vous y avez inclus l'extension cible, celle-ci est d'abord retirée pour que vous n'obteniez pasreport.pdf_20260405_123456789.pdf.- Le nom du fichier téléversé sans son extension.
report.docxproduitreport_20260405_123456789.pdf. - Pour les conversions d'URL, le domaine.
https://example.com/pageproduitexample_20260405_123456789.pdf. - À défaut de tout cela, le littéral
output.
La clé de stockage est assainie avant l'écriture du résultat : seul le nom de base survit, .. est supprimé, les caractères <>:"|?* sont retirés et les espaces deviennent des tirets bas. Téléversez My Report (final).docx et le PDF atterrit sous My_Report_(final)_20260405_123456789.pdf. Ce chemin vous est renvoyé dans object_key et a la forme {env}/files/{project_id}/{endpoint}/{filename}.
Les noms de fichiers envoyés à POST /v2/ingest/files sont en outre plafonnés à 255 caractères.
Plafond de taille et le 413#
Le plafond de téléversement dépend du plan et s'applique à chaque fichier individuellement.
| Plan | Taille max de téléversement | Octets |
|---|---|---|
| Founding | 5 MB | 5242880 |
| Indie | 15 MB | 15728640 |
| Studio | 50 MB | 52428800 |
| Production | 150 MB | 157286400 |
| Enterprise | Négociée | Selon contrat |
La taille est mesurée sur la partie téléversée elle-même, au fil de l'arrivée du corps, et non d'après un en-tête que vous contrôlez : un envoi en chunked sans Content-Length est donc vérifié de la même manière. Un dépassement renvoie 413 Payload Too Large avant tout travail de conversion et avant la facturation de la moindre op :
{
"detail": {
"error": "File too large",
"file_size": 10485760,
"max_size": 5242880,
"tier": "free",
"key_type": "private"
}
}
file_size et max_size sont tous deux en octets. tier est le slug du plan (free, starter, pro, business, enterprise), pas le nom affiché que vous voyez sur la page tarifaire : un projet Studio rapporte donc "tier": "pro". key_type vaut private, public ou dashboard, avec repli sur unknown.
Franchir le contrôle de taille n'est pas le dernier obstacle. Une allocation mensuelle épuisée répond 402 Payment Required, et trop de requêtes dans une fenêtre répondent 429, deux cas décrits dans Limites de débit et quotas.
Type de contenu et octets magiques#
Les téléversements passent deux contrôles, dans cet ordre.
1. La liste d'extensions autorisées. Chaque endpoint déclare les extensions qu'il accepte. Une non-correspondance donne 400 Bad Request :
{
"detail": "Invalid file format '.pdf' for png-to-jpeg. Allowed: .png"
}
2. Le reniflage des octets magiques. Les premiers octets du fichier sont comparés au groupe que revendique son extension. Une non-correspondance à forte confiance donne elle aussi 400 :
{
"detail": "File content does not match the 'png-to-jpeg' input type."
}
C'est ce que vous obtenez quand vous renommez un PDF en .png et le téléversez : les octets commencent par %PDF-, l'extension dit PNG, et les deux se contredisent. Ce contrôle existe parce que c'est l'extension qui achemine votre requête. Sans lui, des octets PDF arrivent dans un décodeur d'images et vous récoltez un échec opaque au fond du convertisseur au lieu d'un 400 clair dès la porte, et un fichier délibérément mal étiqueté se retrouve confié à un parseur qui n'aurait jamais dû le voir.
Deux choses que ce contrôle ne fait pas, toutes deux bonnes à connaître :
- Le
Content-Typede la partie n'est jamais inspecté. Il n'y a aucune liste MIME autorisée nulle part dans le chemin de téléversement :application/octet-streampasse donc sans problème. L'extension du nom de fichier est la seule chose qui achemine la requête, ce qui explique pourquoi l'envoi d'un fichier sans extension échoue. - Les formats texte n'ont pas de signature fiable et sautent complètement le reniflage :
.json,.csv,.xml,.yaml,.toml,.md,.html,.svg,.txt. Un fichier.jsonqui contient en réalité du CSV est accepté à ce stade et échoue plus tard, dans le parseur.
Les signatures binaires reconnues sont PNG, JPEG, GIF, WebP, HEIC/HEIF, PDF et le groupe bureautique (un conteneur ZIP pour .docx/.xlsx/.pptx/ODF/EPUB, ou l'ancien OLE2 pour .doc/.xls/.ppt). Le reniflage est délibérément permissif : les octets qu'il ne reconnaît pas passent plutôt que d'être bloqués.
Fichiers volumineux : la checklist#
- Vérifiez le plafond d'abord. Un 413 est bon marché pour l'API et coûteux pour vous, car vous avez téléversé le corps entier pour l'obtenir.
- Attendez-vous à un téléversement synchrone.
async_moden'existe que sururl-to-pdf,url-to-screenshoteturl-to-markdown. Les endpoints de téléversement l'ignorent et convertissent toujours à l'intérieur de la requête. Voir tâches synchrones et asynchrones. - Envoyez un
job_idque vous avez généré. Si un proxy placé devant vous coupe la connexion avant la fin de la conversion, le travail se termine quand même. InterrogezGET /v1/convert/status/{job_id}et vous obtenez{"status": "processing"}, puis soit{"status": "success", "presigned_url": ..., "object_key": ...}, soit{"status": "failed", "error": ...}. Réutiliser votre propre ID relance cette tâche ; réutiliser l'ID d'un autre projet renvoie409. - Prévoyez les timeouts. Une requête est plafonnée à 300 secondes de bout en bout, après quoi vous obtenez
504avec{"error": "Request timeout"}. Les conversions bureautiques adossées à LibreOffice ont leur propre plafond de 120 secondes, remonté lui aussi en504. - Gérez le
503avecRetry-After: 10. Les conversions de fichiers s'exécutent derrière un contrôle d'admission doté d'une file d'attente bornée. Quand la file est pleine, la requête est refusée immédiatement plutôt que de patienter : réessayez donc après l'intervalle indiqué dans l'en-tête. - Pour beaucoup de documents, changez d'endpoint.
POST /v2/ingest/filesaccepte jusqu'à 200 fichiers, renvoie202immédiatement avec unjob_id, et accepte unwebhook_urlpour que vous n'ayez jamais à interroger. Voir webhooks. - Téléchargez rapidement. Les liens de sortie sont signés et expirent. Si le vôtre a expiré, relisez l'endpoint de statut : chaque interrogation émet un nouveau lien vers le même objet stocké.
Questions fréquentes#
Quel nom de champ l'API EnConvert attend-elle pour un téléversement de fichier ?#
file, envoyé en multipart/form-data, un fichier par requête, sur chaque endpoint de conversion V1 qui accepte un téléversement. L'exception est POST /v2/ingest/files, qui utilise files et accepte jusqu'à 200 fichiers par job.
EnConvert peut-il télécharger le fichier depuis une URL au lieu que je le téléverse ?#
Uniquement sur les endpoints URL (url-to-pdf, url-to-screenshot, url-to-markdown, website-to-pdf, website-to-screenshot) et les endpoints V2 /v2/perceive et /v2/ingest. Les endpoints de conversion par téléversement n'ont pas de paramètre url. Toute URL que vous passez doit être joignable publiquement : les adresses privées, loopback, link-local et de métadonnées cloud sont rejetées avec 400.
Pourquoi mon téléversement a-t-il renvoyé 413 Payload Too Large ?#
Le fichier dépassait le plafond par fichier de votre plan, soit 5 MB sur Founding, 15 MB sur Indie, 50 MB sur Studio et 150 MB sur Production. Le corps de la réponse porte un objet detail avec error, file_size, max_size, tier et key_type pour que vous puissiez montrer à l'appelant les chiffres exacts.
Pourquoi mon téléversement PNG échoue-t-il avec « File content does not match » ?#
Les premiers octets du fichier appartiennent à un format différent de celui que revendique son extension, par exemple un PDF renommé en .png. Envoyez le fichier sous sa véritable extension. Les formats texte comme .json et .csv ne sont jamais vérifiés octet par octet, cette erreur n'apparaît donc que pour les types binaires.
Puis-je téléverser un fichier volumineux de manière asynchrone ?#
Pas sur les endpoints de téléversement V1 : ils convertissent toujours dans la requête. Envoyez un job_id généré par le client et interrogez GET /v1/convert/status/{job_id} pour survivre à une connexion coupée, ou utilisez POST /v2/ingest/files, asynchrone par conception et capable d'appeler un webhook à la fin du job.