API Reference · REST

Alqari API Documentation

Alqari exposes a simple JSON-over-HTTPS REST API to upload documents, run OCR and extraction, validate results, ask questions, and automate workflows — for Arabic and English documents. All requests require an API key.

Base URL

https://api.alqari.sa

Authentication

Bearer <API_KEY>
Get an API key — free

Authentication

Create an API key (starts with qari_) from your dashboard, then send it in the Authorization header on every request. The full key is shown only once at creation. Never expose your key in client-side code or public repositories.

curl https://api.alqari.sa/documents \
  -H "Authorization: Bearer qari_••••••••••"

Treat your API key like a password. If it leaks, revoke it immediately from the dashboard and issue a new one.

Alternative: session token via sign-in

For end-user apps, sign in via POST /auth/login with email_or_phone and password to receive an access_token, used in the Authorization header the same way. Session tokens are short-lived — use a qari_ key for long-running server integrations.

curl -X POST https://api.alqari.sa/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "email_or_phone": "you@company.sa", "password": "••••••••" }'

A successful response returns: access_token, refresh_token, token_type, user_name, email, phone_number.

Base URL

All endpoints are relative to the base URL below. Always use HTTPS.

Production

https://api.alqari.sa

Rate Limits

Limits are applied per API key, and current status is returned in response headers on every request. Exceeding the limit returns 429 with a Retry-After header.

HeaderDescription
X-RateLimit-LimitMax requests allowed in the window
X-RateLimit-RemainingRequests remaining in the window
Retry-AfterSeconds to wait before retrying (on 429)

Errors

The API uses conventional HTTP status codes. Error bodies always contain a human-readable detail field.

CodeMeaning
400Bad request — invalid input or parameters
401Unauthorized — missing or invalid API key
403Forbidden — key lacks the required scope
404Not found — resource does not exist
422Validation error — see detail array
429Too many requests — rate limited
500Server error — retry later
// 401 Unauthorized
{
  "detail": "Invalid or missing API key"
}

// 422 Validation error
{
  "detail": [
    { "loc": ["body", "file"], "msg": "field required", "type": "missing" }
  ]
}

Upload & run OCR

POST/services/upload-ocr

Upload a PDF or image and run OCR in one step. Send as multipart/form-data and do not set the Content-Type header manually. Optional query params: skip_vlm, process_for_chat, output.

Request

curl -X POST "https://api.alqari.sa/services/upload-ocr?process_for_chat=true&output=markdown" \
  -H "Authorization: Bearer qari_••••••••••" \
  -F "file=@invoice_2024.pdf"

Response

{
  "document_id": "9xKpL3mN",
  "status": "completed"
}

OCR output

GET/services/ocr-output/:id/{format}

Retrieve the OCR result in the requested format once processing completes. Available formats: markdown, ocr (raw text), html, blocks, layout. To trigger OCR on a previously uploaded document: POST /services/ocr/:id.

Request

curl https://api.alqari.sa/services/ocr-output/9xKpL3mN/markdown \
  -H "Authorization: Bearer qari_••••••••••"

Response

{
  "document_id": "9xKpL3mN",
  "format": "markdown",
  "content": "# فاتورة ضريبية ..."
}

AI validation

POST/services/ai-validate

Run AI-powered validation rules against an already-processed document. Pass document_id and rules_text as query params. Results are not always perfect — have a human review critical outcomes.

Request

curl -X POST "https://api.alqari.sa/services/ai-validate?document_id=9xKpL3mN&rules_text=1.%20Check%20required%20fields" \
  -H "Authorization: Bearer qari_••••••••••"

Response

{
  "document_id": "9xKpL3mN",
  "results": [
    { "rule": "Check required fields", "passed": true },
    { "rule": "Validate dates", "passed": false, "note": "..." }
  ]
}

Ask a document

POST/services/chat/:id

Ask a natural-language question about a processed document (upload it with process_for_chat=true). You can optionally pass chat_history for multi-turn conversations.

Request

curl -X POST https://api.alqari.sa/services/chat/9xKpL3mN \
  -H "Authorization: Bearer qari_••••••••••" \
  -H "Content-Type: application/json" \
  -d '{ "message": "ما إجمالي الفاتورة؟" }'

Response

{
  "document_id": "9xKpL3mN",
  "question": "ما إجمالي الفاتورة؟",
  "answer": "إجمالي الفاتورة هو SAR 124,500.00",
  "tokens_used": { "input": 812, "output": 24 }
}

Run a workflow

POST/workflows/:id/run

Trigger a pre-defined automation workflow with a document_id or payload. To run by uploading a file directly, use POST /workflows/:id/run-upload (multipart, authenticated with a qari_ key). Track the run via GET /workflows/runs/:runId.

Request

curl -X POST https://api.alqari.sa/workflows/7dR2/run \
  -H "Authorization: Bearer qari_••••••••••" \
  -H "Content-Type: application/json" \
  -d '{ "document_id": "9xKpL3mN" }'

Response

{
  "run_id": "5Qm1",
  "workflow_id": "7dR2",
  "status": "running"
}

Webhooks

POST(your endpoint)

Add a Webhook node inside a workflow to POST run results to your own HTTPS endpoint. You can test your webhook URL before publishing via POST /workflows/webhooks/test-url, then read the last received payload via GET /workflows/webhooks/test/:token/last.

Request

POST https://your-app.com/webhooks/alqari
Content-Type: application/json

{
  "event": "workflow.run.completed",
  "workflow_id": "7dR2",
  "run_id": "5Qm1",
  "status": "completed"
}

Response

// Respond with 2xx to acknowledge receipt.

Using the API

Every endpoint is a standard REST call over HTTPS with JSON, so you can call it from any language. The examples below use cURL and Python (the requests library). Set the BASE and HEADERS variables once and reuse them.

# Reusable base URL + auth header
BASE="https://api.alqari.sa"
AUTH="Authorization: Bearer qari_••••••••••"

curl "$BASE/documents" -H "$AUTH"