Convert a document

POST/v1/convertRequires an API key

Converts one document. In the default synchronous mode the answer contains the result; with mode=async it returns a job to follow. See the guides on output formats, schema extraction, scans and images, asynchronous jobs and webhooks.

Request

The body is multipart/form-data.

Field Type Required Description
file file yes The document: PDF, DOCX, RTF, TXT, CSV, LOG or an image. Up to 50 MB
format text no json (default), markdown or html. Not case sensitive
mode text no sync (default) or async
schema text no A JSON Schema as a JSON string. Used only with format=json
webhook_url text no An http(s) URL called when an async job ends

Header: Authorization: Bearer <API key>.

Response

Synchronous (200)

Field Type Description
success boolean true
mode string sync
document object file_name, file_type, pages, characters, processing_time_ms, ocr_applied
output_format string The format returned
data object or string The result: an object for json, a string for markdown and html
schema_applied boolean true when the AI extraction produced data that conforms to your schema; false means data is not a verified match
ocr_applied boolean true when the document was read with OCR
input_truncated boolean true when the text was longer than the 25,000 characters sent to the extractor
{
  "success": true,
  "mode": "sync",
  "document": {
    "file_name": "invoice.pdf",
    "file_type": "application/pdf",
    "pages": 1,
    "characters": 214,
    "processing_time_ms": 412,
    "ocr_applied": false
  },
  "output_format": "json",
  "data": {"invoice_number": "INV-2847", "date": "2026-05-21", "total": 1240.0},
  "schema_applied": true,
  "ocr_applied": false,
  "input_truncated": false
}

Asynchronous (202 Accepted): the conversion continues in the background.

{
  "job_id": "3f2b8c1e-5d1c-4a7e-9a0b-0c1d2e3f4a5b",
  "status": "pending",
  "message": "Document conversion job accepted and queued for processing.",
  "status_url": "/v1/jobs/3f2b8c1e-5d1c-4a7e-9a0b-0c1d2e3f4a5b",
  "webhook_url": null
}

Errors

Status When
400 Invalid format, mode, schema or webhook_url
401 Missing, wrong or revoked API key
402 Monthly page quota used up, or the document needs more pages than remain
413 File larger than 50 MB
422 file missing or the body is not valid multipart/form-data
429 Rate limit exceeded; see Retry-After
500 The document could not be processed (Document parsing error: …)
503 An image could not be read because the OCR provider is not answering; retry after Retry-After (60 seconds); no pages are charged. A scanned PDF does not fail this way: see Scanned documents and images

Examples

Convert a PDF to JSON
curl -s https://api.docslice.app/v1/convert \
  -H "Authorization: Bearer $DOCSLICE_API_KEY" \
  -F "file=@invoice.pdf" \
  -F "format=json"
import json
import os
import requests

api_key = os.environ["DOCSLICE_API_KEY"]

with open("invoice.pdf", "rb") as handle:
    response = requests.post(
        "https://api.docslice.app/v1/convert",
        headers={"Authorization": f"Bearer {api_key}"},
        files={"file": ("invoice.pdf", handle, "application/pdf")},
        data={"format": "json"},
        timeout=120,
    )

print(json.dumps(response.json(), indent=2))
const fs = require("node:fs");

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
form.append("format", "json");

fetch("https://api.docslice.app/v1/convert", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.DOCSLICE_API_KEY}` },
  body: form,
})
  .then((response) => response.json())
  .then((data) => console.log(JSON.stringify(data, null, 2)));
<?php
$curl = curl_init('https://api.docslice.app/v1/convert');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('DOCSLICE_API_KEY')],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('invoice.pdf', 'application/pdf', 'invoice.pdf'),
        'format' => 'json',
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
]);
echo curl_exec($curl);
curl_close($curl);
Convert a PDF to Markdown
curl -s https://api.docslice.app/v1/convert \
  -H "Authorization: Bearer $DOCSLICE_API_KEY" \
  -F "file=@invoice.pdf" \
  -F "format=markdown"
import json
import os
import requests

api_key = os.environ["DOCSLICE_API_KEY"]

with open("invoice.pdf", "rb") as handle:
    response = requests.post(
        "https://api.docslice.app/v1/convert",
        headers={"Authorization": f"Bearer {api_key}"},
        files={"file": ("invoice.pdf", handle, "application/pdf")},
        data={"format": "markdown"},
        timeout=120,
    )

print(json.dumps(response.json(), indent=2))
const fs = require("node:fs");

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
form.append("format", "markdown");

fetch("https://api.docslice.app/v1/convert", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.DOCSLICE_API_KEY}` },
  body: form,
})
  .then((response) => response.json())
  .then((data) => console.log(JSON.stringify(data, null, 2)));
