API de conversion de fichiers par lot#
L'API batch d'EnConvert convertit plusieurs URLs en une seule requête : passez un tableau d'URLs à /v1/convert/url-to-pdf ou /v1/convert/url-to-screenshot et recevez une réponse HTTP 202 avec un batch_id. Chaque URL est convertie de manière asynchrone en arrière-plan, et les résultats sont livrés sous forme d'URLs de téléchargement présignées, soit une par fichier, soit regroupées dans une seule archive ZIP. Suivez la progression en interrogeant GET /v1/convert/batch/{batch_id}, ou soyez notifié par webhook ou email à la fin du traitement.
X-API-Key: sk_...). Les clés publiques sont limitées aux requêtes synchrones à URL unique.
Fonctionnement#
- Envoyez une requête avec un tableau d'URLs dans le paramètre
urlvers/v1/convert/url-to-pdfou/v1/convert/url-to-screenshot. - L'API valide le lot par rapport aux limites de votre plan et renvoie HTTP 202 avec un
batch_id. - Chaque URL est convertie en arrière-plan et facture une op. Le nombre total d'éléments du lot est vérifié au préalable par rapport à votre quota mensuel d'ops restant avant le début du traitement.
- Suivez la progression via
GET /v1/convert/batch/{batch_id}, ou recevez un webhook ou une notification par email à la fin du traitement. - Téléchargez les résultats via les URLs présignées présentes dans la réponse de statut du lot.
Modes de sortie#
Mode individuel (par défaut)#
Chaque URL produit un fichier distinct. Chaque fichier reçoit sa propre URL de téléchargement présignée dans la réponse de statut du lot.
Requête :
curl -X POST https://api.enconvert.com/v1/convert/url-to-pdf \
-H "X-API-Key: sk_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"url": [
"https://example.com/page-1",
"https://example.com/page-2",
"https://example.com/page-3"
]
}'
Réponse (HTTP 202 Accepted) :
{
"status": "processing",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"url_count": 3,
"output_format": "individual"
}
async_mode est automatiquement défini sur true, que vous l'incluiez explicitement dans la requête ou non.
Mode archive ZIP#
Définissez output_format sur true pour recevoir tous les fichiers convertis regroupés dans une seule archive ZIP. Nécessite un plan avec accès à la sortie ZIP.
Requête :
curl -X POST https://api.enconvert.com/v1/convert/url-to-pdf \
-H "X-API-Key: sk_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"url": [
"https://example.com/page-1",
"https://example.com/page-2",
"https://example.com/page-3"
],
"output_format": true,
"output_filename": "monthly-reports"
}'
Réponse (HTTP 202 Accepted) :
{
"status": "processing",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"url_count": 3,
"output_format": "zip"
}
En mode ZIP, toutes les URLs sont traitées séquentiellement, et les résultats réussis sont regroupés dans une seule archive ZIP nommée {output_filename}_{timestamp}.zip (ou batch_{timestamp}.zip si aucun nom personnalisé n'est fourni).
Paramètres du lot#
| Paramètre | Type | Par défaut | Description | Restriction de plan |
|---|---|---|---|---|
url |
string[] |
(obligatoire) | Tableau d'URLs à convertir. | -- |
output_format |
boolean |
false |
Définissez sur true pour regrouper tous les résultats dans une archive ZIP. Nécessite plusieurs URLs. |
Nécessite l'accès à la sortie ZIP |
output_filename |
string |
Généré automatiquement | Nom de fichier personnalisé pour la sortie. En mode ZIP, il nomme l'archive ZIP. | -- |
async_mode |
boolean |
true (implicite) |
Toujours true pour un lot. Activé automatiquement lorsque plusieurs URLs sont fournies. |
Nécessite l'accès asynchrone |
notification_email |
string |
Email du propriétaire du projet | Adresse email à notifier à la fin du traitement. Si omise, l'email du propriétaire du projet est utilisé par défaut. | -- |
callback_url |
string |
null |
URL du webhook qui recevra un POST à la fin du traitement. | Nécessite l'accès aux webhooks |
direct_download |
-- | -- | Non pris en charge pour un lot. Renvoie une erreur 400 si défini avec plusieurs URLs. | -- |
Paramètres du navigateur et du rendu#
Ces paramètres s'appliquent à chaque URL du lot :
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
viewport_width |
integer |
1920 |
Largeur de la fenêtre d'affichage du navigateur en pixels. |
viewport_height |
integer |
1080 |
Hauteur de la fenêtre d'affichage du navigateur en pixels. |
single_page |
boolean |
true |
Génère le rendu sous forme d'une seule page continue (url-to-pdf uniquement). |
load_media |
boolean |
true |
Attend le chargement des images et des médias. |
enable_scroll |
boolean |
true |
Fait défiler les pages pour déclencher le chargement du contenu différé (lazy-loaded). |
handle_sticky_header |
boolean |
true |
Détecte et gère les en-têtes collants/fixes. |
handle_cookies |
boolean |
true |
Ferme automatiquement les bannières de consentement aux cookies. |
wait_for_images |
boolean |
true |
Attend que toutes les images aient fini de charger. |
Authentification et requêtes personnalisées#
Ces paramètres s'appliquent à chaque URL du lot. Nécessitent un plan avec accès à l'authentification de base.
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
auth |
object |
null |
Identifiants d'authentification HTTP Basic : {"username": "...", "password": "..."}. |
cookies |
array |
null |
Tableau d'objets cookie injectés avant chaque chargement de page. Max 50. |
headers |
object |
null |
En-têtes HTTP personnalisés envoyés avec chaque requête. Max 20. |
Options PDF (url-to-pdf uniquement)#
Passez un objet pdf_options pour contrôler le format de sortie PDF de chaque page du lot :
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
page_size |
string |
"A4" |
Nom du format de page. |
orientation |
string |
"portrait" |
"portrait" ou "landscape". |
margins |
object |
{"top": 10, "bottom": 10, "left": 10, "right": 10} |
Marges en mm. |
grayscale |
boolean |
false |
Sortie en niveaux de gris via Ghostscript. |
Interrogation du statut du lot#
Utilisez l'endpoint de statut du lot pour vérifier la progression et récupérer les URLs de téléchargement.
GET /v1/convert/batch/{batch_id}
X-API-Key: sk_your_private_key
Remplacez {batch_id} par le batch_id renvoyé par la requête initiale.
État en cours de traitement#
Pendant que les conversions sont encore en cours :
{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"total": 3,
"completed": 1,
"failed": 0,
"in_progress": 2,
"output_mode": "individual",
"zip_download_url": null,
"items": [
{
"source_url": "https://example.com/page-1",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 184320,
"duration": "3.12"
},
{
"source_url": "https://example.com/page-2",
"status": "In Progress",
"download_url": null,
"output_file_size": null,
"duration": null
},
{
"source_url": "https://example.com/page-3",
"status": "In Progress",
"download_url": null,
"output_file_size": null,
"duration": null
}
]
}
État terminé#
Lorsque toutes les URLs ont été converties avec succès :
{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"total": 3,
"completed": 3,
"failed": 0,
"in_progress": 0,
"output_mode": "individual",
"zip_download_url": null,
"items": [
{
"source_url": "https://example.com/page-1",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 184320,
"duration": "3.12"
},
{
"source_url": "https://example.com/page-2",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 210944,
"duration": "4.55"
},
{
"source_url": "https://example.com/page-3",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 97280,
"duration": "2.87"
}
]
}
État partiel#
Lorsque toutes les URLs sont terminées mais que certaines ont échoué :
{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "partial",
"total": 3,
"completed": 2,
"failed": 1,
"in_progress": 0,
"output_mode": "individual",
"zip_download_url": null,
"items": [
{
"source_url": "https://example.com/page-1",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 184320,
"duration": "3.12"
},
{
"source_url": "https://example.com/page-2",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 210944,
"duration": "4.55"
},
{
"source_url": "https://invalid-url.example",
"status": "Failed",
"download_url": null,
"output_file_size": null,
"duration": "0.87"
}
]
}
Mode ZIP terminé#
En mode ZIP, une seule zip_download_url est fournie pour l'archive entière :
{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"total": 3,
"completed": 3,
"failed": 0,
"in_progress": 0,
"output_mode": "zip",
"zip_download_url": "https://spaces.example.com/...",
"items": [
{
"source_url": "https://example.com/page-1",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 184320,
"duration": "3.12"
},
{
"source_url": "https://example.com/page-2",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 210944,
"duration": "4.55"
},
{
"source_url": "https://example.com/page-3",
"status": "Success",
"download_url": "https://spaces.example.com/...",
"output_file_size": 97280,
"duration": "2.87"
}
]
}
Valeurs de statut du lot#
| Statut | Signification |
|---|---|
processing |
Au moins une URL est encore en cours de conversion. |
completed |
Toutes les URLs ont été converties avec succès. |
partial |
Toutes les URLs sont terminées, mais certaines ont échoué. |
failed |
Toutes les URLs ont échoué. |
Callbacks webhook#
Fournissez un callback_url dans la requête pour recevoir une notification POST automatique à la fin du traitement. Le webhook est envoyé avec Content-Type: application/json et un timeout de 30 secondes. Aucune nouvelle tentative n'est effectuée en cas d'échec de la livraison.
Callback en mode individuel#
En mode individuel, un POST webhook distinct est envoyé pour chaque URL à mesure qu'elle se termine :
{
"job_id": "12345",
"status": "success",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"gcs_uri": "env/files/{project_id}/url-to-pdf/page1_20260405_123456789.pdf",
"filename": "page1_20260405_123456789.pdf",
"file_size": 184320
}
Callback en mode ZIP#
En mode ZIP, un seul POST webhook est envoyé lorsque le lot entier est terminé :
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "success",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"gcs_uri": "env/files/{project_id}/url-to-pdf/batch_20260405_123456789.zip",
"filename": "batch_20260405_123456789.zip",
"file_size": 456789,
"total_tasks": 3,
"successful_tasks": 2,
"failed_tasks": 1,
"tasks": [
{"url": "https://example.com/page-1", "status": "success", "filename": "page1.pdf"},
{"url": "https://example.com/page-2", "status": "success", "filename": "page2.pdf"},
{"url": "https://invalid.example", "status": "failed", "error": "Page load timeout"}
]
}
Notifications par email#
Un email de fin de traitement est envoyé à notification_email lorsque le lot se termine. Si aucun notification_email n'est fourni, l'email est envoyé par défaut à l'adresse du propriétaire du projet.
L'email contient :
- Le statut de la tâche (succès/échec) avec une bannière colorée
- L'ID du lot
- Pour les tâches par lot : un tableau listant chaque URL, son statut et le nom du fichier de sortie
- Un lien pour télécharger les résultats depuis le tableau de bord
Restrictions par plan d'abonnement#
| Fonctionnalité | Founding | Indie | Studio | Enterprise |
|---|---|---|---|---|
| Traitement par lot | Non | Oui | Oui | Oui |
| Mode asynchrone | Non | Oui | Oui | Oui |
| Regroupement en sortie ZIP | Non | Non | Oui | Oui |
| Callbacks webhook | Non | Non | Oui | Oui |
| HTTP Basic Auth / Cookies / Headers | Non | Oui | Oui | Oui |
| Limite de taille du lot | 0 | Selon le plan | Selon le plan | Illimité |
| Conversions mensuelles | 100 | Selon le plan | Selon le plan | Illimité |
Exemples de code#
Python -- Mode individuel avec interrogation (polling)#
import requests
import time
# Submit batch
response = requests.post(
"https://api.enconvert.com/v1/convert/url-to-pdf",
headers={"X-API-Key": "sk_your_private_key"},
json={
"url": [
"https://example.com/page-1",
"https://example.com/page-2",
"https://example.com/page-3"
]
}
)
data = response.json()
batch_id = data["batch_id"]
print(f"Batch started: {batch_id} ({data['url_count']} URLs)")
# Poll for completion
while True:
status = requests.get(
f"https://api.enconvert.com/v1/convert/batch/{batch_id}",
headers={"X-API-Key": "sk_your_private_key"}
).json()
print(f"Status: {status['status']} ({status['completed']}/{status['total']})")
if status["status"] in ("completed", "partial", "failed"):
for item in status["items"]:
if item["download_url"]:
print(f" {item['source_url']} -> {item['download_url']}")
break
time.sleep(5)
Python -- Mode ZIP avec webhook#
import requests
response = requests.post(
"https://api.enconvert.com/v1/convert/url-to-pdf",
headers={"X-API-Key": "sk_your_private_key"},
json={
"url": [
"https://example.com/page-1",
"https://example.com/page-2",
"https://example.com/page-3"
],
"output_format": True,
"output_filename": "monthly-reports",
"callback_url": "https://your-server.com/webhook/enconvert",
"pdf_options": {
"page_size": "A4",
"orientation": "portrait"
}
}
)
data = response.json()
print(f"Batch started: {data['batch_id']}")
print(f"URLs: {data['url_count']}, Format: {data['output_format']}")
# Results will be delivered to your webhook URL
Node.js -- Captures d'écran par lot#
const response = await fetch("https://api.enconvert.com/v1/convert/url-to-screenshot", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "sk_your_private_key"
},
body: JSON.stringify({
url: [
"https://example.com/page-1",
"https://example.com/page-2",
"https://example.com/page-3"
],
output_format: true,
output_filename: "screenshots-bundle"
})
});
const data = await response.json();
console.log(`Batch ${data.batch_id}: ${data.url_count} screenshots queued`);
Réponses d'erreur#
| Statut | Condition |
|---|---|
400 Bad Request |
url est vide ou manquant |
400 Bad Request |
output_format=true avec une seule URL (plusieurs URLs requises) |
400 Bad Request |
direct_download=true avec plusieurs URLs (non pris en charge) |
400 Bad Request |
direct_download=true avec async_mode=true |
400 Bad Request |
Clé publique tentant d'utiliser plusieurs URLs |
402 Payment Required |
Le lot dépasserait le quota mensuel d'ops restant |
402 Payment Required |
Limite de stockage atteinte |
403 Forbidden |
Traitement asynchrone non disponible sur le plan actuel |
403 Forbidden |
Traitement par lot non disponible (limite de lot à 0) |
403 Forbidden |
La taille du lot dépasse la limite de lot du plan |
403 Forbidden |
Sortie ZIP non disponible sur le plan actuel |
403 Forbidden |
Callbacks webhook non disponibles sur le plan actuel |
404 Not Found |
Lot introuvable (mauvais batch_id ou mauvais projet) |
Limites#
| Limite | Valeur |
|---|---|
| Taille du lot | Dépend du plan (Founding : désactivé) |
| Conversions mensuelles | Dépend du plan (le lot entier est vérifié au préalable) |
| Timeout de livraison du webhook | 30 secondes (sans nouvelle tentative) |
| Nombre maximum de cookies par requête | 50 |
| Nombre maximum d'en-têtes personnalisés par requête | 20 |
| Conservation des fichiers | Dépend du plan |
Questions fréquentes#
Comment convertir plusieurs URLs en PDF en une seule requête API ?#
Envoyez un POST à /v1/convert/url-to-pdf avec un tableau d'URLs dans le paramètre url, authentifié avec une clé API privée (sk_...). L'API répond avec HTTP 202 et un batch_id, et chaque URL est convertie en arrière-plan.
Puis-je obtenir tous les résultats de conversion par lot dans un seul fichier ZIP ?#
Oui. Définissez output_format sur true pour regrouper tous les résultats réussis dans une archive ZIP nommée {output_filename}_{timestamp}.zip (ou batch_{timestamp}.zip si aucun nom personnalisé n'est fourni). La sortie ZIP nécessite un plan avec accès à la sortie ZIP (Studio, Production ou Enterprise) et plusieurs URLs dans la requête.
Comment vérifier le statut d'une tâche de conversion par lot ?#
Interrogez GET /v1/convert/batch/{batch_id} avec votre clé API privée. La réponse indique processing, completed, partial ou failed, ainsi que des éléments par URL contenant download_url, output_file_size et duration.
Pourquoi ma requête par lot renvoie-t-elle 403 Forbidden ?#
Une réponse 403 Forbidden signifie qu'une restriction de plan a été atteinte : le traitement asynchrone n'est pas disponible sur votre plan, le traitement par lot est désactivé (limite de lot à 0), la taille du lot dépasse la limite de votre plan, ou une fonctionnalité restreinte comme la sortie ZIP ou les callbacks webhook n'est pas incluse dans votre plan.
Puis-je utiliser le traitement par lot avec une clé API publique ?#
Non. Le traitement par lot nécessite une clé API privée (sk_...). Les clés publiques sont limitées aux requêtes synchrones à URL unique, et l'envoi de plusieurs URLs avec une clé publique renvoie 400 Bad Request.