Docrya API
Generate PDFs from your templates with a single HTTP request. Internal operator docs live in the repository under docs/internal/.
Create your account
Sign up to get a workspace where templates and API keys live.
Create a template
In the dashboard, open Templates and create a document template. Publish a version when you are ready—render requests use the template templateId (UUID) and optionally templateVersion (positive integer). You can copy the template id from the URL or the template detail UI.
Customize your template
In the template editor, layouts use commercial_document_v1: you define line item columns with a stable key and a display label. Required keys are description, quantity, unit_price, and line_total. You may add up to three optional columns: custom_1, custom_2, custom_3 (for example “SKU” or “Unit”).
If a custom column appears in the layout, every row in data.items must include that field (string or number), or validation will fail.
Full JSON schema for layouts: docs/LAYOUT-SCHEMA-V1.md in the repository.
Generate an API key
From the dashboard, open the API card, generate a key, and copy it immediately—plaintext is shown only once. Store it in a secret manager or environment variable.
- Dashboard → API card → Generate API key
- Copy from the one-time modal
- Send it as
Authorization: Bearer <api_key>orX-API-Key
Request body (POST /api/v1/render)
Authenticate every request. The response body is a PDF (application/pdf).
- Headers:
Content-Type: application/json, plus Bearer orX-API-Keyas above templateId: UUID of the templatetemplateVersion: optional; omit to let the server resolve the active versiondata: structured payload for the layout (company, client, line items, summary, optional order number and filename)
Example below includes custom_1 on the line item—use it only when your template layout defines that column.
{
"templateId": "00000000-0000-4000-8000-000000000001",
"templateVersion": 1,
"data": {
"company": {
"name": "Acme Corp",
"cnpj": "12.345.678/0001-99",
"logo_url": null,
"address": "123 Market St, Suite 100"
},
"client": {
"name": "Jane Customer",
"document": "ID-99281",
"phone": "+1 555-0100"
},
"items": [
{
"description": "Consulting hours",
"quantity": 2,
"unit_price": 150,
"total": 300,
"custom_1": "SKU-42"
}
],
"summary": {
"subtotal": 300,
"discount": 0,
"total": 300,
"notes": "Thank you for your business."
},
"order_number": "SO-1001",
"filename": "sales-order.pdf"
}
}Code examples
Replace https://your-domain.com, YOUR_API_KEY, and templateId in the JSON with your deployment URL, key, and template UUID. For local development, use http://localhost:3000.
cURL
curl -sS -X POST "https://your-domain.com/api/v1/render" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"templateId":"00000000-0000-4000-8000-000000000001","templateVersion":1,"data":{"company":{"name":"Acme Corp","cnpj":"12.345.678/0001-99","logo_url":null,"address":"123 Market St, Suite 100"},"client":{"name":"Jane Customer","document":"ID-99281","phone":"+1 555-0100"},"items":[{"description":"Consulting hours","quantity":2,"unit_price":150,"total":300,"custom_1":"SKU-42"}],"summary":{"subtotal":300,"discount":0,"total":300,"notes":"Thank you for your business."},"order_number":"SO-1001","filename":"sales-order.pdf"}}' \
--output document.pdfJavaScript (fetch)
const BASE_URL = "https://your-domain.com" // or http://localhost:3000 in development
const API_KEY = "YOUR_API_KEY"
const body = {
"templateId": "00000000-0000-4000-8000-000000000001",
"templateVersion": 1,
"data": {
"company": {
"name": "Acme Corp",
"cnpj": "12.345.678/0001-99",
"logo_url": null,
"address": "123 Market St, Suite 100"
},
"client": {
"name": "Jane Customer",
"document": "ID-99281",
"phone": "+1 555-0100"
},
"items": [
{
"description": "Consulting hours",
"quantity": 2,
"unit_price": 150,
"total": 300,
"custom_1": "SKU-42"
}
],
"summary": {
"subtotal": 300,
"discount": 0,
"total": 300,
"notes": "Thank you for your business."
},
"order_number": "SO-1001",
"filename": "sales-order.pdf"
}
}
const res = await fetch(`${BASE_URL}/api/v1/render`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify(body),
})
if (!res.ok) {
const err = await res.text()
throw new Error(`Render failed: ${res.status} ${err}`)
}
const pdfBuffer = await res.arrayBuffer()
// Browser: save with Blob + object URL, or Node: fs.writeFileSync("out.pdf", Buffer.from(pdfBuffer))
Python (requests)
Install: pip install requests
import json
import requests
BASE_URL = "https://your-domain.com" # e.g. http://localhost:3000
API_KEY = "YOUR_API_KEY"
payload = json.loads(r"""
{
"templateId": "00000000-0000-4000-8000-000000000001",
"templateVersion": 1,
"data": {
"company": {
"name": "Acme Corp",
"cnpj": "12.345.678/0001-99",
"logo_url": null,
"address": "123 Market St, Suite 100"
},
"client": {
"name": "Jane Customer",
"document": "ID-99281",
"phone": "+1 555-0100"
},
"items": [
{
"description": "Consulting hours",
"quantity": 2,
"unit_price": 150,
"total": 300,
"custom_1": "SKU-42"
}
],
"summary": {
"subtotal": 300,
"discount": 0,
"total": 300,
"notes": "Thank you for your business."
},
"order_number": "SO-1001",
"filename": "sales-order.pdf"
}
}
""")
r = requests.post(
f"{BASE_URL}/api/v1/render",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
r.raise_for_status()
with open("document.pdf", "wb") as f:
f.write(r.content)