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.
Overview
Section titled “Overview”The /v1/create endpoint is the fastest path to a PDF. It supports three input methods:
- Data + Template — Send structured JSON. Glyph renders it with a built-in template or auto-detects the document type and generates a layout.
- Raw HTML — Send an HTML string. Glyph renders it directly to PDF via Playwright.
- 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.
Input Methods
Section titled “Input Methods”Data + Template
Section titled “Data + Template”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"}Raw HTML
Section titled “Raw HTML”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.
URL Capture
Section titled “URL Capture”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.
Request
Section titled “Request”Headers
Section titled “Headers”| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer gk_your_api_key |
Content-Type | Yes | application/json |
Accept | No | application/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"}Parameters
Section titled “Parameters”At least one of data, html, or url must be provided.
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | Conditional | Your data in any JSON structure. Must have at least one key. Required unless html or url is provided. |
html | string | Conditional | Raw HTML string to convert to PDF. No template needed. Required unless data or url is provided. |
url | string | Conditional | URL to capture as PDF. The page is rendered in a full browser and converted. Required unless data or html is provided. |
templateId | string | No | Template 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. |
intent | string | No | Natural language description of what you want (e.g., "professional invoice", "Stripe-styled proposal"). Used with the data path only. |
style | string | No | Style preset: stripe-clean, bold, minimal, corporate. Used with the data path only. |
format | string | No | Output format: pdf (default) or png |
ttl | number | No | Time-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. |
options | object | No | Rendering options (see below) |
Options
Section titled “Options”| Option | Type | Description |
|---|---|---|
options.pageSize | string | A4, letter (default), or legal |
options.orientation | string | portrait (default) or landscape |
options.margin | object | Custom margins: { top, bottom, left, right } as CSS strings |
options.scale | number | Scale factor (0.1 to 3, default: 1) |
Response
Section titled “Response”JSON Response
Section titled “JSON Response”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" }}| Field | Type | Description |
|---|---|---|
success | boolean | Whether generation succeeded |
format | string | Output format (pdf or png) |
url | string | Base64 data URL of the generated file |
size | number | File size in bytes |
filename | string | Suggested filename |
expiresAt | string | ISO timestamp (24 hours from generation) |
analysis | object | How Glyph interpreted your data (only present when using the data input path) |
analysis.detectedType | string | Detected document type |
analysis.confidence | number | Detection confidence (0 to 1) |
analysis.fieldsIdentified | array | Field categories found in your data |
analysis.layoutDecisions | array | Layout choices made during generation |
source | object | Input method used: { type: "template", templateId }, { type: "html" }, or { type: "url", url } |
sessionId | string | Session ID for subsequent /v1/modify and /v1/generate calls |
_links | object | Hypermedia links for next actions |
Raw File Response
Section titled “Raw File Response”When the Accept header matches the output content type (e.g., application/pdf), the response is the raw binary file:
Headers:
Content-Type: application/pdfContent-Disposition: attachment; filename="glyph-invoice-1706000000000.pdf"Content-Length: 45678X-Glyph-Session-Id: 550e8400-e29b-41d4-a716-446655440000X-Glyph-Document-Type: invoiceBody: Binary PDF or PNG data
Document Type Detection
Section titled “Document Type Detection”Glyph automatically detects the document type from your data:
| Type | Detection Signals |
|---|---|
invoice | items + total + tax, dueDate, invoiceNumber |
quote | items + total + validUntil, quoteNumber |
receipt | items + paid, transactionId, paymentMethod |
report | summary, metrics, analysis, findings |
certificate | awarded, completion, certifiedTo |
letter | recipient, sender, body, salutation |
contract | contract, agreement, terms, signature, parties |
Code Examples
Section titled “Code Examples”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" }'cURL (Download raw PDF)
Section titled “cURL (Download raw PDF)”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.pdfcURL (Raw HTML to PDF)
Section titled “cURL (Raw HTML to PDF)”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.pdfcURL (URL to PDF)
Section titled “cURL (URL to PDF)”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.pdfcURL (Custom TTL - 7 days)
Section titled “cURL (Custom TTL - 7 days)”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.pdfJavaScript
Section titled “JavaScript”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-generateawait 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' })});Python
Section titled “Python”import requestsimport 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 URLdata_url = result['url']base64_data = data_url.split(',')[1]with open('invoice.pdf', 'wb') as f: f.write(base64.b64decode(base64_data))Analysis-Only Endpoint
Section titled “Analysis-Only Endpoint”To see how Glyph interprets your data without generating a document:
POST /v1/create/analyze
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." ] }}Error Responses
Section titled “Error Responses”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" }}Tips for Best Results
Section titled “Tips for Best Results”- Use descriptive field names: Names like
customer,total,itemsare recognized automatically - Include line items as arrays: Use arrays for products, services, or items
- Add context fields: Include
invoiceNumber,date,dueDateto improve detection - Use the
intentparameter: A short description like"professional invoice"helps Glyph make better layout decisions - Choose a style: The
styleparameter gives you control over the visual output without writing CSS
Next Steps
Section titled “Next Steps”- POST /v1/modify - Make AI-powered changes to a generated document
- POST /v1/generate - Re-generate after modifications
- Templates Overview - Browse available document templates
- MCP Server - Use with AI coding assistants