Reference
API docs
Base URL: https://api.arabdoc.dev. One authenticated endpoint renders a PDF from JSON.
Authentication
Send your key on every render request as X-API-Key. Free keys are self-serve at
/signup (POST /v1/signup/free). Keys look like
ad_live_… and are shown once at creation.
X-API-Key: ad_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
POST /v1/render
Request JSON body. Response is application/pdf on success.
{
"template": "invoice",
"data": { /* template schema */ },
"options": {
"numerals": "western",
"calendar": "dual",
"justify": false
}
}
Options
| Field | Type | Notes |
|---|---|---|
numerals |
"western" | "arabic-indic" |
Optional. Controls digit shaping in dates and amounts. |
calendar |
"gregorian" | "hijri" | "dual" |
Optional. Dual prints Hijri + Gregorian (Asia/Riyadh). |
justify |
boolean |
Optional, default false. Chromium cannot do true Arabic kashida; leave
false for text-align: right. See
limitations.
|
Template schemas
All objects are strict — unknown fields are rejected.
invoice
| Field | Type |
|---|---|
| invoiceNumber, issueDate, supplyDate, currency | string |
| seller, buyer | { name, address, city, vatNumber, email?, crNumber? } |
| items[] | { description, sku?, quantity, unitPrice, lineTotal } · max 200 |
| subtotal, vatRate, vatAmount, total | number |
| notes?, font? | string / font id |
contract
| Field | Type |
|---|---|
| title, contractNumber, signedDate, city, currency | string |
| partyA, partyB | { name, address, crNumber, email? } |
| lineItems[] | { label, description, amount } · max 200 |
| clauses[] | { number, text } |
| governingLaw?, font? | string / font id |
certificate
| Field | Type |
|---|---|
| title, subtitle, issuerName, recipientName, bodyText | string |
| certificateNumber, issueDate, signatoryName, signatoryTitle, city | string |
| courseCode?, font? | string / font id |
letter
| Field | Type |
|---|---|
| referenceNumber, letterDate, subject, salutation, closing | string |
| sender | { orgName, department, address, email?, signatoryName, signatoryTitle } |
| recipient | { name, title?, orgName? } |
| bodyParagraphs[] | string[] |
| font? | font id |
report
| Field | Type |
|---|---|
| title, subtitle, orgName, periodLabel, reportDate, reportNumber, authorName, executiveSummary | string |
| authorEmail? | string |
| metrics[] | { name, code, value, unit, change } |
| sections[] | { heading, body } |
| font? | font id |
Font ids: amiri, noto-naskh-arabic, ibm-plex-sans-arabic,
cairo, tajawal.
Error codes
Errors are JSON: { "error": { "code", "message", "details?" } }.
| HTTP | code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 400 | VALIDATION_ERROR | Bad body / template data |
| 400 | UNKNOWN_TEMPLATE | Template name not in the five |
| 400 | LIMIT_EXCEEDED | >50 pages or line caps |
| 413 | PAYLOAD_TOO_LARGE | Body > 1 MB |
| 429 | RATE_LIMITED | Per-minute or daily cap · Retry-After |
| 500 | INTERNAL_ERROR | Unexpected failure |
Examples
curl -X POST https://api.arabdoc.dev/v1/render \
-H "X-API-Key: $ARABDOC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "letter",
"data": {
"referenceNumber": "LTR-100",
"letterDate": "2026-08-08",
"sender": {
"orgName": "شركة المثال",
"department": "الموارد البشرية",
"address": "الرياض",
"signatoryName": "فهد العتيبي",
"signatoryTitle": "مدير"
},
"recipient": { "name": "نورة الشمري" },
"subject": "تأكيد موعد",
"salutation": "تحية طيبة،",
"bodyParagraphs": ["نود تأكيد موعد الاجتماع يوم الأحد."],
"closing": "وتفضلوا بقبول فائق الاحترام"
},
"options": { "numerals": "western", "calendar": "dual" }
}' \
-o letter.pdf
const res = await fetch("https://api.arabdoc.dev/v1/render", {
method: "POST",
headers: {
"X-API-Key": process.env.ARABDOC_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
template: "invoice",
data: invoicePayload,
options: { numerals: "western", calendar: "dual" },
}),
});
if (!res.ok) throw new Error(await res.text());
const pdf = Buffer.from(await res.arrayBuffer());
await fs.writeFile("invoice.pdf", pdf);
import os, requests
r = requests.post(
"https://api.arabdoc.dev/v1/render",
headers={
"X-API-Key": os.environ["ARABDOC_API_KEY"],
"Content-Type": "application/json",
},
json={
"template": "report",
"data": report_payload,
"options": {"numerals": "western", "calendar": "dual"},
},
timeout=60,
)
r.raise_for_status()
open("report.pdf", "wb").write(r.content)
Limits
-
Body size
1 MB max request body.
-
Line items
200 max on invoice/contract arrays.
-
Pages
50 pages max per PDF.
-
Rate
60 requests/minute per key. Monthly quota by tier (Free 100 · $29 2k · $99 10k · $299 50k).
-
Product constraints
No kashida justification (Chromium), five templates only, no custom upload / DOCX / ZATCA — details and workarounds on the landing page.