<?php
$curl = curl_init('https://api.docslice.app/v1/convert');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('DOCSLICE_API_KEY')],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('invoice.pdf', 'application/pdf', 'invoice.pdf'),
        'format' => 'markdown',
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
]);
echo curl_exec($curl);
curl_close($curl);
Extract fields with a JSON Schema
SCHEMA='{"type":"object","properties":{"invoice_number":{"type":"string","description":"Invoice number"},"date":{"type":"string","description":"Issue date, YYYY-MM-DD"},"total":{"type":"number","description":"Total amount"}},"required":["invoice_number","total"]}'

curl -s https://api.docslice.app/v1/convert \
  -H "Authorization: Bearer $DOCSLICE_API_KEY" \
  -F "file=@invoice.pdf" \
  -F "format=json" \
  -F "schema=$SCHEMA"
import json
import os
import requests

api_key = os.environ["DOCSLICE_API_KEY"]
schema = {
    "type": "object",
    "properties": {
        "invoice_number": {"type": "string", "description": "Invoice number"},
        "date": {"type": "string", "description": "Issue date, YYYY-MM-DD"},
        "total": {"type": "number", "description": "Total amount"},
    },
    "required": ["invoice_number", "total"],
}

with open("invoice.pdf", "rb") as handle:
    response = requests.post(
        "https://api.docslice.app/v1/convert",
        headers={"Authorization": f"Bearer {api_key}"},
        files={"file": ("invoice.pdf", handle, "application/pdf")},
        data={"format": "json", "schema": json.dumps(schema)},
        timeout=120,
    )

print(json.dumps(response.json(), indent=2))
const fs = require("node:fs");

const schema = {
  type: "object",
  properties: {
    invoice_number: { type: "string", description: "Invoice number" },
    date: { type: "string", description: "Issue date, YYYY-MM-DD" },
    total: { type: "number", description: "Total amount" },
  },
  required: ["invoice_number", "total"],
};

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
form.append("format", "json");
form.append("schema", JSON.stringify(schema));

fetch("https://api.docslice.app/v1/convert", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.DOCSLICE_API_KEY}` },
  body: form,
})
  .then((response) => response.json())
  .then((data) => console.log(JSON.stringify(data, null, 2)));
<?php
$schema = [
    'type' => 'object',
    'properties' => [
        'invoice_number' => ['type' => 'string', 'description' => 'Invoice number'],
        'date' => ['type' => 'string', 'description' => 'Issue date, YYYY-MM-DD'],
        'total' => ['type' => 'number', 'description' => 'Total amount'],
    ],
    'required' => ['invoice_number', 'total'],
];

$curl = curl_init('https://api.docslice.app/v1/convert');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('DOCSLICE_API_KEY')],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('invoice.pdf', 'application/pdf', 'invoice.pdf'),
        'format' => 'json',
        'schema' => json_encode($schema),
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
]);
echo curl_exec($curl);
curl_close($curl);
Start an asynchronous conversion
curl -s https://api.docslice.app/v1/convert \
  -H "Authorization: Bearer $DOCSLICE_API_KEY" \
  -F "file=@invoice.pdf" \
  -F "format=json" \
  -F "mode=async"
import json
import os
import requests

api_key = os.environ["DOCSLICE_API_KEY"]

with open("invoice.pdf", "rb") as handle:
    response = requests.post(
        "https://api.docslice.app/v1/convert",
        headers={"Authorization": f"Bearer {api_key}"},
        files={"file": ("invoice.pdf", handle, "application/pdf")},
        data={"format": "json", "mode": "async"},
        timeout=120,
    )

print(response.status_code)  # 202: accepted, the work continues in the background
print(json.dumps(response.json(), indent=2))
const fs = require("node:fs");

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
form.append("format", "json");
form.append("mode", "async");

fetch("https://api.docslice.app/v1/convert", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.DOCSLICE_API_KEY}` },
  body: form,
}).then(async (response) => {
  console.log(response.status); // 202: accepted, the work continues in the background
  console.log(JSON.stringify(await response.json(), null, 2));
});
<?php
$curl = curl_init('https://api.docslice.app/v1/convert');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('DOCSLICE_API_KEY')],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('invoice.pdf', 'application/pdf', 'invoice.pdf'),
        'format' => 'json',
        'mode' => 'async',
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_RESPONSE_CODE) . PHP_EOL; // 202: accepted, the work continues in the background
echo $body;
curl_close($curl);