API Anything to Markdown#
L'endpoint POST /v1/convert/anything-to-markdown converte quasi ogni documento caricato — file PDF, Word, PowerPoint, Excel, CSV, HTML, EPUB, testo semplice e OpenDocument — in Markdown pulito e strutturato per intestazioni. Rileva automaticamente il formato dal file che invii, lo instrada all'estrattore giusto e restituisce un unico file .md con la struttura di cui le pipeline LLM e RAG hanno davvero bisogno: vere intestazioni #/##/###, tabelle pipe GitHub-Flavored, blocchi di codice recintati e link risolti. È la controparte per file di url-to-markdown, e lo stesso convertitore alimenta l'ingestione di file nell'endpoint di ingest — quindi il Markdown che ottieni qui è esattamente ciò che il chunker semantico consuma.
Un solo endpoint sostituisce uno stack di librerie specifiche per formato (pdfplumber, mammoth, python-pptx, openpyxl): carichi un file, ottieni Markdown, lo passi ai tuoi embedding.
Endpoint#
POST /v1/convert/anything-to-markdown
Content-Type: multipart/form-data
Formato di output: Markdown (.md, UTF-8). Il formato viene rilevato automaticamente dall'estensione del nome del file caricato e dai suoi magic byte — non devi specificare un tipo di input.
Formati di input supportati#
Il tipo di input viene rilevato dall'estensione del file (validata rispetto ai magic byte del file). Questi sono tutti i formati che l'endpoint accetta:
| Categoria | Formati | Estensioni | Note |
|---|---|---|---|
.pdf |
Intestazioni dedotte dalla dimensione del font; tabelle estratte come tabelle pipe; intestazioni/piè di pagina ricorrenti deduplicati. I PDF scansionati o solo immagine non hanno un livello di testo e vengono rifiutati — l'OCR non viene eseguito. | ||
| Word | DOCX, DOC | .docx, .doc |
Gli stili di intestazione di Word diventano #/##/###; elenchi e tabelle preservati. Il formato .doc (legacy) è gestito tramite LibreOffice. |
| Presentazioni | PPTX, PPT | .pptx, .ppt |
Una sezione ## Slide N per diapositiva, elenchi puntati del corpo, tabelle e note del relatore. .ppt (legacy) tramite LibreOffice. |
| Fogli di calcolo | XLSX, XLS, CSV | .xlsx, .xls, .csv |
Un'intestazione ## SheetName più una tabella GFM per foglio. I valori delle celle sono mantenuti alla lettera (zeri iniziali e codici non vengono riformattati). |
| E-book | EPUB | .epub |
Capitoli concatenati nell'ordine di lettura (spine); il documento indice/navigazione viene saltato. |
| Web / markup | HTML, XHTML | .html, .htm, .xhtml |
Conversione fedele dell'intero documento (non estrazione del solo articolo). |
| OpenDocument | ODT, ODS, ODP | .odt, .ods, .odp |
Documenti di testo, foglio di calcolo e presentazione, tramite LibreOffice. |
| Testo formattato | RTF | .rtf |
Convertito tramite LibreOffice. |
| Testo semplice | Text, Markdown | .txt, .text, .md, .markdown, .mdown, .mkd |
Passthrough con codifica normalizzata (Markdown è già output valido). |
.png, .jpg e simili) non sono ancora supportate su questo endpoint — l'OCR delle immagini richiede una pipeline separata e soggetta a costi. Il caricamento di un'immagine restituisce un 400 con un messaggio chiaro. Per convertire una pagina web in Markdown invece di un file, usa url-to-markdown.
Autenticazione#
Questo endpoint supporta l'autenticazione sia con chiave privata sia con chiave pubblica.
Chiave privata#
Includi la tua chiave segreta nell'header X-API-Key. Usala per le chiamate server-to-server in cui la chiave non viene mai esposta al client.
X-API-Key: sk_live_your_private_key
Chiave pubblica con JWT#
Per l'uso lato client, genera prima un token JWT con la tua chiave pubblica, poi passalo come token Bearer.
Passo 1 -- Ottieni un token:
POST /v1/auth/token
X-API-Key: pk_live_your_public_key
Passo 2 -- Usa il token:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Il flusso completo, incluso il blocco per dominio e il refresh del token, è descritto nella guida all'autenticazione. Ogni chiave API contiene una allowlist di endpoint consentiti — se /v1/convert/anything-to-markdown non è nell'elenco della chiave, la richiesta viene rifiutata con 403.
Parametri della richiesta#
Invia il file come multipart/form-data. Il documento va nel campo file; gli altri sono campi form opzionali.
| Parametro | Tipo | Obbligatorio | Predefinito | Descrizione |
|---|---|---|---|---|
file |
file | Sì | -- | Il documento da convertire. La sua estensione deve essere uno dei formati di input supportati sopra. |
output_filename |
string |
No | Nome input | Nome personalizzato per il file di output. L'estensione .md viene aggiunta automaticamente. |
direct_download |
boolean |
No | true |
Accettato per parità di forma della richiesta con gli altri endpoint di conversione. |
job_id |
string |
No | -- | Job ID fornito dal client per il recupero in caso di timeout. Quando una conversione sincrona supera i limiti di timeout del reverse proxy, interroga GET /v1/convert/status/{job_id} per recuperare il risultato. |
Risposta#
La conversione viene eseguita in-process e il file .md risultante viene archiviato, poi l'endpoint restituisce un corpo JSON con un URL di download pre-firmato:
{
"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
}
Gli stessi valori sono riportati negli header di risposta (X-Object-Key, X-File-Size, X-Conversion-Time, X-Filename) così puoi leggerli senza analizzare il corpo. Scarica il Markdown da presigned_url — il link ha vita breve.
Come viene convertito ciascun formato#
Ogni formato viene normalizzato nella stessa forma Markdown pulita, così il chunking e l'embedding a valle vedono una struttura coerente indipendentemente dalla sorgente.
- PDF — Il testo viene estratto con posizionamento a livello di parola. La dimensione del font più comune è trattata come testo del corpo; le dimensioni maggiori diventano intestazioni
#/##/###(dalla più grande). Le tabelle vengono rilevate geometricamente ed emesse come tabelle pipe GFM, e il loro testo viene rimosso dal flusso di prosa così nulla viene duplicato. Le righe che si ripetono sulla maggior parte delle pagine (intestazioni/piè di pagina ricorrenti) vengono scartate. Un PDF senza livello di testo (una scansione o un export solo immagine) viene rifiutato con un chiaro400— questo endpoint non esegue OCR. - DOCX / DOC — Gli stili di paragrafo "Heading 1/2/3" di Word si mappano in modo netto su
#/##/###; elenchi, tabelle, grassetto e corsivo sono preservati. Il formato.doclegacy viene prima instradato attraverso LibreOffice. - PPTX / PPT — Ogni diapositiva diventa una sezione
## Slide N: Title, i segnaposto del corpo diventano elenchi puntati, le tabelle diventano tabelle pipe e le note del relatore vengono aggiunte come sottosezione### Notes— così ogni diapositiva è un'unità indipendente e recuperabile. - XLSX / XLS / CSV — Ogni foglio di lavoro diventa un'intestazione
## SheetNamepiù una tabella GFM; un CSV è una singola tabella. Le celle vengono lette come stringhe, così ID, codici e zeri iniziali sono preservati esattamente. - EPUB — I documenti di contenuto vengono letti nell'ordine spine (di lettura) e convertiti capitolo per capitolo; il documento di navigazione/indice viene saltato così da non inquinare i tuoi chunk.
- HTML / XHTML — L'intero documento viene convertito fedelmente (non ridotto a un singolo "articolo"), con script/style/noscript rimossi e intestazioni, elenchi, tabelle, link e codice preservati.
- ODT / ODS / ODP / RTF — Convertiti tramite lo stesso motore LibreOffice che alimenta gli endpoint document-to-PDF.
- Text / Markdown — I fine riga e la codifica vengono normalizzati; un caricamento
.mdpassa essenzialmente invariato.
Formato di output#
Il risultato è Markdown GitHub-Flavored costruito per il consumo da parte delle macchine:
- Intestazioni — ATX (
#,##,###), usate come confini semantici delle sezioni. - Tabelle — Tabelle pipe GFM (mantenute atomiche, mai divise), con i
|nelle celle preceduti da escape. - Codice — Blocchi recintati con indicazione del linguaggio dove rilevabile.
- Struttura — Paragrafi, elenchi e citazioni preservati; le sezioni per diapositiva e per foglio danno confini reali anche ai formati piatti.
Poiché le intestazioni sono vere intestazioni ATX, questo output alimenta direttamente un chunker che riconosce le intestazioni. Se vuoi i chunk — non solo il Markdown — invia il file all'endpoint di ingest, che esegue esattamente questa conversione e poi suddivide il risultato in JSONL pronto per RAG.
Costruire una pipeline RAG#
Questo endpoint converte un file alla volta in Markdown. Per una pipeline di retrieval completa di solito vuoi i chunk, non il Markdown grezzo, e spesso molti file in una volta:
- Un file, solo il Markdown — usa questo endpoint, poi suddividilo in chunk da solo.
- Molti file, suddivisi in JSONL — usa
POST /v2/ingest/files. Esegue la stessa conversione su ogni file caricato, suddivide ciascuno in chunk basati sulle intestazioni e assembla un unico file JSONL che si carica direttamente inJSONLoaderdi LangChain,SimpleDirectoryReaderdi LlamaIndex o in un database vettoriale. - Pagine web invece di file — usa
POST /v2/ingest(crawl o elenco di URL) o url-to-markdown per una singola pagina.
Esempi di codice#
curl (chiave privata)#
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 (chiave privata)#
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 (chiave privata)#
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 (chiave privata)#
$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"];
Risposte di errore#
| Stato | Condizione |
|---|---|
400 Bad Request |
Tipo di file non supportato, un file vuoto, il caricamento di un'immagine (OCR non supportato) o un documento senza testo estraibile (ad es. un PDF scansionato). |
400 Bad Request |
I byte del file non corrispondono all'estensione dichiarata (mancata corrispondenza dei magic byte). |
401 Unauthorized |
Chiave API / token JWT mancante o non valido. |
402 Payment Required |
Limite mensile di conversioni o limite di archiviazione raggiunto. |
403 Forbidden |
/v1/convert/anything-to-markdown non è tra gli endpoint consentiti della chiave API. |
413 Payload Too Large |
Il caricamento supera il limite di dimensione per file del tuo piano. |
500 Internal Server Error |
La conversione è fallita in modo imprevisto. |
Il riferimento completo dei codici di stato è nella guida ai codici di errore.
Limiti#
| Limite | Valore |
|---|---|
| Dimensione massima di caricamento | Dipende dal piano (Free: 5 MB) |
| Conversioni mensili | Dipende dal piano (Free: 100) |
| Conservazione dei file | Dipende dal piano (Free: 1 ora) |
| Limite di pagine PDF | 2,000 pagine |
| Formati di input supportati | Vedi la tabella dei formati di input supportati |
Domande frequenti#
Come converto un PDF in Markdown con un'API?#
Invia una richiesta POST a /v1/convert/anything-to-markdown come multipart/form-data con il PDF nel campo file e la tua chiave nell'header X-API-Key. Ricevi JSON con un presigned_url a un file .md le cui intestazioni derivano dalle dimensioni dei font del PDF e le cui tabelle sono tabelle pipe GitHub-Flavored. I PDF scansionati o solo immagine non hanno un livello di testo e vengono rifiutati — questo endpoint non esegue OCR.
Quali formati di file posso convertire in Markdown?#
PDF, Word (.docx, .doc), PowerPoint (.pptx, .ppt), Excel (.xlsx, .xls), CSV, EPUB, HTML/XHTML, OpenDocument (.odt, .ods, .odp), RTF e testo semplice/Markdown. L'elenco completo con note per ciascun formato è nella tabella dei formati di input supportati. Le immagini non sono ancora supportate.
Posso convertire documenti in Markdown per una pipeline RAG o LLM?#
Sì — è proprio per questo che è costruito l'output: vere intestazioni #/##/###, tabelle pipe atomiche e codice recintato. Per un singolo file ottieni qui il Markdown e lo suddividi in chunk da solo; per molti file suddivisi in JSONL pronto per l'embedding, inviali a POST /v2/ingest/files, che esegue questa stessa conversione e suddivide ciascun file in chunk pronti per RAG.
In cosa differisce da Microsoft MarkItDown o docling?#
Risolve lo stesso problema "qualsiasi file in Markdown" come API in hosting — nessuna installazione locale, nessuna dipendenza ML pesante e output basato sulle intestazioni ottimizzato per il chunking. Si abbina direttamente a /v2/ingest così la stessa conversione alimenta una pipeline RAG end-to-end (conversione → chunk → JSONL) senza dover collegare tu stesso le librerie.
Convertite PDF scansionati o immagini?#
Non su questo endpoint. Un PDF deve avere un vero livello di testo; un PDF scansionato o solo immagine, o un file immagine (.png, .jpg), viene rifiutato con un chiaro 400 perché l'OCR è una pipeline separata e soggetta a costi. I PDF nativi digitali e gli altri formati di documento elencati si convertono senza problemi.