SDK Java de conversion de fichiers#
com.enconvert:enconvert-sdk est le client Java officiel de l'API EnConvert. Une seule dépendance Maven ou Gradle vous donne la conversion de fichiers (URL vers PDF, DOCX vers PDF, HEIC vers WebP, n'importe quoi vers Markdown) ainsi que la surface de web intelligence V2 : perceive, discover, lookup, distill, ingest et watch. Il cible Java 17 et versions ultérieures, s'appuie sur le java.net.http.HttpClient intégré au JDK, et n'embarque que Gson comme dépendance tierce. Chaque appel est une méthode bloquante ordinaire qui renvoie un record typé, et les conversions longues récupèrent de façon transparente les timeouts du reverse proxy en interrogeant le statut du job.
com.enconvert:enconvert-sdk:0.0.1 · Source : conversionapi/java-sdk · Java : 17+ · Dépendances : Gson uniquement
Installation#
// build.gradle
dependencies {
implementation 'com.enconvert:enconvert-sdk:0.0.1'
}
// build.gradle.kts
dependencies {
implementation("com.enconvert:enconvert-sdk:0.0.1")
}
<!-- pom.xml -->
<dependency>
<groupId>com.enconvert</groupId>
<artifactId>enconvert-sdk</artifactId>
<version>0.0.1</version>
</dependency>
Le HTTP est pris en charge par java.net.http.HttpClient, fourni par le JDK. Le seul artefact tiers embarqué est Gson pour le JSON, déclaré en dépendance api afin d'être visible sur votre classpath de compilation.
Démarrage rapide#
import com.enconvert.Enconvert;
import com.enconvert.model.ConversionResult;
import com.enconvert.model.UrlToPdfOptions;
import com.enconvert.model.v2.PerceiveOptions;
import com.enconvert.model.v2.PerceiveResult;
import java.util.List;
Enconvert client = new Enconvert(System.getenv("ENCONVERT_API_KEY"));
ConversionResult pdf = client.convertUrlToPdf("https://example.com",
UrlToPdfOptions.builder().saveTo("page.pdf").build());
System.out.println(pdf.presignedUrl());
// Lire une page comme votre agent devrait le faire, avec un score de qualité attaché.
PerceiveResult page = client.v2.perceive("https://example.com",
PerceiveOptions.builder().outputs(List.of("markdown", "structured")).build());
System.out.println(page.outputs().get("markdown").url());
System.out.println(page.renderQuality()); // par ex. 0.93
Chaque classe d'options est un builder immuable et chaque réponse est un record Java : les accesseurs se lisent donc comme pdf.presignedUrl() et page.renderQuality(). Le client détient un seul HttpClient partagé et aucun état mutable par requête, si bien qu'une instance unique peut servir de singleton ou de bean Spring partagé entre plusieurs threads. Les extraits ci-dessous omettent les imports : les types d'options et de réponses vivent dans com.enconvert.model (conversion) et com.enconvert.model.v2 (web intelligence), les exceptions dans com.enconvert.exceptions.
Ce que le client expose#
Enconvert porte directement la surface de conversion. La surface de web intelligence vit sur le champ public final client.v2, une instance de EnconvertV2.
| Groupe | Méthodes | Renvoie |
|---|---|---|
| URL unique | convertUrlToPdf, convertUrlToScreenshot, convertUrlToMarkdown |
ConversionResult |
| Envoi de fichier | convertImage, convertDocument, convertToMarkdown, convertToPdf |
ConversionResult |
| Site entier | convertWebsiteToPdf, convertWebsiteToScreenshot |
BatchSubmission |
| Statut | getJobStatus, getBatchStatus, waitForBatch |
JobStatus, BatchStatus |
v2 perceive |
perceive, perceiveDirect, getPerceiveOperation, perceiveBatch, getPerceiveBatch, downloadPerceiveArtifact |
PerceiveResult, PerceiveDirectResult, PerceiveBatchResult |
v2 discover |
discover |
DiscoverResult |
v2 lookup |
lookup |
LookupResult |
v2 distill |
distill |
DistillResult |
v2 ingest |
ingest, ingestFiles, getIngestJob, listIngestJobs, cancelIngestJob, retryIngestWebhook, getWebhookSecret, rotateWebhookSecret |
IngestJob, IngestJobList, WebhookRetryResult, WebhookSecret |
v2 watch |
createWatcher, getWatcher, listWatchers, getWatcherSnapshots, updateWatcher, deleteWatcher |
Watcher, WatcherList, WatcherSnapshotList |
La plupart des méthodes possèdent une surcharge courte sans argument d'options : client.v2.perceive(url) et client.convertUrlToPdf(url) compilent donc tous les deux. convertImage, distill et ingest font exception : chacune exige toujours son objet d'options, parce que le format cible, le schéma et la source sont respectivement obligatoires.
Conversion de fichiers#
Les endpoints de conversion couvrent 43 paires {input}-to-{output} implémentées, deux endpoints à détection automatique (anything-to-markdown et anything-to-pdf), et les endpoints de rendu navigateur. La référence complète des paramètres se trouve dans Paramètres et options.
convertUrlToPdf#
Rend n'importe quelle URL publique en PDF.
ConversionResult result = client.convertUrlToPdf("https://example.com",
UrlToPdfOptions.builder()
.pdfOptions(PdfOptions.builder().pageSize("A4").orientation("landscape").build())
.singlePage(false)
.viewportWidth(1440)
.saveTo("report.pdf")
.build());
| Option | Type | Par défaut | Description |
|---|---|---|---|
saveTo |
String |
aucun | Chemin local où écrire le PDF. Les répertoires parents sont créés pour vous. |
singlePage |
boolean |
true |
true produit une seule page continue. false pagine en utilisant pdfOptions.pageSize. |
pdfOptions |
PdfOptions |
aucun | Taille de page, orientation, marges, échelle, niveaux de gris, en-tête, pied de page. Voir Options PDF. |
viewportWidth |
int |
1920 |
Largeur de la fenêtre d'affichage du navigateur, en pixels. |
viewportHeight |
int |
1080 |
Hauteur de la fenêtre d'affichage du navigateur, en pixels. |
loadMedia, enableScroll |
boolean |
true |
Attend les images et les vidéos avant la capture, et fait défiler la page de haut en bas pour déclencher les chargements différés. |
outputFilename |
String |
auto | Remplace le nom de fichier généré. |
auth, cookies, headers |
HttpBasicAuth, List<BrowserCookie>, Map<String, String> |
aucun | Identifiants, cookies injectés et en-têtes de requête supplémentaires pour les pages derrière une authentification. |
convertUrlToScreenshot#
Capture un PNG de n'importe quelle URL. Mêmes options de fenêtre d'affichage, de médias, de défilement, de nom de fichier, d'authentification, de cookies et d'en-têtes que convertUrlToPdf, à l'exception de singlePage et pdfOptions.
client.convertUrlToScreenshot("https://example.com",
UrlToScreenshotOptions.builder().viewportWidth(1440).saveTo("screenshot.png").build());
convertUrlToMarkdown#
Extrait du Markdown GitHub-Flavored propre à partir d'une URL. La navigation, les pieds de page, les publicités et les scripts sont supprimés, le corps principal de l'article est conservé, et un frontmatter YAML (title, description, url, links, images) est ajouté en tête. Même jeu d'options que convertUrlToScreenshot.
client.convertUrlToMarkdown("https://example.com/article",
UrlToMarkdownOptions.builder().saveTo("article.md").build());
convertImage#
Convertit entre jpeg, png, svg, heic et webp, ou rastérise un PDF en JPEG.
// Depuis un chemin sur le disque
client.convertImage(Path.of("photo.heic"),
ConvertImageOptions.builder("webp").saveTo("photo.webp").build());
// Rastériser un PDF
client.convertImage(Path.of("scan.pdf"),
ConvertImageOptions.builder("jpeg").saveTo("scan.jpeg").build());
// Depuis des octets en mémoire, avec un nom de fichier explicite
byte[] bytes = Files.readAllBytes(Path.of("photo.heic"));
client.convertImage(new FileInput(bytes, "photo.heic"),
ConvertImageOptions.builder("webp").build());
Trois surcharges d'entrée existent sur chaque méthode de fichier : java.nio.file.Path (lecture depuis le disque), byte[] brut (le nom de fichier vaut alors upload.bin), et com.enconvert.FileInput lorsque vous devez associer des octets en mémoire à un vrai nom de fichier. Le format d'entrée est déduit de l'extension ; le format de sortie est obligatoire.
| Option | Type | Requis | Description |
|---|---|---|---|
outputFormat |
String |
Oui | Passé à ConvertImageOptions.builder(outputFormat). Une valeur parmi jpeg, png, svg, heic, webp. Les alias comme jpg sont normalisés. |
saveTo |
String |
non | Chemin local où écrire le résultat. |
outputFilename |
String |
non | Remplace le nom de fichier généré. |
convertDocument#
Convertit des documents et des formats de données structurées. Le format de sortie vaut pdf par défaut.
// docx vers pdf
client.convertDocument(Path.of("report.docx"),
ConvertDocumentOptions.builder().saveTo("report.pdf").build());
// json vers yaml
client.convertDocument(Path.of("data.json"),
ConvertDocumentOptions.builder().outputFormat("yaml").saveTo("data.yaml").build());
// markdown vers pdf avec mise en page
client.convertDocument(Path.of("README.md"),
ConvertDocumentOptions.builder()
.outputFormat("pdf")
.pdfOptions(PdfOptions.builder()
.pageSize("A4")
.margins(new PdfMargins(20.0, 20.0, 25.0, 25.0))
.build())
.saveTo("readme.pdf")
.build());
Extensions d'entrée reconnues : .doc, .docx, .xls, .xlsx, .ppt, .pptx, .html, .htm, .odt, .ods, .odp, .ots, .pages, .numbers, .md, .markdown, .csv, .json, .xml, .yaml, .yml, .toml.
L'EPUB n'a pas de paire de conversion documentaire dédiée. Faites plutôt passer les fichiers .epub par convertToPdf ou convertToMarkdown.
| Option | Type | Par défaut | Description |
|---|---|---|---|
outputFormat |
String |
"pdf" |
Format cible. |
saveTo |
String |
aucun | Chemin local où écrire le résultat. |
outputFilename |
String |
aucun | Remplace le nom de fichier généré. |
pdfOptions |
PdfOptions |
aucun | Mise en page, prise en compte lorsque la sortie est un PDF. |
Conversions prises en charge#
convertImage et convertDocument valident la paire {input}-to-{output} contre les endpoints que l'API implémente réellement. Une paire non prise en charge lève immédiatement une IllegalArgumentException en listant les sorties valides pour cette entrée, plutôt que de payer un aller-retour réseau pour une requête vouée à l'échec.
| Entrée | Sorties |
|---|---|
json |
csv, toml, xml, yaml |
xml |
csv, json |
yaml |
json |
csv |
json, xml |
toml |
json |
markdown |
html, pdf |
html |
pdf |
doc, excel, ppt, odt, ods, odp, ots, pages, numbers |
pdf |
jpeg, png, svg, heic, webp |
les uns vers les autres, les 20 paires |
pdf |
jpeg |
Le même tableau est interrogeable à l'exécution via com.enconvert.Formats : Formats.validOutputsFor("json") renvoie [csv, toml, xml, yaml], Formats.validOutputsFor("pdf") renvoie [jpeg], et Formats.IMPLEMENTED_CONVERSIONS contient les 43 noms d'endpoints.
convertToMarkdown#
Envoyez n'importe quel document pris en charge vers un endpoint à détection automatique et récupérez du Markdown propre. La hiérarchie des titres survit à la conversion, ce qui en fait une première étape naturelle pour un pipeline RAG.
client.convertToMarkdown(Path.of("handbook.docx"),
ConvertToMarkdownOptions.builder().saveTo("handbook.md").build());
Accepte les formats PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT et MD, ainsi que les formats bureautiques hérités et ODF. Le format est détecté côté serveur, il n'y a donc aucune vérification d'extension côté client : tout fichier est envoyé tel quel. Les images ne sont pas prises en charge et sont rejetées avec un 400. Les seules options sont saveTo et outputFilename.
convertToPdf#
L'autre endpoint à détection automatique : presque n'importe quoi vers PDF.
// pptx vers pdf
client.convertToPdf(Path.of("slides.pptx"),
ConvertToPdfOptions.builder().saveTo("slides.pdf").build());
// pdf transmis tel quel, converti en niveaux de gris
client.convertToPdf(Path.of("scan.pdf"),
ConvertToPdfOptions.builder()
.pdfOptions(PdfOptions.builder().grayscale(true).build())
.saveTo("scan-gray.pdf")
.build());
Accepte les formats bureautiques, ODF, Pages, Numbers, RTF, CSV, HTML, Markdown, texte brut, images matricielles, SVG, EPUB, ainsi qu'un PDF existant transmis tel quel. L'EPUB est traité ici parce qu'il n'a pas de paire de conversion documentaire dédiée. Les options sont saveTo, outputFilename et pdfOptions.
grayscale est pris en compte sur cet endpoint. La géométrie de page (taille de page, largeur et hauteur, orientation, marges, échelle, en-tête, pied de page) est ignorée par anything-to-pdf. Lorsque vous avez besoin d'une mise en page complète, passez plutôt par convertDocument ou convertUrlToPdf.
Conversion d'un site entier#
convertWebsiteToPdf et convertWebsiteToScreenshot découvrent chaque page d'un site, convertissent chacune d'elles en arrière-plan, et regroupent les résultats dans une seule archive ZIP. Les deux sont asynchrones et renvoient un BatchSubmission. Les deux exigent une clé API privée.
BatchSubmission batch = client.convertWebsiteToPdf("https://example.com",
WebsiteToPdfOptions.builder()
.crawlMode("sitemap") // "auto" (par défaut), "sitemap", "full"
.excludePatterns(List.of("/blog/tag/")) // mode full crawl uniquement
.notificationEmail("[email protected]")
.build());
System.out.println(batch.batchId() + " " + batch.urlCount() + " " + batch.discoveryMethod());
// Bloque jusqu'à ce que le lot quitte l'état "processing", puis enregistre le ZIP
BatchStatus status = client.waitForBatch(batch.batchId(),
WaitForBatchOptions.builder().saveTo("site.zip").build());
System.out.println(status.completed() + " of " + status.total() + " pages converted");
convertWebsiteToScreenshot fonctionne à l'identique et produit un ZIP de PNG. waitForBatch interroge toutes les 5 secondes par défaut, abandonne au bout de 30 minutes, et accepte intervalMs, timeoutMs et saveTo. En cas de timeout, elle lève une ApiException avec le statut 504.
Interroger le statut vous-même#
JobStatus job = client.getJobStatus("job_abc123");
if ("success".equals(job.status())) System.out.println(job.presignedUrl());
if ("failed".equals(job.status())) System.err.println(job.error());
BatchStatus batch = client.getBatchStatus("bat_abc123");
if (!"processing".equals(batch.status())) System.out.println(batch.zipDownloadUrl());
Web intelligence (V2)#
Tout ce qui se trouve sous client.v2 transforme des pages web en données prêtes pour un agent. Chaque lecture porte renderQuality, un score de 0.0 à 1.0 qui indique à quel point la page s'est réellement rendue proprement. Une page de challenge, un mur de cookies ou une coquille SPA vide reviennent avec un score bas et des warnings() et deductions() renseignés, au lieu d'être présentés comme du vrai contenu : une mauvaise lecture n'entre donc jamais silencieusement dans le contexte de votre agent. Le contenu est toujours renvoyé, il est simplement signalé. Le modèle est présenté en détail dans la vue d'ensemble V2.
Perceive#
Rend une URL vers les artefacts que vous demandez. Référence de l'endpoint : Perceive.
PerceiveResult page = client.v2.perceive("https://example.com",
PerceiveOptions.builder()
.outputs(List.of("markdown", "screenshot", "structured"))
.extract(List.of("tables", "metadata"))
.waitFor("css:main")
.build());
System.out.println(page.renderQuality()); // de 0.0 à 1.0
System.out.println(page.statusCode() + " " + page.deductions()); // par ex. 200 {http_error=0.7}
System.out.println(page.outputs().get("markdown").url()); // URL signée, 15 minutes
System.out.println(page.structured()); // forme définie par l'appelant
| Option | Type | Par défaut | Description |
|---|---|---|---|
outputs |
List<String> |
["markdown", "structured"] |
Une valeur parmi markdown, html_cleaned, html_raw, screenshot, screenshot_full_page, pdf, links, images, structured. |
extract |
List<String> |
aucun | Cibles heuristiques : tables, prices, contacts, metadata, main_content, headings, structured_data, technologies, all. |
schema |
Map<String, Object> |
aucun | Schéma JSON pour l'extraction structurée. |
waitFor, waitTimeoutMs |
String, int |
aucun, 30000 |
Un sélecteur CSS, éventuellement préfixé par css:, ou js:<expr> à attendre, avec un budget de 0 à 60000 ms. |
jsCode |
String |
aucun | JavaScript exécuté après la navigation, 20000 caractères maximum. |
viewport, mobile |
PerceiveViewport, boolean |
1920 x 1080, false |
Largeur de 320 à 3840, hauteur de 240 à 2160, ou émulation mobile. |
onlyMainContent |
boolean |
true |
Supprime la navigation, l'en-tête, le pied de page et les bandeaux cookies de l'artefact Markdown et de l'extrait main_content. |
cacheMode |
String |
"enabled" |
enabled réutilise un cache d'une heure, bypass le contourne, refresh force un nouveau rendu. |
blockResources |
List<String> |
aucun | Types de ressources que le navigateur ne doit pas charger, par exemple image, font, script. |
pdfOptions |
PdfOptions |
aucun | Utile uniquement lorsque outputs contient pdf. |
headers, cookies, auth |
Map, List<BrowserCookie>, HttpBasicAuth |
aucun | En-têtes de requête, cookies injectés, identifiants HTTP Basic. |
respectRobots |
boolean |
aucun | Respecte les règles robots du site. |
proxyUrl, geolocation et actionChain existent sur le builder mais ne sont pas disponibles côté serveur et sont pour l'instant rejetés avec un 422.
Les URL d'artefacts sont signées pour 15 minutes et resignées à chaque lecture de l'opération : client.v2.getPerceiveOperation(page.operationId()) vous rend donc des liens frais. Traitez jusqu'à 1000 URL par lot avec un seul bloc d'options partagé : les petits lots se terminent en ligne, les plus gros reviennent avec le statut queued, il faut donc les interroger.
PerceiveBatchResult batch = client.v2.perceiveBatch(
List.of("https://a.example.com", "https://b.example.com"),
PerceiveBatchOptions.builder()
.outputs(List.of("markdown"))
.outputMode("zip") // "manifest" (par défaut) ou "zip"
.build());
PerceiveBatchResult done = client.v2.getPerceiveBatch(batch.jobId());
System.out.println(done.completed() + "/" + done.total());
Évitez complètement l'aller-retour par URL signée avec perceiveDirect, qui renvoie directement les octets de l'artefact. Cette méthode exige exactement une sortie produisant un artefact (n'importe laquelle sauf structured) et lève une IllegalArgumentException avant l'envoi si vous en demandez plus ou moins :
PerceiveDirectResult direct = client.v2.perceiveDirect("https://example.com",
PerceiveOptions.builder().outputs(List.of("pdf")).build());
Files.write(Path.of(direct.filename()), direct.content());
System.out.println(direct.renderQuality() + " " + direct.contentType());
// Retélécharger un artefact stocké d'une opération antérieure
PerceiveDirectResult stored = client.v2.downloadPerceiveArtifact(page.operationId(), "markdown");
downloadPerceiveArtifact accepte un nom de sortie null ou omis lorsque l'opération n'a produit qu'un seul artefact ; sinon elle renvoie un 400 listant les sorties disponibles. Une fois l'artefact stocké arrivé au bout de sa rétention, elle renvoie un 410.
Discover#
Énumère les URL d'un site sans rien rendre. Aucun navigateur n'intervient, c'est donc rapide. Référence de l'endpoint : Discover.
DiscoverResult found = client.v2.discover("https://example.com",
DiscoverOptions.builder()
.mode("hybrid") // "sitemap", "crawl", "hybrid"
.maxUrls(200)
.maxDepth(3)
.excludePatterns(List.of("/tag/"))
.build());
System.out.println(found.total() + " urls, truncated=" + found.truncated());
found.urls().forEach(System.out::println);
| Option | Type | Par défaut | Plage |
|---|---|---|---|
mode |
String |
"hybrid" |
sitemap, crawl, hybrid |
maxUrls |
int |
100 |
de 1 à 1000 |
maxDepth |
int |
2 |
de 1 à 5 |
includePatterns, excludePatterns |
List<String> |
aucun | Liste blanche et liste noire d'expressions régulières, 50 entrées maximum chacune. La liste noire est appliquée en second. |
sameDomainOnly, respectRobots |
boolean |
true, aucun |
Rester sur le domaine de départ, et respecter les règles robots du site. |
Lookup#
Recherche web catégorisée, avec rendu automatique facultatif des meilleurs résultats. Référence de l'endpoint : Lookup.
LookupResult search = client.v2.lookup("best static site generators",
LookupOptions.builder()
.category("web") // web, news, images, scholar, patents, maps
.numResults(10)
.country("us")
.timeFilter("month") // hour, day, week, month, year
.perceiveTop(3) // rend automatiquement les 3 premiers résultats
.build());
search.results().forEach(hit -> {
System.out.println(hit.position() + " " + hit.title() + " " + hit.url());
if (hit.perceive() != null) System.out.println(" quality " + hit.perceive().renderQuality());
});
Avec perceiveTop supérieur à 0 (de 0 à 10, 0 par défaut), les N premières URL de résultats sont rendues via perceive et chaque résultat porte son PerceiveResult complet en ligne sur hit.perceive(). numResults va de 1 à 100 et vaut 10 par défaut ; page va de 1 à 10.
Distill#
Extraction structurée pilotée par schéma, sur une ou plusieurs pages. Référence de l'endpoint : Distill.
DistillResult extraction = client.v2.distill(
DistillOptions.builder(Map.of("products", "list of product names with their listed price"))
.urls(List.of("https://example.com/catalog"))
.cssSchema(CssSchema.builder(".product-card", List.of(
CssField.builder("name", "text").selector("h3").build(),
CssField.builder("price", "text").selector(".price").build()))
.targetField("products")
.build())
.build());
extraction.results().forEach(item ->
System.out.println(item.data() + " via " + item.extractionTier()));
Le cssSchema facultatif exécute d'abord une passe CSS gratuite ; seuls les champs auxquels elle ne peut pas répondre escaladent vers le niveau LLM, et item.extractionTier() indique quel chemin a produit l'enregistrement (css, llm, mixed ou none). Vous pouvez aussi découvrir les URL au préalable au lieu de les lister :
client.v2.distill(
DistillOptions.builder(Map.of("title", "page title", "summary", "one-line summary"))
.discoverFrom(new DistillDiscoverFrom("https://example.com", "sitemap", 10))
.build());
Exactement l'un de urls (50 maximum) et discoverFrom doit être défini, et schema est exigé par la fabrique du builder. Les deux règles sont vérifiées côté client et lèvent une IllegalArgumentException avant qu'aucune requête ne parte.
Ingest#
Transforme un site entier, ou un ensemble de documents envoyés, en JSONL découpé et prêt pour le RAG, à travers un seul pipeline. Ingest est toujours asynchrone. Référence de l'endpoint : Ingest.
// Depuis un site
IngestJob job = client.v2.ingest(IngestOptions.builder()
.mode("sitemap") // "urls" (par défaut), "sitemap", "crawl"
.url("https://docs.example.com")
.maxPages(100)
.chunk(new IngestChunkOptions(512, 1)) // maxWords, sentenceOverlap
.webhookUrl("https://my.app/hooks/enconvert")
.build());
// Ou depuis des fichiers envoyés
IngestJob fileJob = client.v2.ingestFiles(
List.of(new FileInput(Files.readAllBytes(Path.of("handbook.pdf")), "handbook.pdf"),
new FileInput(Files.readAllBytes(Path.of("notes.docx")), "notes.docx")),
IngestFilesOptions.builder().chunk(new IngestChunkOptions(512, 1)).build());
// Interroger jusqu'à obtenir le JSONL
IngestJob status = client.v2.getIngestJob(job.jobId());
if ("completed".equals(status.status())) {
System.out.println(status.outputUrl() + " (" + status.totalChunks() + " chunks)");
}
client.v2.listIngestJobs(V2ListOptions.builder().limit(20).build());
client.v2.cancelIngestJob(job.jobId()); // idempotent
ingestFiles accepte les formats PDF, DOCX, PPTX, XLSX, CSV, HTML, EPUB, TXT et MD, ainsi que les formats bureautiques hérités et ODF. Le découpage vaut par défaut 512 mots (de 32 à 4000) avec 1 phrase de chevauchement (de 0 à 10). mode vaut urls par défaut, ce qui exige une liste urls non vide et interdit url ; tous les autres modes exigent une url de départ et interdisent urls. Le SDK vérifie cet appariement avant l'envoi.
Les webhooks de fin sont signés en HMAC. Récupérez le secret et les noms d'en-têtes dont vous avez besoin pour vérifier une livraison, faites-le tourner en cas de fuite, et relancez une livraison que votre endpoint aurait manquée :
WebhookSecret secret = client.v2.getWebhookSecret();
System.out.println(secret.signatureHeader() + " " + secret.signatureScheme());
client.v2.rotateWebhookSecret(); // les anciennes signatures cessent aussitôt d'être valides
WebhookRetryResult retry = client.v2.retryIngestWebhook(job.jobId());
System.out.println(retry.delivered() + " after " + retry.attempts() + " attempts");
Watch#
Surveillance récurrente des changements sur une URL, avec notification par e-mail et par webhook. Référence de l'endpoint : Watch.
Watcher watcher = client.v2.createWatcher("https://example.com/pricing",
WatchCreateOptions.builder()
.frequencyMinutes(60) // de 60 à 43200, plancher horaire
.diffMode("auto") // auto, text, structured, tables, metadata
.webhookUrl("https://my.app/hooks/changes")
.notifyEmail(true)
.build());
WatcherSnapshotList history = client.v2.getWatcherSnapshots(watcher.watcherId(),
SnapshotListOptions.builder().limit(10).build());
history.snapshots().forEach(s ->
System.out.println(s.checkedAt() + " changed=" + s.hasChanges()
+ " similarity=" + s.similarity()));
client.v2.updateWatcher(watcher.watcherId(), WatcherUpdate.builder().status("paused").build());
client.v2.updateWatcher(watcher.watcherId(), WatcherUpdate.builder().webhookUrl("").build());
client.v2.deleteWatcher(watcher.watcherId()); // suppression logique, idempotente
listWatchers() et getWatcher(watcherId) permettent de les relire. updateWatcher exige au moins un champ et lève sinon une IllegalArgumentException. Une chaîne vide explicite pour webhookUrl efface le webhook, tandis que la laisser à null signifie « aucun changement ». deleteWatcher est une suppression logique : elle renvoie le watcher marqué avec le statut deleted, et un watcher supprimé se relit ensuite en 404.
WatcherSnapshot.changes() est du texte brut repris de la page surveillée. Échappez-le avant de l'afficher dans un tableau de bord, un e-mail ou un message de chat.
Options PDF#
PdfOptions est partagé par convertUrlToPdf, convertWebsiteToPdf, convertDocument, convertToPdf et PerceiveOptions.pdfOptions.
client.convertUrlToPdf("https://internal.example.com/report",
UrlToPdfOptions.builder()
.pdfOptions(PdfOptions.builder()
.pageSize("A4")
.orientation("landscape")
.margins(new PdfMargins(10.0, 10.0, 15.0, 15.0))
.scale(0.9)
.header(new PdfHeaderFooter("Quarterly Report", 15.0))
.footer(new PdfHeaderFooter("Confidential", 12.0))
.build())
.auth(new HttpBasicAuth("user", "pass"))
.cookies(List.of(BrowserCookie.builder("session", "abc123").domain("internal.example.com").build()))
.headers(Map.of("X-Tenant", "acme"))
.saveTo("report.pdf")
.build());
| Champ | Type | Description |
|---|---|---|
pageSize |
String |
"A4", "A3", "Letter", "Legal", et similaires. |
pageWidth, pageHeight |
double |
Dimensions personnalisées. Définies ensemble, elles remplacent pageSize. |
orientation |
String |
"portrait" ou "landscape". |
margins |
PdfMargins |
Record composé de top, bottom, left, right. Tout champ null est omis. |
scale |
double |
Échelle de rendu, par exemple 0.9 pour 90 pour cent. |
grayscale |
boolean |
Post-traite le PDF en niveaux de gris. |
header, footer |
PdfHeaderFooter |
Record composé de content (2000 caractères maximum) et height. |
BrowserCookie a besoin d'un nom et d'une valeur, plus soit domain, soit url ; lorsque domain est défini sans path, l'API fixe path à / par défaut. Ne combinez pas auth avec un en-tête Authorization explicite, car l'API rejette ce conflit.
Gestion des erreurs#
Chaque exception du SDK hérite d'EnconvertException, qui hérite elle-même de RuntimeException : rien ne vous impose donc une clause throws sur vos sites d'appel. Attrapez d'abord les sous-classes spécifiques.
try {
client.convertUrlToPdf("https://example.com");
} catch (AuthenticationException e) {
System.err.println("Invalid or missing API key");
} catch (QuotaException e) {
System.err.println("Request refused with 402: " + e.getMessage());
} catch (RateLimitException e) {
System.err.println("Too many requests, back off and retry");
} catch (ApiException e) {
System.err.println("API error [" + e.getStatusCode() + "]: " + e.getMessage());
}
| Classe | Déclenchée sur | Code de statut |
|---|---|---|
AuthenticationException |
Clé API manquante, invalide ou non autorisée | 401, 403 |
QuotaException |
HTTP 402 | 402 |
RateLimitException |
Trop de requêtes | 429 |
ApiException |
Toute autre réponse 4xx ou 5xx | le code réel |
EnconvertException |
Classe de base, également levée en cas d'échec de transport, de requête interrompue ou de fichier d'entrée illisible | aucun |
La validation côté client (paire de conversion non prise en charge, schéma distill manquant, mise à jour de watcher vide, mauvais nombre de sorties pour perceiveDirect) lève une IllegalArgumentException avant qu'aucune requête ne soit émise. La table des messages des réponses serveur se trouve dans la référence Codes d'erreur.
Récupération des timeouts#
Les rendus d'URL longs et les conversions de documents volumineux peuvent survivre au timeout du reverse proxy, même quand la conversion finit par réussir. Le SDK gère cela de manière transparente :
- Avant chaque requête d'URL unique ou d'envoi de fichier, le SDK génère un UUID et l'envoie en tant que
job_id. - Si la requête revient en 5xx, le SDK bascule vers le polling de
GET /v1/convert/status/{jobId}toutes les 3 secondes. - Sur
success, il renvoie le résultat. Surfailed, il lève uneApiExceptionportant le message d'erreur du serveur. - Le délai maximal de polling est de 5 minutes. Au-delà, il lève
ApiException(504, "Conversion timed out").
Vous n'avez aucun code à écrire pour cela. Si une réponse réussie omet job_id, le SDK y réinjecte l'identifiant qu'il a généré, si bien que result.jobId() reste toujours utilisable avec getJobStatus.
convertWebsiteToPdf et convertWebsiteToScreenshot n'ont pas de ligne de job à interroger : un 5xx signifie donc que la soumission elle-même a échoué, et l'erreur remonte directement. Les endpoints V2 n'utilisent pas non plus le polling de job ; leurs flux asynchrones passent par getPerceiveBatch et getIngestJob.
Configuration#
Enconvert client = Enconvert.builder(System.getenv("ENCONVERT_API_KEY"))
.baseUrl("https://api.enconvert.com")
.timeout(Duration.ofSeconds(300))
.build();
Trois constructeurs sont disponibles comme raccourcis : new Enconvert(apiKey), new Enconvert(apiKey, baseUrl) et new Enconvert(apiKey, baseUrl, timeout).
| Option | Type | Par défaut | Description |
|---|---|---|---|
apiKey |
String |
obligatoire | Clé API privée. Une valeur null ou vide lève une IllegalArgumentException. |
baseUrl |
String |
https://api.enconvert.com |
URL de base de l'API. Les barres obliques finales sont supprimées. |
timeout |
Duration |
300 secondes | Appliqué à la fois comme timeout de connexion et comme timeout par requête. |
La clé voyage dans l'en-tête X-API-Key. Les URL de téléchargement présignées sont récupérées sans elle, puisqu'elles sont déjà signées. Les types de clés sont traités dans Authentification ; créez et gérez vos clés depuis le tableau de bord.
Structure du résultat#
Chaque conversion de fichier unique et d'URL unique renvoie le même record :
public record ConversionResult(
String presignedUrl,
String objectKey,
String filename,
Long fileSize,
Double conversionTimeSeconds,
String jobId) {}
L'URL présignée est valable un temps limité. Passez saveTo (ou récupérez l'URL vous-même) et stockez les octets dans votre propre bucket si vous voulez qu'ils lui survivent.
Les autres records de réponse que vous manipulerez le plus souvent :
| Record | Accesseurs principaux |
|---|---|
JobStatus |
status() (processing, success, failed), presignedUrl(), objectKey(), error() |
BatchStatus |
status(), total(), completed(), failed(), inProgress(), zipDownloadUrl(), items() |
PerceiveResult |
operationId(), renderQuality(), statusCode(), deductions(), outputs(), structured(), cacheHit(), warnings() |
V2OutputArtifact |
url(), objectKey(), sizeBytes(), contentType(), expiresIn() |
PerceiveDirectResult |
content(), contentType(), filename(), renderQuality(), contentHash() |
IngestJob |
jobId(), status(), pagesProcessed(), totalChunks(), outputUrl(), webhookDelivered() |
Watcher |
watcherId(), status(), frequencyMinutes(), checksCount(), nextCheckAt(), lastChangeAt() |
Les champs dont la forme est définie par votre propre requête (structured, data, trackFields, les changes d'un snapshot) sont exposés en JsonObject Gson et passent sans modification. Les énumérations à valeurs textuelles restent des String plutôt que de devenir des constantes enum Java : une nouvelle valeur de l'API ne casse donc jamais la désérialisation sur une version plus ancienne du SDK. com.enconvert.model.v2.V2Enums contient chaque valeur acceptée sous forme de constante à l'abri des fautes de frappe.
Source et problèmes#
- Maven Central :
com.enconvert:enconvert-sdk:0.0.1 - GitHub : conversionapi/java-sdk
- Licence : MIT
- Autres clients : tous les SDK · référence des endpoints · tarifs
Questions fréquentes#
Comment convertir des fichiers en Java avec une dépendance Maven ?#
Ajoutez com.enconvert:enconvert-sdk:0.0.1 à votre pom.xml ou votre build.gradle, construisez un client avec new Enconvert(System.getenv("ENCONVERT_API_KEY")), et appelez une méthode typée comme convertUrlToPdf, convertImage, convertDocument ou convertToPdf. Passez saveTo sur le builder d'options pour écrire la sortie directement sur le disque au lieu de gérer vous-même l'URL présignée.
Comment convertir une URL en PDF en Java ?#
Appelez client.convertUrlToPdf(url, UrlToPdfOptions.builder().saveTo("page.pdf").build()). Définissez singlePage(false) pour paginer selon pdfOptions.pageSize au lieu de produire une seule page continue, et passez auth, cookies ou headers pour une page derrière une authentification.
Comment convertir un DOCX en PDF en Java ?#
Appelez client.convertDocument(Path.of("report.docx"), ConvertDocumentOptions.builder().saveTo("report.pdf").build()). Le format de sortie vaut pdf par défaut : vous ne définissez donc outputFormat que lorsque vous voulez autre chose, par exemple yaml à partir d'une entrée .json. Pour les formats sans paire dédiée, comme l'EPUB ou le RTF, utilisez convertToPdf.
Comment convertir du HEIC en WebP en Java ?#
Appelez client.convertImage(Path.of("photo.heic"), ConvertImageOptions.builder("webp").saveTo("photo.webp").build()). Le format d'entrée vient de l'extension du fichier et le format de sortie est l'argument obligatoire du builder. jpeg, png, svg, heic et webp se convertissent tous les uns vers les autres, et pdf se rastérise en jpeg. Ce client ne propose pas de méthode de compression sur place.
Comment récupérer une page web en Markdown propre depuis Java ?#
Deux chemins. client.convertUrlToMarkdown(url, ...) renvoie du Markdown GitHub-Flavored avec un frontmatter YAML, sous forme de fichier téléchargeable. client.v2.perceive(url, PerceiveOptions.builder().outputs(List.of("markdown")).build()) renvoie le même contenu sous forme d'artefact prêt pour un agent, avec un score renderQuality, des options d'extraction et un contrôle du cache. Utilisez perceive quand une mauvaise lecture doit être détectable plutôt que silencieuse.
Qu'est-ce que renderQuality et pourquoi chaque lecture en porte-t-il un ?#
renderQuality est un score de 0.0 à 1.0 attaché à chaque rendu V2. Un score élevé signifie que la page s'est rendue proprement ; un score bas signifie que quelque chose s'est interposé, par exemple un challenge anti-bot, un mur de cookies, un écran de connexion, une page d'erreur HTTP ou une coquille SPA vide. Le contenu est tout de même renvoyé, avec warnings() et deductions() renseignés, pour que votre pipeline puisse écarter ou relancer la lecture au lieu d'injecter une page de challenge dans un modèle comme s'il s'agissait de l'article.
Comment transformer un site de documentation en fragments prêts pour le RAG en Java ?#
Appelez client.v2.ingest(IngestOptions.builder().mode("sitemap").url("https://docs.example.com").maxPages(100).chunk(new IngestChunkOptions(512, 1)).build()). Le job est asynchrone : soit vous interrogez getIngestJob(jobId) jusqu'à ce que le statut soit completed puis lisez outputUrl() pour récupérer le JSONL, soit vous définissez webhookUrl et vérifiez la signature HMAC avec le secret renvoyé par getWebhookSecret(). Pour des documents locaux plutôt qu'un site, utilisez ingestFiles.
Comment le SDK gère-t-il les conversions qui dépassent le timeout du proxy ?#
Avant chaque requête d'URL unique ou d'envoi de fichier, il génère un UUID et l'envoie comme job_id. Si la requête renvoie un 5xx, il interroge GET /v1/convert/status/{jobId} toutes les 3 secondes jusqu'à ce que le job signale success ou failed, avec un délai maximal de 5 minutes au-delà duquel il lève ApiException(504, "Conversion timed out"). Les soumissions de lots de site entier sont exclues, parce qu'elles n'ont pas de ligne de job à interroger.
Quelle version de Java le SDK exige-t-il, et qu'embarque-t-il ?#
Java 17 ou plus récent. Le HTTP passe par le java.net.http.HttpClient du JDK, et Gson est le seul artefact tiers sur le classpath. Les réponses sont des records Java : un switch moderne ou un pattern matching sur ces types fonctionne donc comme attendu. Le client est thread-safe : gardez une seule instance et partagez-la.