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. Keys look like
ad_live_… once self-serve issuance is live. Until then, keys are issued manually —
request one via /signup or email.
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. Kashida elongation is unsupported (Chromium).
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
Node
Python
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).