Skip to content

Quickstart

The five-minute path from clone to first extraction. For depth on every step, see the full integration guide.

Required env (in .env):

Terminal window
POSTGRES_PASSWORD=<random>
MINIO_ROOT_USER=<random>
MINIO_ROOT_PASSWORD=<random>
ARTIFACT_SIGNING_SECRET=<random>
SESSION_SECRET=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
# Bootstrap the first platform admin
BOOTSTRAP_PLATFORM_ADMIN_ENABLED=true
BOOTSTRAP_PLATFORM_ADMIN_EMAIL=admin@yourcompany.com
BOOTSTRAP_PLATFORM_ADMIN_PASSWORD=<choose-one>
# Point the LLM row at a model server. These are first-boot seeds only.
LLM_URL=https://your-vllm.internal:8000
LLM_MODEL=qwen3-8b-instruct
LLM_BACKEND_KIND=vllm

For Ollama, OpenAI, Gemini, credentials, and runtime edits after first boot, see Infrastructure setup.

Terminal window
# Application + infra (no GPU model servers in stack):
docker compose -f docker/docker-compose.yml up -d
# Or include the bundled local PaddleOCR-VL + GLM-OCR servers
# (single-GPU, 24 GiB):
docker compose -f docker/docker-compose.yml \
-f docker/docker-compose.local-models.yaml up -d
Terminal window
curl http://localhost:8080/v1/health
{ "status": "ok", "components": { "database": true, "redis": true, "worker": true, "storage": true, "providers": { "paddleocr-vl": true, "glmocr-vl": true, "llm": true } }, "queue_depth": 0 }
Terminal window
docstack-admin tenant create --id acme --name "Acme Corp" \
--initial-admin-email admin@acme.com
docstack-admin user invite --tenant-id acme \
--email integrator@acme.com --role tenant_admin

Open the invite URL the CLI prints to set a password.

Terminal window
docstack-admin api-keys create --tenant-id acme \
--user-email integrator@acme.com --name backlog-sync
# → printed once: rk_<public>_<secret>

The secret is unrecoverable — capture it now.

Terminal window
API="http://localhost:8080"
KEY="rk_<public>_<secret>"
JOB=$(curl -s -X POST "$API/v1/documents" \
-H "Authorization: Bearer $KEY" \
-F "file=@invoice.pdf" \
| jq -r .job_id)
echo "submitted: $JOB"
Terminal window
while true; do
RESPONSE=$(curl -s -H "Authorization: Bearer $KEY" \
"$API/v1/documents/$JOB")
STATUS=$(echo "$RESPONSE" | jq -r .status)
echo "status: $STATUS"
case "$STATUS" in
completed|needs_review|rejected|failed) break ;;
esac
sleep 2
done
echo "$RESPONSE" | jq .canonical.markdown

That’s it. The response includes the full CanonicalOcrDocument (per-page blocks, tables, formulas, charts, seals) plus, if a template was applied, the structured extraction.parsed payload and any validation flags.