API Reference

Parse PDFs, Word documents, and images — then extract, audit, and translate the structured result. Everything you can do in the Playground is available over a simple REST API.

Authentication

Create an API key on your Account page, then send it with every request. Keys start with dxsk_ and are shown in full only once at creation.

Authorization: Bearer dxsk_...

# All endpoints below accept this header in place of a login session.

Quick Start

Upload a document → poll the job → get Markdown and structured elements with per-block positions.

import os, time, requests

API_KEY = os.environ["DOCXSTACK_API_KEY"]
BASE = "https://docxstack.com/api"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# 1. Upload a document and create a parse job
with open("contract.pdf", "rb") as f:
    r = requests.post(
        f"{BASE}/v1/parse",
        headers=HEADERS,
        files={"file": f},
        data={"parser_id": "pdf_fallback", "language": "en"},
    )
r.raise_for_status()
job_id = r.json()["job_id"]

# 2. Poll until the job completes
while True:
    job = requests.get(f"{BASE}/v1/jobs/{job_id}", headers=HEADERS).json()
    if job["status"] in ("done", "failed"):
        break
    time.sleep(2)

# 3. Use the result
print(job["markdown"])          # full document markdown
for el in job["elements"]:      # structured blocks with positions
    print(el["type"], el["page"], el["bbox"], el.get("content"))

Parse & Jobs

GET/v1/parsers

List available parsers and their input types. Parsers: pdf_fallback (digital PDF), docx (Word), paddleocr (images & scanned PDF).

POST/v1/parse

Multipart upload: file (pdf/docx/png/jpg), parser_id, language (optional, default zh). Returns job_id with status 202. Async — poll for the result.

1 credit / page
GET/v1/jobs

Your recent jobs (newest first, max 50): id, status, filename, size, pages, created_at.

GET/v1/jobs/{job_id}

Job status and result: markdown, elements, metadata. Polling is free — parse credits are charged once when the job completes.

GET/v1/jobs/{job_id}/file

The original uploaded file (inline, for previews or re-download).

GET/v1/jobs/{job_id}/extras

Previously saved extract / audit / translate results for the job ({} if none).

DELETE/v1/jobs/{job_id}

Delete the job, its results, and the uploaded file.

Document Intelligence

All three take the parse elements array. Add an optional job_id to save the result to that job's history.

POST/v1/extract

Rule-based field extraction. Body: {elements, schema: [{name, type, keywords?}], language?, job_id?}. Types: string | number | date | boolean | list. Returns fields, provenance (element indexes), confidence.

3 credits / page
POST/v1/extract/preview

Free preview of extraction (same body, no credits).

POST/v1/audit

Contract risk audit with a built-in Chinese + English clause pattern library (uncapped liability, unilateral termination, auto-renewal, IP assignment, and more). Returns findings with severity, quote, explanation, and element position.

5 credits / page
POST/v1/audit/preview

Free preview — scans the first 30 elements only.

POST/v1/translate

Translate elements to en | zh-CN | zh-TW (OpenCC for zh↔zh, MyMemory for zh↔en). Body: {elements, target_lang, job_id?}. Returns translated elements + markdown.

2 credits / page

Element Schema

Every parsed block is one element:

{
  "type": "heading | text | list | table | image",
  "page": 0,                    // 0-based page number
  "page_w": 595, "page_h": 842, // page size: PDF points, or image pixels
  "bbox": { "x0": 50, "y0": 32, "x1": 530, "y1": 260 },
  "content": "..."              // string; string[][] for tables
}

// DOCX files have no intrinsic layout: page is 0 and bbox is null.
// PaddleOCR coordinates are image pixels; pdfplumber uses PDF points.

Credits & Errors

GET/v1/credits/balance

Current credit balance (also visible in the Nav bar when logged in).

  • 401 — missing or invalid API key / session.
  • 402 — insufficient credits; top up on the Pricing page.
  • 404 — job not found (or belongs to another account).
  • 413 — translation payload exceeds 8,000 characters.
  • 429-style — free translation API rate limits may return the source text; retry later.