API REST
Des endpoints HTTPS avec une clé d'API bearer. DTO stables, erreurs prévisibles, création idempotente.
Voir le cycle de vieUn cycle de vie des tâches prévisible sur une API REST et un MCP hébergé équivalent : créez une tâche, attendez ready, récupérez le Markdown, libérez l'emplacement. L'API et le MCP ne contournent jamais les limites du produit.
Choisissez l'intégration qui vous convient. Les deux appellent le même moteur de conversion et obéissent aux mêmes emplacements, limites et conservation.
Des endpoints HTTPS avec une clé d'API bearer. DTO stables, erreurs prévisibles, création idempotente.
Voir le cycle de vieUn endpoint Model Context Protocol géré qui expose la conversion sous forme d'outils d'agent : une fine couche au-dessus de la même API.
Connecter le MCPImportez un spec OpenAPI réduit dans un Custom GPT de ChatGPT pour qu'il convertisse les PDF comme outil intégré.
Configurer l'actionL'API et le MCP utilisent des clés d'API bearer, distinctes de la voie signée par appareil qu'utilise l'extension Chrome. Un compte Google gratuit est requis pour générer des clés.
Authorization: Bearer p2m_… à chaque requête.Idempotency-Key facultative à la création vous permet de réessayer sans risque, sans tâches en double.Scopes. Chaque clé d'API porte des scopes : jobs:create, jobs:read, jobs:download, jobs:delete (ceux par défaut), plus settings:read / settings:write. Émettez des clés au moindre privilège ; l'API REST comme les outils MCP appliquent les scopes de la clé.
Un cycle de vie prévisible, deux façons de le piloter : appelez l'API REST depuis votre propre code, ou utilisez les outils équivalents du MCP hébergé. Ne revendiquez jamais un résultat avant status=ready.
Faites un POST d'une URL de PDF ou téléversez des octets. Vous recevez un id de tâche et un emplacement. Idempotency-Key est respecté mais facultatif.
Interrogez la tâche jusqu'à ready ou error, ou enregistrez un webhook signé sur les offres payantes au lieu d'interroger.
Téléchargez le résultat une fois prêt. Lisez truncated et pages pour savoir si un long document a été renvoyé partiellement.
Libérez un emplacement une fois terminé. Supprimer des tâches en file ou en traitement est destructif : confirmez-le dans les clients destinés aux utilisateurs.
# 1. create a job from a PDF URL
curl -X POST https://pdf2md.dev/api/v2/jobs \
-H "Authorization: Bearer p2m_…" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/report.pdf"}'
# → { "job_id": "job_9f3c…", "status": "queued" }
# 2. poll status
curl https://pdf2md.dev/api/v2/jobs/job_9f3c… \
-H "Authorization: Bearer p2m_…"
# → { "status": "ready", "pages": 24, "truncated": false }
# 3. fetch the Markdown
curl https://pdf2md.dev/api/v2/jobs/job_9f3c…/download \
-H "Authorization: Bearer p2m_…"
# 4. free the slot
curl -X DELETE https://pdf2md.dev/api/v2/jobs/job_9f3c… \
-H "Authorization: Bearer p2m_…"
Erreurs. Les réponses utilisent des formes stables et des codes HTTP prévisibles (400 entrée incorrecte, 401 auth, 404 tâche inconnue, 409 aucun emplacement libre / slots_full, 413 trop volumineux, 429 débit limité). Le schéma complet se trouve dans le spec OpenAPI.
Create accepte un url JSON ou un file multipart, plus des champs facultatifs file_name, external_id, tags et callback_url / callback_secret pour un webhook par tâche. La création par lots est tout-ou-rien et doit tenir dans vos emplacements libres.
Compte et usage. Consultez votre offre, vos limites et votre usage à l'exécution avec GET /api/v2/me, /api/v2/limits et /api/v2/usage ; gérez les clés sur /api/v2/api-keys et les webhooks sur /api/v2/webhooks.
Les mêmes quatre appels depuis n'importe quel langage. Le voici avec requests. Pour un parcours complet pas à pas avec gestion des erreurs, consultez le tutoriel Python.
# pip install requests
import time, requests
API = "https://pdf2md.dev/api/v2"
H = {"Authorization": "Bearer p2m_…"}
# 1. create a job from a PDF URL (or post a file with files={"file": ...})
job = requests.post(f"{API}/jobs", headers=H,
json={"url": "https://example.com/report.pdf"}).json()
jid = job["job_id"]
# 2. poll until ready (or register a webhook instead)
while True:
j = requests.get(f"{API}/jobs/{jid}", headers=H).json()
if j["status"] in ("ready", "error"):
break
time.sleep(3)
# 3. download the Markdown
md = requests.get(f"{API}/jobs/{jid}/download", headers=H).text
print(md)
# multipart upload of a local PDF
curl -X POST https://pdf2md.dev/api/v2/jobs \
-H "Authorization: Bearer p2m_…" \
-F "[email protected]" \
-F "file_name=document.pdf"
// create from URL, poll, download
const API = "https://pdf2md.dev/api/v2";
const H = { Authorization: "Bearer p2m_…" };
let job = await (await fetch(`${API}/jobs`, {
method: "POST",
headers: { ...H, "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com/report.pdf" })
})).json();
while (job.status === "queued" || job.status === "processing") {
await new Promise(s => setTimeout(s, 2000));
job = await (await fetch(`${API}/jobs/${job.job_id}`, { headers: H })).json();
}
if (job.status === "ready") {
const md = await (await fetch(`${API}/jobs/${job.job_id}/download`, { headers: H })).text();
console.log(md);
}
La vérification de signature des webhooks est dans la section Webhooks ; la configuration du client MCP est dans la section MCP. Schéma complet : OpenAPI.
Connectez un agent compatible à notre endpoint MCP géré. Les outils sont une fine couche au-dessus de l'API REST, donc chaque appel obéit aux mêmes emplacements, limites et conservation.
JSON-RPC 2.0 sur Streamable HTTP avec votre clé d'API comme token bearer. Aucun serveur local à exécuter. Méthodes : initialize, tools/list, tools/call, ping.
Le même cycle de vie plus les limites, exposé sous forme de sept outils. Chacun respecte les scopes de la clé ; les réponses de tools/call incluent slot_usage et tier.
Attendez ready avant d'utiliser la sortie ; confirmez avant de supprimer des tâches en file/en traitement ; gérez truncated et 429 Retry-After. (Les noms d'outils sont préfixés par pdf_to_markdown_.)
// MCP client config (hosted, no local process)
{
"mcpServers": {
"pdf2md": {
"url": "https://pdf2md.dev/api/v2/mcp",
"headers": {
"Authorization": "Bearer p2m_…"
}
}
}
}
Nous publions deux specs : l'OpenAPI complet pour les développeurs, et un spec d'action réduit avec le sous-ensemble sûr et minimal pour les clients d'IA et les Custom GPT Actions de ChatGPT.
Le contrat complet : chaque endpoint, paramètre, DTO et erreur. Générez des clients ou explorez-le dans vos outils.
Un sous-ensemble minimal d'action (créer, statut, récupérer) pour les Custom GPT Actions de ChatGPT. Importez l'URL, définissez votre clé d'API comme auth, et votre GPT convertit les PDF nativement.
Le spec réduit est une commodité pour les clients d'IA, pas une frontière de sécurité : la même auth, les mêmes scopes et limites s'appliquent que sur l'API complète.
Les limites proviennent de votre offre et s'appliquent à l'identique sur chaque surface. Les valeurs en direct sont sur la page des tarifs.
Les offres payantes augmentent les emplacements, la taille de fichier, le budget de temps, la conservation et les limites de débit, et ajoutent les webhooks et la création par lots. Comparer les offres →
429 avec un en-tête Retry-After : temporisez et réessayez.409. Libérez un emplacement avec delete, ou attendez qu'une tâche se termine.Sur les offres payantes, enregistrez un webhook signé (ou passez un callback_url par tâche) et nous vous faisons un POST à chaque événement terminal notable : job.ready, job.error, job.truncated et job.deleted. L'événement est une notification, pas une livraison : il ne transporte aucun contenu de document, donc récupérez le Markdown via l'API après l'avoir reçu.
Faites un POST d'une URL HTTPS (protégée contre le SSRF) et d'un filtre events facultatif. Le secret de signature whsec_… est renvoyé une seule fois. Ou définissez callback_url + callback_secret sur une tâche unique.
Nous vous faisons un POST de JSON avec les en-têtes X-P2M-Event, X-P2M-Timestamp, X-P2M-Delivery et X-P2M-Signature.
Recalculez la signature, accusez réception avec 2xx, et soyez idempotent (les livraisons peuvent réessayer avec backoff). Téléchargez ensuite le Markdown.
# delivery → your endpoint
X-P2M-Event: job.ready
X-P2M-Timestamp: 1718900000
X-P2M-Signature: sha256=9a8b7c…
{
"event": "job.ready",
"job": {
"job_id": "job_9f3c…",
"status": "ready",
"pages": 24, "truncated": false,
"download_url": "/api/v2/jobs/job_9f3c…/download"
}
}
# verify (Python): signature = sha256= + hex(HMAC(secret, "ts.rawbody"))
import hmac, hashlib
def verify(secret, ts, raw_body, sig):
expected = "sha256=" + hmac.new(
secret.encode(), f"{ts}.".encode() + raw_body,
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
Insérez ces règles dans le system prompt d'un agent pour qu'il pilote correctement les outils et n'invente jamais de résultats.
Ne revendiquez ni ne résumez jamais un résultat avant status=ready. Tant que c'est queued ou processing, continuez d'interroger ou attendez le webhook.
Supprimer une tâche queued ou processing est destructif. Demandez à l'utilisateur avant d'appeler pdf_to_markdown_delete_job sur une tâche non terminée.
Si truncated=true, dites à l'utilisateur que le document a été renvoyé partiellement jusqu'au budget de temps de l'offre, et proposez une offre supérieure ou de découper le fichier.
En cas de 429, attendez le nombre de secondes de Retry-After avant de réessayer. Ne martelez pas la file.
Supprimez les tâches terminées dont vous n'avez plus besoin pour ne pas épuiser vos emplacements.
Partez de /llms.txt et du spec OpenAPI plutôt que de deviner les endpoints à partir de la prose.
Tout ce dont un agent a besoin pour s'intégrer sans lire le code source : un fichier de capacités compact, un fichier de contexte détaillé et le spec OpenAPI.