---
title: "Quickstart"
description: "Convert your first document to Markdown with the v1 API: one POST /v1/convert call, then read or poll the result."
url: https://markitdown.ai/docs/quickstart
updated: 2026-09-28
source: markitdown.ai
---

# Quickstart

> Convert your first document to Markdown with the v1 API: one POST /v1/convert call, then read or poll the result.

## 1. Convert a file or a web page

**POST** `/v1/convert/pdf` — Convert an uploaded PDF to Markdown

**A local file (multipart, up to 100 MB)**

```bash
curl -X POST https://api.markitdown.ai/v1/convert/pdf \
  -H "x-api-key: mdai_…" \
  -F file=@report.pdf
```

**POST** `/v1/convert/url` — Fetch a public web page and convert it to Markdown

**A public web page**

```bash
curl -X POST https://api.markitdown.ai/v1/convert/url \
  -H "x-api-key: mdai_…" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/article" }'
```

`url` input only works on `POST /v1/convert/url`: it fetches the page, keeps its main content, and renders the page in a headless browser first when the server sends an empty JavaScript shell (`render`: `auto` by default, `force`, or `skip`). Relative links come back as full URLs, and `frontmatter: true` adds the page title, author, and publish date as YAML front matter. A PDF or Office file behind a link has to be downloaded and sent as `file` — the API does not fetch arbitrary documents by URL.

## 2. Read the Markdown

When the document finishes within the wait window (60 seconds by default), the response is `200` with `status: "completed"` and the Markdown inlined in `files[0].outputs[0].content`. `usage.credits_charged` shows what the call cost and `files[0].pages` how many pages were parsed.

**200 OK (trimmed)**

```json
{
  "id": "cnv_3f7c…",
  "object": "conversion",
  "name": "pdf",
  "status": "completed",
  "async_reason": null,
  "summary": { "sources": 1, "queued": 0, "running": 0, "completed": 1, "failed": 0 },
  "files": [
    {
      "id": "file_a1…",
      "role": "source",
      "name": "report.pdf",
      "status": "completed",
      "pages": 12,
      "credits": 12,
      "outputs": [
        { "id": "file_b2…", "role": "output", "format": "markdown", "variant": "standard", "content": "# Quarterly report\n…" }
      ]
    }
  ],
  "usage": { "credits_charged": 12, "credits_reserved": 0, "credits_remaining": 138 },
  "links": { "self": "/v1/conversions/cnv_3f7c…", "files": "/v1/conversions/cnv_3f7c…/files", "events": "/v1/conversions/cnv_3f7c…/events" }
}
```

## 3. Poll when you get a 202

A large document, several files at once, or a busy queue returns `202 Accepted` with the same envelope in `status: "queued"` or `"running"`, a `Location` header, and a `Retry-After` hint. Wait on the conversion, then read it.

**Wait for the conversion (long poll)**

```bash
curl "https://api.markitdown.ai/v1/conversions/<id>?wait=100" -H "x-api-key: mdai_…"

# Or read one finished output's raw bytes directly
curl "https://api.markitdown.ai/v1/conversions/<id>/files/<file_id>/content" \
  -H "x-api-key: mdai_…"
```

## Which input should I send?

Send exactly one input kind per call. Use multipart `file` (or `files`, up to 100) for local bytes, JSON `url`/`urls` on `/v1/convert/url` for public pages, JSON `text`/`texts` for content you already hold in memory (`html`, `text`, and `markdown/*` names, up to 5 MB each), JSON `file`/`files` referencing a file id from an earlier conversion, or JSON `upload`/`uploads` referencing a completed `POST /v1/uploads` (for a file over the multipart size limit — see Files below). `POST /v1/convert/{name}/estimate` takes the same body and returns each source's page count and credit cost without creating anything.

## How do I avoid a double charge on retry?

Add an `Idempotency-Key` header with a unique value per logical submission, for example a UUID you store next to the source. If a network error hides the response, retry the same request with the same key: the API replays the original conversion, marked with `Idempotent-Replayed: true`, instead of starting and charging a second one. Keys are remembered for 24 hours; reusing one with a different body returns `409 idempotency_conflict`.

## Related

- [Introduction](https://markitdown.ai/docs/introduction)
- [Authentication](https://markitdown.ai/docs/authentication)
- [Introduction](https://markitdown.ai/docs)
- [Document Conversion APIs](https://markitdown.ai/developers)
