> ## Documentation Index
> Fetch the complete documentation index at: https://docs.markpdf.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Referencia

> Python client classes, methods and options.

# Referencia

## Clientes

<CodeGroup>
  ```python Client (síncrono) theme={null}
  import markpdf

  client = markpdf.Client(
      api_key="YOUR_API_KEY",     # or MARKPDF_API_KEY environment variable
      base_url="https://api.markpdf.tech",  # optional, production default
      timeout=300,               # segundos, default 300
      max_retries=2,             # reintentos automáticos en 429/5xx
  )
  ```

  ```python AsyncClient (asíncrono) theme={null}
  import markpdf

  client = markpdf.AsyncClient(
      api_key="YOUR_API_KEY",
      base_url="https://api.markpdf.tech",
      timeout=300,
      max_retries=2,
  )
  ```
</CodeGroup>

<ParamField body="api_key" type="string" required>
  Your API key. If you don't pass it, the client reads `MARKPDF_API_KEY` from the environment.
</ParamField>

<ParamField body="base_url" type="string" default="https://api.markpdf.tech">
  URL base of API. Change it only if you use your own proxy.
</ParamField>

<ParamField body="timeout" type="float" default="300">
  Timeout in seconds per request HTTP. Large documents in `mode=quality` may take longer; upload it if you need it.
</ParamField>

<ParamField body="max_retries" type="integer" default="2">
  Automatic retries with exponential backoff in `429` and `5xx`. See [Error Handling](/docs/sdks/python/error-handling).
</ParamField>

`AsyncClient` implements the async context manager protocol (`async with`) to successfully close the HTTP session. `Client` also supports `with`.

## Methods common to both clients

All methods accept the same named parameters as the conversion [API](/docs/api/parameters). `AsyncClient` exposes the same signature with `await`.

### `convert_file`

```python theme={null}
client.convert_file(
    path: str | Path,
    *,
    input_format: str = "auto",
    mode: str = "fast",
    engine: str = "auto",
    clean: bool = True,
    response_format: str = "markdown",
    pages: str | None = None,
    output_url: str | None = None,
    output_encoding: str = "identity",
    output_head_url: str | None = None,
    auto_poll: bool = True,
) -> str | ConversionResult
```

Upload a local file to `POST /convert/raw` with the contents compressed to `gzip` if it exceeds 1MB (transparent, no configuration required). Returns `str` with Markdown, or `ConversionResult` if `response_format="json"`.

<ParamField body="path" type="str | Path" required>
  Path to local file.
</ParamField>

<ParamField body="auto_poll" type="boolean" default="true">
  If the server responds `202` (backends saturated), SDK automatically polls from `GET /jobs/{id}` to `completed` or `failed`. With `auto_poll=Failedse`, the method casts `MarkpdfJobQueuedError` with the `job_id` so you can do the poll yourself. See [Streaming and async](/docs/sdks/python/streaming-and-async).
</ParamField>

### `convert_from_url`

```python theme={null}
client.convert_from_url(
    url: str,
    *,
    filename: str | None = None,
    input_format: str = "auto",
    mode: str = "fast",
    engine: str = "auto",
    clean: bool = True,
    response_format: str = "markdown",
    pages: str | None = None,
    output_url: str | None = None,
    output_encoding: str = "identity",
    output_head_url: str | None = None,
    auto_poll: bool = True,
) -> str | ConversionResult
```

Call `POST /convert/from-url`. `url` must be a pre-signed URL accessible by HTTPS.

### `convert_stream`

```python theme={null}
client.convert_stream(
    path: str | Path | None = None,
    *,
    url: str | None = None,
    filename: str | None = None,
    input_format: str = "auto",
    clean: bool = True,
    slim: bool = True,
    stream_slim_strategy: str = "sampled",
) -> Iterator[str]  # AsyncIterator[str] en AsyncClient
```

Returns an iterator that produces Markdown fragments as they arrive via streaming (`POST /convert/stream` or `/convert/stream-from-url` depending on `path` or `url` passes). See [Streaming and async](/docs/sdks/python/streaming-and-async).

### `pdf_index`

```python theme={null}
client.pdf_index(url: str, *, filename: str | None = None) -> PdfSpine
```

Call `POST /pdf/index`. Returns a `PdfSpine` object typed with `page_count`, `sections`, `pages`, `font_model`, `estimated_tokens_full`, etc. — same fields documented by [`POST /pdf/index`](/docs/api/pdf-index).

```python theme={null}
spine = client.pdf_index("https://bucket.example.com/report.pdf?sig=...")
for section in spine.sections:
    print(section.page, section.level, section.text)
```

### `get_job`

```python theme={null}
client.get_job(job_id: str) -> JobStatus
```

Manually query `GET /jobs/{id}`. `JobStatus.status` is one of `"queued"`, `"processing"`, `"completed"`, `"failed"`. When `status == "completed"`, `JobStatus.body` contains the original result (Markdown or JSON depending on the parameters of the queued conversion).

## Return Types

### `ConversionResult`

<ResponseField name="markdown" type="str">
  Converted document.
</ResponseField>

<ResponseField name="filename" type="str">
  Name of the processed document.
</ResponseField>

<ResponseField name="input_format" type="str">
  Formato detectado o forzado.
</ResponseField>

<ResponseField name="engine" type="str">
  Engine that produced the output.
</ResponseField>

<ResponseField name="size_bytes" type="int">
  Input document size.
</ResponseField>

<ResponseField name="markdown_bytes" type="int">
  Output Markdown size.
</ResponseField>

<ResponseField name="token_saved_estimate" type="int">
  Estimated saved tokens vs. raw document.
</ResponseField>

<ResponseField name="timings" type="Timings">
  `convert_ms`, `clean_ms`, `total_worker_ms`, `upload_ms`, `total_request_ms`.
</ResponseField>

### `PdfSpine`

<ResponseField name="page_count" type="int" />

<ResponseField name="sections" type="list[Section]">
  Each `Section` has `page`, `level`, `text`.
</ResponseField>

<ResponseField name="pages" type="list[PageInfo]">
  Each `PageInfo` has `page`, `chars`, `first_line`, `headings`.
</ResponseField>

<ResponseField name="pages_truncated" type="bool" />

<ResponseField name="estimated_tokens_full" type="int" />

<ResponseField name="estimated_tokens_spine_only" type="int" />

### `JobStatus`

<ResponseField name="job_id" type="str" />

<ResponseField name="status" type="str">
  `"queued"`, `"processing"`, `"completed"` o `"failed"`.
</ResponseField>

<ResponseField name="body" type="str | dict | None">
  Present only when `status == "completed"`.
</ResponseField>

<ResponseField name="error" type="str | None">
  Present only when `status == "failed"`.
</ResponseField>
