{ "openapi": "3.0.3", "info": { "title": "DocFast API", "version": "1.0.0", "description": "Convert HTML, Markdown, and URLs to pixel-perfect PDFs. Built-in invoice & receipt templates.\n\n## Authentication\nAll conversion and template endpoints require an API key via `Authorization: Bearer ` or `X-API-Key: ` header.\n\n## Rate Limits\n- Free tier: 100 PDFs/month, 10 req/min\n- Pro tier: 10,000 PDFs/month\n\n## Getting Started\n1. Sign up at [docfast.dev](https://docfast.dev) or via `POST /v1/signup/free`\n2. Verify your email with the 6-digit code\n3. Use your API key to convert documents", "contact": { "name": "DocFast", "url": "https://docfast.dev" } }, "servers": [{ "url": "https://docfast.dev", "description": "Production" }], "tags": [ { "name": "Conversion", "description": "Convert HTML, Markdown, or URLs to PDF" }, { "name": "Templates", "description": "Built-in document templates" }, { "name": "Account", "description": "Signup, key recovery, and email management" }, { "name": "Billing", "description": "Stripe-powered subscription management" }, { "name": "System", "description": "Health checks and usage stats" } ], "components": { "securitySchemes": { "BearerAuth": { "type": "http", "scheme": "bearer", "description": "API key as Bearer token" }, "ApiKeyHeader": { "type": "apiKey", "in": "header", "name": "X-API-Key", "description": "API key via X-API-Key header" } }, "schemas": { "PdfOptions": { "type": "object", "properties": { "format": { "type": "string", "enum": ["A4", "Letter", "Legal", "A3", "A5", "Tabloid"], "default": "A4", "description": "Page size" }, "landscape": { "type": "boolean", "default": false, "description": "Landscape orientation" }, "margin": { "type": "object", "properties": { "top": { "type": "string", "example": "20mm" }, "bottom": { "type": "string", "example": "20mm" }, "left": { "type": "string", "example": "15mm" }, "right": { "type": "string", "example": "15mm" } } }, "printBackground": { "type": "boolean", "default": true, "description": "Print background graphics" }, "filename": { "type": "string", "default": "document.pdf", "description": "Suggested filename for the PDF" } } }, "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Error message" } } } } }, "paths": { "/v1/convert/html": { "post": { "tags": ["Conversion"], "summary": "Convert HTML to PDF", "description": "Renders HTML content as a PDF. Supports full CSS including flexbox, grid, and custom fonts. Bare HTML fragments are auto-wrapped.", "security": [{ "BearerAuth": [] }, { "ApiKeyHeader": [] }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "allOf": [ { "type": "object", "required": ["html"], "properties": { "html": { "type": "string", "description": "HTML content to convert", "example": "

Hello World

Your first PDF

" }, "css": { "type": "string", "description": "Optional CSS to inject (for HTML fragments)" } } }, { "$ref": "#/components/schemas/PdfOptions" } ] } } } }, "responses": { "200": { "description": "PDF file", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid API key" }, "415": { "description": "Unsupported Content-Type" }, "429": { "description": "Rate limit exceeded or server busy" } } } }, "/v1/convert/markdown": { "post": { "tags": ["Conversion"], "summary": "Convert Markdown to PDF", "description": "Converts Markdown content to a beautifully styled PDF with syntax highlighting.", "security": [{ "BearerAuth": [] }, { "ApiKeyHeader": [] }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "allOf": [ { "type": "object", "required": ["markdown"], "properties": { "markdown": { "type": "string", "description": "Markdown content to convert", "example": "# Hello World\n\nThis is **bold** and this is *italic*.\n\n- Item 1\n- Item 2" }, "css": { "type": "string", "description": "Optional custom CSS" } } }, { "$ref": "#/components/schemas/PdfOptions" } ] } } } }, "responses": { "200": { "description": "PDF file", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Invalid request" }, "401": { "description": "Missing or invalid API key" }, "429": { "description": "Rate limit exceeded" } } } }, "/v1/convert/url": { "post": { "tags": ["Conversion"], "summary": "Convert URL to PDF", "description": "Fetches a URL and converts the rendered page to PDF. Only http/https URLs are supported. Private/reserved IPs are blocked (SSRF protection).", "security": [{ "BearerAuth": [] }, { "ApiKeyHeader": [] }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "allOf": [ { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "format": "uri", "description": "URL to convert", "example": "https://example.com" }, "waitUntil": { "type": "string", "enum": ["load", "domcontentloaded", "networkidle0", "networkidle2"], "default": "networkidle0", "description": "When to consider navigation complete" } } }, { "$ref": "#/components/schemas/PdfOptions" } ] } } } }, "responses": { "200": { "description": "PDF file", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Invalid URL or DNS failure" }, "401": { "description": "Missing or invalid API key" }, "429": { "description": "Rate limit exceeded" } } } }, "/v1/templates": { "get": { "tags": ["Templates"], "summary": "List available templates", "description": "Returns all available document templates with their field definitions.", "security": [{ "BearerAuth": [] }, { "ApiKeyHeader": [] }], "responses": { "200": { "description": "Template list", "content": { "application/json": { "schema": { "type": "object", "properties": { "templates": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "example": "invoice" }, "name": { "type": "string", "example": "Invoice" }, "description": { "type": "string" }, "fields": { "type": "array", "items": { "type": "string" } } } } } } } } } } } } }, "/v1/templates/{id}/render": { "post": { "tags": ["Templates"], "summary": "Render a template to PDF", "description": "Renders a template with the provided data and returns a PDF.", "security": [{ "BearerAuth": [] }, { "ApiKeyHeader": [] }], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Template ID (e.g., 'invoice', 'receipt')" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "object", "description": "Template data fields", "example": { "company": "Acme Corp", "items": [{ "description": "Widget", "quantity": 5, "price": 9.99 }] } } } } } } }, "responses": { "200": { "description": "PDF file", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "404": { "description": "Template not found" } } } }, "/v1/signup/free": { "post": { "tags": ["Account"], "summary": "Request a free API key", "description": "Sends a 6-digit verification code to your email. Use `/v1/signup/verify` to complete signup.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email", "example": "you@example.com" } } } } } }, "responses": { "200": { "description": "Verification code sent", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "verification_required" }, "message": { "type": "string" } } } } } }, "409": { "description": "Email already registered" }, "429": { "description": "Too many signup attempts" } } } }, "/v1/signup/verify": { "post": { "tags": ["Account"], "summary": "Verify email and get API key", "description": "Verify your email with the 6-digit code to receive your API key.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email", "code"], "properties": { "email": { "type": "string", "format": "email" }, "code": { "type": "string", "example": "123456", "description": "6-digit verification code" } } } } } }, "responses": { "200": { "description": "API key issued", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "verified" }, "apiKey": { "type": "string", "example": "df_free_abc123..." }, "tier": { "type": "string", "example": "free" } } } } } }, "400": { "description": "Invalid code" }, "410": { "description": "Code expired" }, "429": { "description": "Too many attempts" } } } }, "/v1/recover": { "post": { "tags": ["Account"], "summary": "Request API key recovery", "description": "Sends a verification code to your registered email. Returns the same response whether or not the email exists (prevents enumeration).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email" } } } } } }, "responses": { "200": { "description": "Recovery code sent (if account exists)" }, "429": { "description": "Too many recovery attempts" } } } }, "/v1/recover/verify": { "post": { "tags": ["Account"], "summary": "Verify recovery code and get API key", "description": "Verify the recovery code to retrieve your API key. The key is shown only in the response — never sent via email.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["email", "code"], "properties": { "email": { "type": "string", "format": "email" }, "code": { "type": "string", "example": "123456" } } } } } }, "responses": { "200": { "description": "API key recovered", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "recovered" }, "apiKey": { "type": "string" }, "tier": { "type": "string" } } } } } }, "400": { "description": "Invalid code" }, "410": { "description": "Code expired" }, "429": { "description": "Too many attempts" } } } }, "/v1/email-change": { "post": { "tags": ["Account"], "summary": "Request email change", "description": "Change the email associated with your API key. Sends a verification code to the new email address.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["apiKey", "newEmail"], "properties": { "apiKey": { "type": "string", "description": "Your current API key" }, "newEmail": { "type": "string", "format": "email", "description": "New email address" } } } } } }, "responses": { "200": { "description": "Verification code sent to new email" }, "400": { "description": "Invalid input" }, "401": { "description": "Invalid API key" }, "409": { "description": "Email already in use" }, "429": { "description": "Too many attempts" } } } }, "/v1/email-change/verify": { "post": { "tags": ["Account"], "summary": "Verify email change", "description": "Verify the code sent to your new email to complete the change.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["apiKey", "newEmail", "code"], "properties": { "apiKey": { "type": "string" }, "newEmail": { "type": "string", "format": "email" }, "code": { "type": "string", "example": "123456" } } } } } }, "responses": { "200": { "description": "Email updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "updated" }, "newEmail": { "type": "string" } } } } } }, "400": { "description": "Invalid code" }, "401": { "description": "Invalid API key" }, "410": { "description": "Code expired" } } } }, "/v1/billing/checkout": { "post": { "tags": ["Billing"], "summary": "Start Pro subscription checkout", "description": "Creates a Stripe Checkout session for the Pro plan ($9/mo). Returns a URL to redirect the user to.", "responses": { "200": { "description": "Checkout URL", "content": { "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" } } } } } }, "500": { "description": "Checkout creation failed" } } } }, "/v1/usage": { "get": { "tags": ["System"], "summary": "Get usage statistics", "description": "Returns your API usage statistics for the current billing period.", "security": [{ "BearerAuth": [] }, { "ApiKeyHeader": [] }], "responses": { "200": { "description": "Usage stats" } } } }, "/health": { "get": { "tags": ["System"], "summary": "Health check", "description": "Returns service health status. No authentication required.", "responses": { "200": { "description": "Service is healthy" } } } } } }