# cURL walkthrough

[HTML](https://pdfcraft.ai/docs/getting-started/quickstart/)
[Site index](https://pdfcraft.ai/llms.txt)

Upload your own PDF and inspect every request from creation to download.


Prepare a small PDF named `document.pdf`. You will need Bash or Zsh, cURL 7.76 or later, Python 3, and [jq](https://jqlang.org/). Conversion uses account credits.

Run the commands in order in the same terminal session. If a step fails, resolve the error before continuing.

## Prepare authentication

Create a key in [OOMOL Console](https://console.oomol.com/api-key), then set:

```bash
export PDF_CRAFT_API_KEY="$(
  python3 -c 'import getpass; print(getpass.getpass("API key: "))'
)"
BASE=https://api.pdfcraft.ai/v1/pcc-api
```

The Python command reads the key without displaying it in the terminal. The remaining commands use cURL.

These API requests include your key, so they omit `--location` to avoid following redirects automatically. If you receive a redirect, check the request URL before continuing.

## Create a task

```bash
curl --fail-with-body --silent --show-error "$BASE/transforms" \
  -H "Authorization: Bearer $PDF_CRAFT_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"input_format":"pdf","input_filename":"document.pdf"}' \
  --output task.json
TASK_UUID=$(jq -er '.uuid' task.json)
```

Expect HTTP `201` and `status: "waiting_for_upload"`. Keep `task.json`; creation does not start processing. If the response is lost, investigate the waiting list rather than automatically creating another task.

## Upload the file

```bash
curl --fail-with-body --silent --show-error \
  "$BASE/transforms/$TASK_UUID/upload-urls" \
  -H "Authorization: Bearer $PDF_CRAFT_API_KEY" \
  --output upload.json
jq . upload.json
```

If `put_url` is present, send the file using **all returned headers**. For this PDF request the service currently returns `Content-Type` and `x-oss-forbid-overwrite`:

```bash
curl --fail-with-body --silent --show-error \
  --request PUT "$(jq -er '.put_url' upload.json)" \
  -H "Content-Type: $(jq -er '.headers["Content-Type"]' upload.json)" \
  -H "x-oss-forbid-overwrite: $(jq -er '.headers["x-oss-forbid-overwrite"]' upload.json)" \
  --data-binary @document.pdf
```

Uploading the file does not require an API key. If the response contains `get_url` and `head_url`, the file has already been uploaded and you can continue to the next step.

Uploaded files cannot be overwritten. If the upload link expires before you use it, request a new one.

## Start conversion

```bash
curl --fail-with-body --silent --show-error \
  "$BASE/transforms/$TASK_UUID/launch" \
  -H "Authorization: Bearer $PDF_CRAFT_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"output_format":"markdown"}'
```

The service returns `202` when it accepts the launch request. Repeating the same parameters returns `200` without running another conversion; changing them returns `409`. For translation or EPUB output, see [parameters](https://pdfcraft.ai/docs/api/conversion/).

## Check status

```bash
curl --fail-with-body --silent --show-error \
  "$BASE/transforms/$TASK_UUID" \
  -H "Authorization: Bearer $PDF_CRAFT_API_KEY"
```

While the status is `running`, wait before checking again. In your application, gradually increase the interval between requests and set an overall timeout, as in the Python example.

Stop polling when the status becomes `succeeded`, `failed` or `cancelled`. For failures, read `error.code`; calling launch again will not restart the task. To display processing progress, see [progress and previews](https://pdfcraft.ai/docs/api/preview/).

## Download after success

Only after `status` becomes `succeeded`:

```bash
curl --fail-with-body --silent --show-error \
  "$BASE/transforms/$TASK_UUID/download-urls" \
  -H "Authorization: Bearer $PDF_CRAFT_API_KEY" \
  --output download.json
curl --fail --silent --show-error \
  "$(jq -er '.get_url' download.json)" \
  --output result.markdown.zip
```

Downloading the file does not require an API key. To inspect file information with a HEAD request, use `head_url`.

If the download link expires, you can request a new one. Once the task expires, the file is no longer available for download, so save your result in time.
