Skip to content

POST /v1/create - Stateless PDF Generation

POST /v1/create

Generate a professional PDF in a single API call. Send JSON data with a template, raw HTML, or a URL — Glyph handles the rest and returns a finished PDF or PNG.

One call. Beautiful document.

The /v1/create endpoint is the fastest path to a PDF. It supports three input methods:

  1. Data + Template — Send structured JSON. Glyph renders it with a built-in template or auto-detects the document type and generates a layout.
  2. Raw HTML — Send an HTML string. Glyph renders it directly to PDF via Playwright.
  3. URL Capture — Send a URL. Glyph navigates to the page and captures it as PDF.

All three paths return a PDF (or PNG) and a sessionId for subsequent AI-powered modifications.

Send structured JSON data with an optional templateId. If no template is specified, Glyph auto-detects the document type and generates a layout.

{
"templateId": "invoice-clean",
"data": {
"company": { "name": "Acme Inc" },
"customer": { "name": "Jane Doe" },
"items": [{ "description": "Consulting", "total": 1500 }],
"total": 1500
}
}

Without templateId, Glyph analyzes the data structure, detects the document type (invoice, receipt, contract, etc.), and generates a professional layout automatically:

{
"data": {
"company": { "name": "Acme Inc" },
"items": [{ "description": "Consulting", "total": 1500 }],
"total": 1500
},
"intent": "professional invoice",
"style": "stripe-clean"
}

Send any HTML string and Glyph renders it directly to PDF. No template needed.

{
"html": "<html><head><style>body { font-family: sans-serif; padding: 40px; } h1 { color: #1a1a1a; }</style></head><body><h1>Monthly Report</h1><p>Generated on 2026-01-15.</p></body></html>"
}

This is useful for converting existing HTML documents, email templates, or dynamically generated markup into PDFs.

Send a URL and Glyph navigates to the page, waits for it to render, and captures it as a PDF.

{
"url": "https://example.com/report/2026-q1"
}

The page is rendered with a full Chromium browser, so JavaScript-heavy pages, CSS layouts, and web fonts all work correctly.

HeaderRequiredDescription
AuthorizationYesBearer gk_your_api_key
Content-TypeYesapplication/json
AcceptNoapplication/json for JSON response with base64 data URL. Omit for raw binary file.
{
"data": {
"company": { "name": "Acme Inc", "email": "billing@acme.com" },
"customer": { "name": "John Doe", "email": "john@example.com" },
"items": [
{ "description": "Consulting", "hours": 10, "rate": 150, "total": 1500 }
],
"subtotal": 1500,
"tax": 120,
"total": 1620
},
"intent": "professional invoice",
"style": "stripe-clean",
"format": "pdf"
}

At least one of data, html, or url must be provided.

ParameterTypeRequiredDescription
dataobjectConditionalYour data in any JSON structure. Must have at least one key. Required unless html or url is provided.
htmlstringConditionalRaw HTML string to convert to PDF. No template needed. Required unless data or url is provided.
urlstringConditionalURL to capture as PDF. The page is rendered in a full browser and converted. Required unless data or html is provided.
templateIdstringNoTemplate to render data with (e.g., "invoice-clean", "contract-simple"). When omitted with data, Glyph auto-detects the document type. Ignored when using html or url. See GET /v1/templates for available IDs.
intentstringNoNatural language description of what you want (e.g., "professional invoice", "Stripe-styled proposal"). Used with the data path only.
stylestringNoStyle preset: stripe-clean, bold, minimal, corporate. Used with the data path only.
formatstringNoOutput format: pdf (default) or png
ttlnumberNoTime-to-live in seconds for the hosted document URL. Range: 300 (5 min) to 604800 (7 days). Default: 86400 (24 hours). Affects the expiresAt timestamp in the response.
optionsobjectNoRendering options (see below)
OptionTypeDescription
options.pageSizestringA4, letter (default), or legal
options.orientationstringportrait (default) or landscape
options.marginobjectCustom margins: { top, bottom, left, right } as CSS strings
options.scalenumberScale factor (0.1 to 3, default: 1)

When Accept: application/json is set (or the accept header does not match the output content type):

