API tout fichier vers Markdown#

L'endpoint POST /v1/convert/anything-to-markdown convertit presque n'importe quel document envoyé — fichiers PDF, Word, PowerPoint, Excel, CSV, HTML, EPUB, texte brut et OpenDocument — en Markdown propre et structuré par titres. Il détecte automatiquement le format du fichier que vous envoyez, le dirige vers le bon extracteur et renvoie un seul fichier .md doté de la structure dont les pipelines LLM et RAG ont réellement besoin : de vrais titres #/##/###, des tableaux pipe GitHub-Flavored, des blocs de code délimités et des liens résolus. C'est l'équivalent fichier de url-to-markdown, et le même convertisseur alimente l'ingestion de fichiers dans l'endpoint d'ingestion — le Markdown que vous obtenez ici est donc exactement ce que consomme le découpeur sémantique.

Un seul endpoint remplace toute une pile de bibliothèques spécifiques à chaque format (pdfplumber, mammoth, python-pptx, openpyxl) : envoyez un fichier, récupérez le Markdown, transmettez-le à vos embeddings.


Endpoint#

POST /v1/convert/anything-to-markdown

Content-Type : multipart/form-data

Format de sortie : Markdown (.md, UTF-8). Le format est détecté automatiquement à partir de l'extension du nom de fichier envoyé et de ses magic bytes — vous ne spécifiez pas de type d'entrée.


Formats d'entrée pris en charge#

Le type d'entrée est détecté à partir de l'extension du fichier (validée par rapport aux magic bytes du fichier). Voici tous les formats acceptés par l'endpoint :

