Documents API
Generate PDF and Excel documents programmatically from your templates.
Overview
The Documents API allows you to:
- Generate single documents from templates
- Batch generate multiple documents
- Track generation job status
- Download generated documents via signed URLs
Authentication
All endpoints require authentication via API key:
Authorization: Bearer YOUR_API_KEY
Generate Document
Generate a single document from a template.
POST /api/v1/documents/generate
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | Template ID (UUID, shortId, or slug) |
format | string | Yes | Output format: pdf or xlsx |
variables | object | No | Template variables |
filename | string | No | Custom filename (without extension) |
metadata | object | No | Custom metadata to attach |
useCredit | boolean | No | Force use of premium credits instead of free quota. Documents generated with credits have no watermark. Default: false |
Example Request
curl -X POST https://api.rynko.dev/v1/documents/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tmpl_invoice",
"format": "pdf",
"variables": {
"invoiceNumber": "INV-2025-001",
"customerName": "Acme Corporation",
"amount": 1250.00,
"lineItems": [
{"description": "Consulting", "quantity": 10, "price": 100},
{"description": "Development", "quantity": 5, "price": 50}
]
},
"filename": "invoice-2025-001"
}'
Response
Document generation is an async operation. The initial response returns job info with queued status:
{
"jobId": "job_abc123def456",
"status": "queued",
"statusUrl": "https://api.rynko.dev/api/v1/documents/jobs/job_abc123def456",
"estimatedWaitSeconds": 5
}
To get the download URL, poll the job status endpoint or use webhooks.
Response Fields
| Field | Type | Description |
|---|---|---|
jobId | string | Unique job identifier |
status | string | Job status: queued for new requests |
statusUrl | string | URL to check job status |
estimatedWaitSeconds | number | Estimated time until completion |
Batch Generate
Generate multiple documents in a single request.
POST /api/v1/documents/generate/batch
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | Template ID |
format | string | Yes | Output format: pdf or xlsx |
documents | array | Yes | Array of document specifications |
documents[].variables | object | Yes | Variables for this document |
documents[].filename | string | No | Custom filename |
documents[].metadata | object | No | Custom metadata |
useCredit | boolean | No | Force use of premium credits instead of free quota. Documents generated with credits have no watermark. Default: false |
Example Request
curl -X POST https://api.rynko.dev/v1/documents/generate/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tmpl_invoice",
"format": "pdf",
"documents": [
{
"variables": {"invoiceNumber": "INV-001", "customerName": "Acme Corp", "amount": 100},
"filename": "invoice-001"
},
{
"variables": {"invoiceNumber": "INV-002", "customerName": "Beta Inc", "amount": 200},
"filename": "invoice-002"
},
{
"variables": {"invoiceNumber": "INV-003", "customerName": "Gamma Ltd", "amount": 300},
"filename": "invoice-003"
}
]
}'
Response
{
"batchId": "batch_xyz789",
"status": "processing",
"totalDocuments": 3,
"completedDocuments": 0,
"failedDocuments": 0,
"createdAt": "2025-01-15T10:00:00Z"
}
Get Job Status
Check the status of a document generation job.
GET /api/v1/documents/jobs/:jobId
Example Request
curl https://api.rynko.dev/v1/documents/jobs/job_abc123def456 \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"jobId": "job_abc123def456",
"status": "completed",
"format": "pdf",
"templateId": "tmpl_invoice",
"downloadUrl": "https://storage.rynko.dev/documents/abc123.pdf?signature=...",
"expiresAt": "2025-01-15T12:00:00Z",
"createdAt": "2025-01-15T10:00:00Z",
"completedAt": "2025-01-15T10:00:05Z"
}
Get Batch Status
Check the status of a batch generation.
GET /api/v1/documents/batches/:batchId
Example Request
curl https://api.rynko.dev/v1/documents/batches/batch_xyz789 \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"batchId": "batch_xyz789",
"status": "completed",
"totalDocuments": 3,
"completedDocuments": 3,
"failedDocuments": 0,
"documents": [
{
"jobId": "job_001",
"status": "completed",
"downloadUrl": "https://storage.rynko.dev/documents/001.pdf?signature=..."
},
{
"jobId": "job_002",
"status": "completed",
"downloadUrl": "https://storage.rynko.dev/documents/002.pdf?signature=..."
},
{
"jobId": "job_003",
"status": "completed",
"downloadUrl": "https://storage.rynko.dev/documents/003.pdf?signature=..."
}
],
"createdAt": "2025-01-15T10:00:00Z",
"completedAt": "2025-01-15T10:00:15Z"
}
List Jobs
List all document generation jobs.
GET /api/v1/documents/jobs
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 20 | Items per page (max 100) |
status | string | - | Filter by status |
templateId | string | - | Filter by template |
Example Request
curl "https://api.rynko.dev/v1/documents/jobs?limit=10&status=completed" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": [
{
"jobId": "job_abc123",
"status": "completed",
"format": "pdf",
"templateId": "tmpl_invoice",
"createdAt": "2025-01-15T10:00:00Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 150,
"totalPages": 15
}
}
Export Jobs
Export document job logs to CSV or JSON format.
GET /api/v1/documents/jobs/export
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | string | csv | Export format: csv or json |
startDate | string | - | Filter by start date |
endDate | string | - | Filter by end date |
status | string | - | Filter by status |
Response
Returns a file download with the exported data.
Retry Failed Job
Retry a failed document generation job.
POST /api/v1/documents/jobs/:jobId/retry
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId | string | Job ID to retry |
Response
{
"jobId": "job_new_abc123",
"status": "pending",
"message": "Job queued for retry"
}
Delete Job
Delete a single document job record.
DELETE /api/v1/documents/jobs/:jobId
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId | string | Job ID to delete |
Response
Returns 204 No Content on success.
Bulk Delete Jobs
Delete multiple document job records.
DELETE /api/v1/documents/jobs/bulk
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
jobIds | array | Yes | Array of job IDs to delete |
Example Request
{
"jobIds": ["job_001", "job_002", "job_003"]
}
Response
{
"deleted": 3,
"message": "Jobs deleted successfully"
}
Bulk Retry Jobs
Retry multiple failed document generation jobs.
POST /api/v1/documents/jobs/bulk/retry
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
jobIds | array | Yes | Array of job IDs to retry |
Example Request
{
"jobIds": ["job_001", "job_002", "job_003"]
}
Response
{
"queued": 3,
"message": "Jobs queued for retry"
}
Get Analytics
Get document generation analytics for your team.
GET /api/v1/documents/analytics
Query Parameters
| Parameter | Type | Description |
|---|---|---|
startDate | string | Filter by start date (ISO format) |
endDate | string | Filter by end date (ISO format) |
Example Request
curl "https://api.rynko.dev/api/v1/documents/analytics?startDate=2025-01-01&endDate=2025-01-31" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"totalDocuments": 1250,
"completedDocuments": 1200,
"failedDocuments": 50,
"byFormat": {
"pdf": 1000,
"xlsx": 250
},
"byDate": [
{"date": "2025-01-01", "count": 45},
{"date": "2025-01-02", "count": 52}
]
}
Job Statuses
| Status | Description |
|---|---|
pending | Job is queued |
processing | Document is being generated |
completed | Document ready for download |
failed | Generation failed (check errorMessage field) |
Error Codes
| Code | HTTP | Description |
|---|---|---|
ERR_TMPL_001 | 404 | Template not found |
ERR_TMPL_002 | 404 | Document template not found |
ERR_TMPL_008 | 400 | Template schema validation failed |
ERR_VALID_002 | 400 | Variable validation failed |
ERR_QUOTA_003 | 429 | Rate limit exceeded |
ERR_QUOTA_008 | 429 | Monthly document generation quota exceeded |
ERR_QUOTA_011 | 429 | Insufficient document credits |
ERR_LIMIT_001 | 400 | PDF page limit exceeded |
ERR_LIMIT_003 | 400 | Excel row limit exceeded |
ERR_LIMIT_007 | 400 | Loop iteration limit exceeded |
See Error Codes for the complete error code reference.
Code Examples
Node.js
import { Rynko } from '@rynko/sdk';
const client = new Rynko({ apiKey: process.env.RYNKO_API_KEY });
// Queue document generation (async operation)
const job = await client.documents.generate({
templateId: 'tmpl_invoice',
format: 'pdf',
variables: {
invoiceNumber: 'INV-2025-001',
customerName: 'Acme Corporation',
amount: 1250.00
},
metadata: {
orderId: 'ord_12345',
customerId: 'cust_67890'
}
});
console.log('Job ID:', job.jobId);
console.log('Status:', job.status); // 'queued'
// Wait for completion to get download URL
const completed = await client.documents.waitForCompletion(job.jobId);
console.log('Download URL:', completed.downloadUrl);
console.log('Metadata:', completed.metadata); // { orderId: 'ord_12345', ... }
Python
from rynko import Rynko
client = Rynko(api_key=os.environ['RYNKO_API_KEY'])
# Queue document generation (async operation)
job = client.documents.generate(
template_id='tmpl_invoice',
format='pdf',
variables={
'invoiceNumber': 'INV-2025-001',
'customerName': 'Acme Corporation',
'amount': 1250.00
},
metadata={
'orderId': 'ord_12345',
'customerId': 'cust_67890'
}
)
print(f"Job ID: {job['jobId']}")
print(f"Status: {job['status']}") # 'queued'
# Wait for completion to get download URL
completed = client.documents.wait_for_completion(job['jobId'])
print(f"Download URL: {completed['downloadUrl']}")
print(f"Metadata: {completed['metadata']}") # {'orderId': 'ord_12345', ...}
Java
import dev.rynko.Rynko;
import dev.rynko.models.GenerateRequest;
import dev.rynko.models.GenerateResult;
import java.util.Map;
Rynko client = new Rynko(System.getenv("RYNKO_API_KEY"));
// Queue document generation (async operation)
GenerateResult job = client.documents().generate(
GenerateRequest.builder()
.templateId("tmpl_invoice")
.format("pdf")
.variable("invoiceNumber", "INV-2025-001")
.variable("customerName", "Acme Corporation")
.variable("amount", 1250.00)
.metadata(Map.of("orderId", "ord_12345", "customerId", "cust_67890"))
.build()
);
System.out.println("Job ID: " + job.getJobId());
System.out.println("Status: " + job.getStatus()); // "queued"
// Wait for completion to get download URL
GenerateResult completed = client.documents().waitForCompletion(job.getJobId());
System.out.println("Download URL: " + completed.getDownloadUrl());
System.out.println("Metadata: " + completed.getMetadata()); // {orderId=ord_12345, ...}
Metadata
Attach custom metadata to document generation requests for tracking and correlation purposes. Metadata is passed through to API responses and webhook payloads.
Usage
Include a metadata object in your generate request:
{
"templateId": "tmpl_invoice",
"format": "pdf",
"variables": { ... },
"metadata": {
"orderId": "ord_12345",
"customerId": "cust_67890",
"source": "api",
"rowNumber": 42
}
}
Constraints
| Constraint | Value |
|---|---|
| Structure | Flat object (no nested objects) |
| Max size | 10 KB |
| Value types | string, number, boolean, null |
In Job Status Response
Metadata is included in job status responses:
{
"jobId": "job_abc123def456",
"status": "completed",
"format": "pdf",
"templateId": "tmpl_invoice",
"downloadUrl": "https://storage.rynko.dev/documents/abc123.pdf?signature=...",
"metadata": {
"orderId": "ord_12345",
"customerId": "cust_67890",
"source": "api",
"rowNumber": 42
},
"createdAt": "2025-01-15T10:00:00Z",
"completedAt": "2025-01-15T10:00:05Z"
}
In Webhook Payloads
Metadata is passed through to webhook events:
{
"id": "evt_abc123",
"type": "document.generated",
"timestamp": "2025-01-15T10:00:05Z",
"data": {
"jobId": "job_abc123def456",
"status": "completed",
"downloadUrl": "https://storage.rynko.dev/documents/abc123.pdf?signature=...",
"metadata": {
"orderId": "ord_12345",
"customerId": "cust_67890",
"source": "api",
"rowNumber": 42
}
}
}
Use Cases
- Order tracking: Link documents to orders in your system
- User attribution: Track which user triggered generation
- Batch correlation: Tag documents from the same batch run
- Source tracking: Identify where requests originated (API, webhook, Sheets Add-on)
- Custom identifiers: Store your internal IDs for later lookup
Batch Metadata
For batch generation, you can set metadata at the batch level (applies to all documents) or per-document:
{
"templateId": "tmpl_invoice",
"format": "pdf",
"metadata": {
"batchRunId": "run_20250115",
"triggeredBy": "scheduled_job"
},
"documents": [
{
"variables": { "invoiceNumber": "INV-001" },
"metadata": { "rowNumber": 1 }
},
{
"variables": { "invoiceNumber": "INV-002" },
"metadata": { "rowNumber": 2 }
}
]
}
Webhooks
Subscribe to document generation events:
| Event | Description |
|---|---|
document.generated | Document successfully generated |
document.failed | Document generation failed |
batch.completed | All documents in batch completed |
See Webhooks for setup instructions.