{
"success": true,
"format": "pdf",
"url": "data:application/pdf;base64,JVBERi0xLjQK...",
"size": 45678,
"filename": "glyph-invoice-1706000000000.pdf",
"expiresAt": "2026-01-29T12:00:00.000Z",
"analysis": {
"detectedType": "invoice",
"confidence": 0.95,
"fieldsIdentified": ["header", "recipient", "lineItems", "summary"],
"layoutDecisions": ["professional header", "table content", "summary summary"]
},
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"_links": {
"modify": "/v1/modify",
"generate": "/v1/generate"
}
}
FieldTypeDescription
successbooleanWhether generation succeeded
formatstringOutput format (pdf or png)
urlstringBase64 data URL of the generated file
sizenumberFile size in bytes
filenamestringSuggested filename
expiresAtstringISO timestamp (24 hours from generation)
analysisobjectHow Glyph interpreted your data (only present when using the data input path)
analysis.detectedTypestringDetected document type
analysis.confidencenumberDetection confidence (0 to 1)
analysis.fieldsIdentifiedarrayField categories found in your data
analysis.layoutDecisionsarrayLayout choices made during generation
sourceobjectInput method used: { type: "template", templateId }, { type: "html" }, or { type: "url", url }
sessionIdstringSession ID for subsequent /v1/modify and /v1/generate calls
_linksobjectHypermedia links for next actions

When the Accept header matches the output content type (e.g., application/pdf), the response is the raw binary file:

Headers:

Content-Type: application/pdf
Content-Disposition: attachment; filename="glyph-invoice-1706000000000.pdf"
Content-Length: 45678
X-Glyph-Session-Id: 550e8400-e29b-41d4-a716-446655440000
X-Glyph-Document-Type: invoice

Body: Binary PDF or PNG data

Glyph automatically detects the document type from your data:

TypeDetection Signals
invoiceitems + total + tax, dueDate, invoiceNumber
quoteitems + total + validUntil, quoteNumber
receiptitems + paid, transactionId, paymentMethod
reportsummary, metrics, analysis, findings
certificateawarded, completion, certifiedTo
letterrecipient, sender, body, salutation
contractcontract, agreement, terms, signature, parties
Terminal window
curl -X POST https://api.glyph.you/v1/create \
-H "Authorization: Bearer gk_your_api_key" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"data": {
"company": { "name": "Acme Inc", "email": "billing@acme.com" },
"customer": { "name": "John Doe", "email": "john@example.com" },
"items": [
{ "description": "Consulting", "hours": 10, "rate": 150, "total": 1500 },
{ "description": "Development", "hours": 20, "rate": 125, "total": 2500 }
],
"subtotal": 4000,
"tax": 320,
"total": 4320,
"invoiceNumber": "INV-2026-001",
"date": "2026-01-15",
"dueDate": "2026-02-15"
},
"intent": "professional invoice",
"style": "stripe-clean"
}'
Terminal window
curl -X POST https://api.glyph.you/v1/create \
-H "Authorization: Bearer gk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"company": { "name": "Acme Inc" },
"customer": { "name": "John Doe" },
"items": [{ "description": "Consulting", "total": 1500 }],
"total": 1500
}
}' \
--output invoice.pdf
Terminal window
curl -X POST https://api.glyph.you/v1/create \
-H "Authorization: Bearer gk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"html": "<html><head><style>body { font-family: Helvetica, sans-serif; padding: 40px; } h1 { color: #1a1a1a; }</style></head><body><h1>Quarterly Report</h1><p>Period: Q1 2026</p><table><tr><th>Metric</th><th>Value</th></tr><tr><td>Revenue</td><td>$1.2M</td></tr></table></body></html>"
}' \
--output report.pdf
Terminal window
curl -X POST https://api.glyph.you/v1/create \
-H "Authorization: Bearer gk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/invoice/12345"
}' \
--output captured.pdf
Terminal window
curl -X POST https://api.glyph.you/v1/create \
-H "Authorization: Bearer gk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"company": { "name": "Acme Inc" },
"customer": { "name": "John Doe" },
"items": [{ "description": "Consulting", "total": 1500 }],
"total": 1500
},
"ttl": 604800
}' \
--output invoice.pdf
const response = await fetch('https://api.glyph.you/v1/create', {
method: 'POST',
headers: {
'Authorization': 'Bearer gk_your_api_key',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
data: {
company: { name: 'Acme Inc' },
customer: { name: 'John Doe', email: 'john@example.com' },
items: [
{ description: 'Consulting', hours: 10, rate: 150, total: 1500 }
],
subtotal: 1500,
tax: 120,
total: 1620
},
intent: 'professional invoice',
style: 'stripe-clean'
})
});
const result = await response.json();
console.log(`Detected: ${result.analysis.detectedType} (${(result.analysis.confidence * 100).toFixed(0)}%)`);
console.log(`Size: ${result.size} bytes`);
console.log(`Session: ${result.sessionId}`);
// Optionally modify and re-generate
await fetch('https://api.glyph.you/v1/modify', {
method: 'POST',
headers: {
'Authorization': 'Bearer gk_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
sessionId: result.sessionId,
instruction: 'Add a QR code for payment'
})
});
import requests
import base64
response = requests.post(
'https://api.glyph.you/v1/create',
headers={
'Authorization': 'Bearer gk_your_api_key',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
json={
'data': {
'company': {'name': 'Acme Inc'},
'customer': {'name': 'John Doe', 'email': 'john@example.com'},
'items': [
{'description': 'Consulting', 'hours': 10, 'rate': 150, 'total': 1500}
],
'subtotal': 1500,
'tax': 120,
'total': 1620
},
'intent': 'professional invoice',
'style': 'stripe-clean'
}
)
result = response.json()
print(f"Detected: {result['analysis']['detectedType']}")
print(f"Size: {result['size']} bytes")
print(f"Session: {result['sessionId']}")
# Save the PDF from the base64 data URL
data_url = result['url']
base64_data = data_url.split(',')[1]
with open('invoice.pdf', 'wb') as f:
f.write(base64.b64decode(base64_data))

To see how Glyph interprets your data without generating a document:

POST /v1/create/analyze

Terminal window
curl -X POST https://api.glyph.you/v1/create/analyze \
-H "Authorization: Bearer gk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"items": [{"name": "Widget", "price": 99}],
"total": 99
},
"intent": "receipt"
}'