Catégorie Formats Extensions Notes
PDF PDF .pdf Titres déduits de la taille de police ; tableaux extraits sous forme de tableaux pipe ; en-têtes/pieds de page récurrents dédupliqués. Les PDF scannés ou uniquement composés d'images n'ont pas de couche de texte et sont rejetés — l'OCR n'est pas effectué.
Word DOCX, DOC .docx, .doc Les styles de titre Word deviennent #/##/### ; listes et tableaux préservés. Le format .doc (hérité) est traité via LibreOffice.
Présentations PPTX, PPT .pptx, .ppt Une section ## Slide N par diapositive, puces du corps, tableaux et notes de l'intervenant. .ppt (hérité) via LibreOffice.
Tableurs XLSX, XLS, CSV .xlsx, .xls, .csv Un titre ## SheetName plus un tableau GFM par feuille. Les valeurs des cellules sont conservées telles quelles (les zéros initiaux et les codes ne sont pas reformatés).
Livres numériques EPUB .epub Chapitres concaténés dans l'ordre de lecture (spine) ; le document de table des matières/navigation est ignoré.
Web / balisage HTML, XHTML .html, .htm, .xhtml Conversion fidèle du document complet (pas seulement une extraction de l'article).
OpenDocument ODT, ODS, ODP .odt, .ods, .odp Documents texte, tableur et présentation, via LibreOffice.
Texte enrichi RTF .rtf Converti via LibreOffice.
Texte brut Text, Markdown .txt, .text, .md, .markdown, .mdown, .mkd Passage direct avec encodage normalisé (le Markdown est déjà une sortie valide).
Note : Les images (.png, .jpg et similaires) ne sont pas encore prises en charge sur cet endpoint — l'OCR d'images nécessite un pipeline distinct et soumis à des coûts. L'envoi d'une image renvoie un 400 avec un message clair. Pour convertir une page web en Markdown au lieu d'un fichier, utilisez url-to-markdown.

Authentification#

Cet endpoint prend en charge l'authentification par clé privée et par clé publique.

Clé privée#

Incluez votre clé secrète dans l'en-tête X-API-Key. Utilisez cette méthode pour les appels serveur à serveur où la clé n'est jamais exposée au client.

X-API-Key: sk_live_your_private_key

Clé publique avec JWT#

Pour une utilisation côté client, générez d'abord un token JWT avec votre clé publique, puis transmettez-le comme token Bearer.

Étape 1 -- Obtenir un token :

POST /v1/auth/token
X-API-Key: pk_live_your_public_key

Étape 2 -- Utiliser le token :

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Le flux complet, y compris le verrouillage de domaine et le renouvellement du token, est décrit dans le guide d'authentification. Chaque clé API porte une liste blanche d'endpoints autorisés — si /v1/convert/anything-to-markdown ne figure pas dans la liste de la clé, la requête est rejetée avec un 403.


Paramètres de requête#

Envoyez le fichier au format multipart/form-data. Le document va dans le champ file ; les autres sont des champs de formulaire optionnels.

Paramètre Type Requis Défaut Description
file fichier Oui -- Le document à convertir. Son extension doit être l'un des formats d'entrée pris en charge ci-dessus.
output_filename string Non Nom d'entrée Nom personnalisé pour le fichier de sortie. L'extension .md est ajoutée automatiquement.
direct_download boolean Non true Accepté pour la cohérence de la forme des requêtes avec les autres endpoints de conversion.
job_id string Non -- ID de tâche fourni par le client pour la récupération après expiration. Lorsqu'une conversion synchrone dépasse les limites de délai du reverse-proxy, interrogez GET /v1/convert/status/{job_id} pour récupérer le résultat.

Réponse#

La conversion s'exécute en interne et le fichier .md résultant est stocké, puis l'endpoint renvoie un corps JSON avec une URL de téléchargement pré-signée :

{
    "presigned_url": "https://spaces.example.com/...signed...",
    "object_key": "env/files/{project_id}/anything-to-markdown/report_20260714_101530123.md",
    "filename": "report_20260714_101530123.md",
    "file_size": 5124,
    "conversion_time_seconds": 1.8,
    "job_id": null
}

Les mêmes valeurs sont renvoyées dans les en-têtes de réponse (X-Object-Key, X-File-Size, X-Conversion-Time, X-Filename) pour que vous puissiez les lire sans analyser le corps. Téléchargez le Markdown depuis presigned_url — le lien est éphémère.


Comment chaque format est converti#

Chaque format est normalisé selon la même forme Markdown propre, de sorte que le découpage et l'embedding en aval voient une structure cohérente quelle que soit la source.

  • PDF — Le texte est extrait avec un positionnement au niveau du mot. La taille de police la plus courante est traitée comme le corps du texte ; les tailles plus grandes deviennent des titres #/##/### (les plus grandes d'abord). Les tableaux sont détectés géométriquement et émis sous forme de tableaux pipe GFM, et leur texte est retiré du flux de prose afin que rien ne soit dupliqué. Les lignes qui se répètent sur la plupart des pages (en-têtes/pieds de page récurrents) sont supprimées. Un PDF sans couche de texte (un scan ou un export uniquement composé d'images) est rejeté avec un 400 clair — cet endpoint n'exécute pas d'OCR.
  • DOCX / DOC — Les styles de paragraphe « Heading 1/2/3 » de Word correspondent proprement à #/##/### ; listes, tableaux, gras et italique sont préservés. Le format hérité .doc est d'abord routé via LibreOffice.
  • PPTX / PPT — Chaque diapositive devient une section ## Slide N: Title, les espaces réservés du corps deviennent des puces, les tableaux deviennent des tableaux pipe, et les notes de l'intervenant sont ajoutées comme sous-section ### Notes — chaque diapositive est ainsi une unité indépendante et récupérable.
  • XLSX / XLS / CSV — Chaque feuille de calcul devient un titre ## SheetName plus un tableau GFM ; un CSV est un seul tableau. Les cellules sont lues comme des chaînes de caractères, de sorte que les identifiants, les codes et les zéros initiaux sont préservés exactement.
  • EPUB — Les documents de contenu sont lus dans l'ordre du spine (ordre de lecture) et convertis chapitre par chapitre ; le document de navigation/table des matières est ignoré afin de ne pas polluer vos chunks.
  • HTML / XHTML — Le document entier est converti fidèlement (il n'est pas réduit à un seul « article »), avec suppression de script/style/noscript et préservation des titres, listes, tableaux, liens et code.
  • ODT / ODS / ODP / RTF — Convertis via le même moteur LibreOffice qui alimente les endpoints document-vers-PDF.
  • Text / Markdown — Les fins de ligne et l'encodage sont normalisés ; un envoi .md passe essentiellement sans modification.

Format de sortie#

Le résultat est du Markdown GitHub-Flavored conçu pour être consommé par des machines :

  • Titres — ATX (#, ##, ###), utilisés comme limites de section sémantiques.
  • Tableaux — Tableaux pipe GFM (gardés atomiques, jamais divisés), avec les | dans les cellules échappés.
  • Code — Blocs délimités avec indications de langage lorsque détectables.
  • Structure — Paragraphes, listes et citations préservés ; les sections par diapositive et par feuille donnent de véritables limites même aux formats plats.

Comme les titres sont de véritables titres ATX, cette sortie alimente directement un découpeur sensible aux titres. Si vous voulez les chunks — pas seulement le Markdown — envoyez plutôt le fichier à l'endpoint d'ingestion, qui exécute exactement cette conversion puis découpe le résultat en JSONL prêt pour le RAG.


Construire un pipeline RAG#

Cet endpoint convertit un fichier à la fois en Markdown. Pour un pipeline de récupération complet, vous voulez généralement des chunks, pas du Markdown brut, et souvent plusieurs fichiers à la fois :

  • Un seul fichier, juste le Markdown — utilisez cet endpoint, puis découpez-le vous-même.
  • Plusieurs fichiers, découpés en JSONL — utilisez POST /v2/ingest/files. Il exécute la même conversion sur chaque fichier envoyé, découpe chacun en chunks sensibles aux titres, et assemble un seul fichier JSONL qui se charge directement dans JSONLoader de LangChain, SimpleDirectoryReader de LlamaIndex, ou une base de données vectorielle.
  • Pages web au lieu de fichiers — utilisez POST /v2/ingest (crawl ou liste d'URL) ou url-to-markdown pour une seule page.

Exemples de code#

curl (clé privée)#

curl -X POST https://api.enconvert.com/v1/convert/anything-to-markdown \
  -H "X-API-Key: sk_live_your_private_key" \
  -F "[email protected]"

Python (clé privée)#

import requests

with open("quarterly-report.pdf", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/anything-to-markdown",
        headers={"X-API-Key": "sk_live_your_private_key"},
        files={"file": ("quarterly-report.pdf", f)},
    )

response.raise_for_status()
result = response.json()

# Download the Markdown from the pre-signed URL.
markdown = requests.get(result["presigned_url"]).text
print(markdown)

Node.js (clé privée)#

import { readFile } from "node:fs/promises";

const form = new FormData();
form.append(
    "file",
    new Blob([await readFile("quarterly-report.pdf")]),
    "quarterly-report.pdf"
);

const response = await fetch(
    "https://api.enconvert.com/v1/convert/anything-to-markdown",
    { method: "POST", headers: { "X-API-Key": "sk_live_your_private_key" }, body: form }
);

const result = await response.json();
const markdown = await fetch(result.presigned_url).then((r) => r.text());
console.log(markdown);

PHP (clé privée)#

$ch = curl_init("https://api.enconvert.com/v1/convert/anything-to-markdown");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["X-API-Key: sk_live_your_private_key"],
    CURLOPT_POSTFIELDS => [
        "file" => new CURLFile("quarterly-report.pdf", "application/pdf", "quarterly-report.pdf"),
    ],
]);

$data = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $data["presigned_url"];

Réponses d'erreur#

Statut Condition
400 Bad Request Type de fichier non pris en charge, fichier vide, envoi d'une image (OCR non pris en charge) ou document sans texte extractible (par exemple un PDF scanné).
400 Bad Request Les octets du fichier ne correspondent pas à son extension déclarée (non-correspondance des magic bytes).
401 Unauthorized Clé API / token JWT manquant ou invalide.
402 Payment Required Limite mensuelle de conversions ou limite de stockage atteinte.
403 Forbidden /v1/convert/anything-to-markdown ne figure pas dans les endpoints autorisés de la clé API.
413 Payload Too Large L'envoi dépasse la limite de taille par fichier de votre forfait.
500 Internal Server Error La conversion a échoué de manière inattendue.

La référence complète des codes de statut est disponible dans le guide des codes d'erreur.


Limites#

Limite Valeur
Taille d'envoi maximale Selon le forfait (Free : 5 MB)
Conversions mensuelles Selon le forfait (Free : 100)
Conservation des fichiers Selon le forfait (Free : 1 heure)
Plafond de pages PDF 2,000 pages
Formats d'entrée pris en charge Voir le tableau formats d'entrée pris en charge

Questions fréquentes#

Comment convertir un PDF en Markdown avec une API ?#

Envoyez une requête POST à /v1/convert/anything-to-markdown au format multipart/form-data avec le PDF dans le champ file et votre clé dans l'en-tête X-API-Key. Vous recevez en retour du JSON avec un presigned_url vers un fichier .md dont les titres proviennent des tailles de police du PDF et dont les tableaux sont des tableaux pipe GitHub-Flavored. Les PDF scannés ou uniquement composés d'images n'ont pas de couche de texte et sont rejetés — cet endpoint n'exécute pas d'OCR.

Quels formats de fichier puis-je convertir en Markdown ?#

PDF, Word (.docx, .doc), PowerPoint (.pptx, .ppt), Excel (.xlsx, .xls), CSV, EPUB, HTML/XHTML, OpenDocument (.odt, .ods, .odp), RTF, ainsi que texte brut/Markdown. La liste complète avec des notes par format se trouve dans le tableau formats d'entrée pris en charge. Les images ne sont pas encore prises en charge.

Puis-je convertir des documents en Markdown pour un pipeline RAG ou LLM ?#

Oui — c'est précisément l'objectif de la sortie : de vrais titres #/##/###, des tableaux pipe atomiques et du code délimité. Pour un seul fichier, vous obtenez le Markdown ici et le découpez vous-même ; pour plusieurs fichiers découpés en JSONL prêt à être embarqué, envoyez-les à POST /v2/ingest/files, qui exécute cette même conversion et découpe chaque fichier en chunks prêts pour le RAG.

En quoi est-ce différent de Microsoft MarkItDown ou docling ?#

Il résout le même problème de « n'importe quel fichier vers Markdown » sous forme d'API hébergée — pas d'installation locale, pas de lourdes dépendances ML, et une sortie sensible aux titres optimisée pour le découpage. Il s'associe directement à /v2/ingest pour que la même conversion alimente un pipeline RAG de bout en bout (conversion → découpage → JSONL) sans avoir à câbler vous-même les bibliothèques ensemble.

Convertissez-vous les PDF scannés ou les images ?#

Pas sur cet endpoint. Un PDF doit avoir une véritable couche de texte ; un PDF scanné ou uniquement composé d'images, ou un fichier image (.png, .jpg), est rejeté avec un 400 clair car l'OCR est un pipeline distinct et soumis à des coûts. Les PDF nativement numériques et les autres formats de document listés se convertissent proprement.