DocumentationAPI Reference

Developer

Webhooks

Receive signed conversion.completed and conversion.failed events instead of polling, and verify each delivery.

Manage endpoints

GEThttps://api.markitdown.ai/v1/webhooksList endpoints
POSThttps://api.markitdown.ai/v1/webhooksRegister an endpoint
DELETEhttps://api.markitdown.ai/v1/webhooks/{id}Remove an endpoint
Create body
urlrequiredstringPublic https URL. Private and reserved addresses are rejected.
eventTypesrequiredstring[]conversion.completed, conversion.failed, or both.

The create response includes the signing secret once. Store it; it is not shown again. Managing webhook endpoints does not require an active subscription — only submitting, estimating, and retrying a conversion do.

Events and payload

  • conversion.completed — a conversion reached completed or completed_with_errors.

  • conversion.failed — every source file in a conversion failed.

  • Each fires once per terminal entry; retrying a failed file moves the conversion back to running, and it fires again the next time the conversion terminates.

Delivery body
{
  "id": "cnv_3f7c…:2026-01-01T00:00:04Z",
  "type": "conversion.completed",
  "data": { "id": "cnv_3f7c…", "object": "conversion", "name": "pdf", "status": "completed", "summary": { "sources": 1, "queued": 0, "running": 0, "completed": 1, "failed": 0 }, "usage": { "credits_charged": 12 }, "links": { "self": "/v1/conversions/cnv_3f7c…", "files": "…/files", "events": "…/events" } }
}

data is the conversion summary envelope — the same shape GET /v1/conversions/{id} returns without its files list, so payload size never depends on how many source files the conversion had. Fetch the outputs with GET /v1/conversions/{id}/files after a delivery.

What does a delivery request look like?

Each delivery is an HTTPS POST with a JSON body. Besides the signature headers it carries x-markitdown-event with the event type and x-markitdown-delivery with a delivery id, so you can route and log events before parsing the body. Register one endpoint per destination and subscribe it only to the events it handles.

How do I verify a delivery?

Deliveries follow Standard Webhooks. Each request carries webhook-id, webhook-timestamp, and webhook-signature. Compute HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{raw body} with your secret (base64-decode it first when it starts with whsec_) and compare the base64 digest with the v1, value in webhook-signature. Reject old timestamps to stop replays. The same delivery also carries x-markitdown-signature: sha256=<hex HMAC of the raw body> for simpler verifiers.

What if my endpoint is down?

Answer with any 2xx status to acknowledge a delivery. Anything else, including a redirect or a timeout, is retried, for up to five attempts in total, with exponential backoff starting at 10 seconds. Handle events idempotently by webhook-id, because a delivery can arrive more than once. If every attempt fails the conversion itself is unaffected: read it with GET /v1/conversions/{id}.

On this page