Response:

{
"success": true,
"analysis": {
"documentType": "receipt",
"confidence": 0.8,
"fields": {
"header": [...],
"recipient": [...],
"lineItems": [...],
"summary": [...],
"metadata": [...],
"footer": [...]
},
"layout": {
"headerStyle": "professional",
"contentStyle": "table",
"summaryStyle": "summary"
},
"styling": {
"suggestedStyle": "stripe-clean"
}
},
"recommendations": {
"suggestedStyle": "stripe-clean",
"suggestedLayout": "table",
"fieldsFound": 5,
"tips": [
"No recipient information found. Add 'customer', 'client', or 'recipient' fields for better document structure."
]
}
}

400 Bad Request - Validation failed

{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": [{ "path": ["data"], "message": "Data object cannot be empty" }]
}

401 Unauthorized - Invalid API key

{
"error": "Invalid API key",
"code": "AUTH_ERROR"
}

502 Bad Gateway - URL capture failed (only for the url input path)

{
"error": "Failed to fetch content from the provided URL",
"code": "URL_FETCH_FAILED",
"details": "..."
}

500 Internal Server Error - Analysis or generation failed

{
"error": "Could not analyze data structure",
"code": "ANALYSIS_FAILED",
"details": "..."
}
{
"error": "Failed to generate document",
"code": "GENERATION_FAILED",
"details": "..."
}

503 Service Unavailable - Playwright not installed

{
"error": "PDF generation not available. Playwright is not installed.",
"code": "PLAYWRIGHT_NOT_INSTALLED",
"details": {
"install": "bun add playwright && npx playwright install chromium"
}
}
  • Use descriptive field names: Names like customer, total, items are recognized automatically
  • Include line items as arrays: Use arrays for products, services, or items
  • Add context fields: Include invoiceNumber, date, dueDate to improve detection
  • Use the intent parameter: A short description like "professional invoice" helps Glyph make better layout decisions
  • Choose a style: The style parameter gives you control over the visual output without writing CSS