docfast/public/openapi.json
DocFast Bot 45b5be248c
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 11m58s
Promote to Production / Deploy to Production (push) Successful in 2m21s
docs: remove free tier, update rate limits and auth for demo+pro model
- Remove free tier from rate limits, add Demo (5/hour, watermarked)
- Update auth section: remove free-tier key mention, link to docfast.dev
- Update getting started: demo → upgrade to Pro → use API key
- Add deprecated: true to /v1/signup/free swagger annotation
- Regenerate openapi.json
2026-02-20 19:10:25 +00:00

1052 lines
No EOL
31 KiB
JSON

{
"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 <key>` or `X-API-Key: <key>` header.\n\n## Demo Endpoints\nTry the API without signing up! Demo endpoints are public (no API key needed) but rate-limited to 5 requests/hour per IP and produce watermarked PDFs.\n\n## Rate Limits\n- Demo: 5 PDFs/hour per IP (watermarked)\n- Pro tier: 5,000 PDFs/month, 30 req/min\n\n## Getting Started\n1. Try the demo at `POST /v1/demo/html` — no signup needed\n2. Subscribe to Pro at [docfast.dev](https://docfast.dev/#pricing) for clean PDFs\n3. Use your API key to convert documents",
"contact": {
"name": "DocFast",
"url": "https://docfast.dev",
"email": "support@docfast.dev"
}
},
"servers": [
{
"url": "https://docfast.dev",
"description": "Production"
}
],
"tags": [
{
"name": "Demo",
"description": "Try the API without signing up — watermarked PDFs, rate-limited"
},
{
"name": "Conversion",
"description": "Convert HTML, Markdown, or URLs to PDF (requires API key)"
},
{
"name": "Templates",
"description": "Built-in document templates"
},
{
"name": "Account",
"description": "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",
"description": "Top margin (e.g. \"10mm\", \"1in\")",
"default": "0"
},
"right": {
"type": "string",
"description": "Right margin",
"default": "0"
},
"bottom": {
"type": "string",
"description": "Bottom margin",
"default": "0"
},
"left": {
"type": "string",
"description": "Left margin",
"default": "0"
}
},
"description": "Page margins"
},
"printBackground": {
"type": "boolean",
"default": true,
"description": "Print background colors and images"
},
"filename": {
"type": "string",
"description": "Custom filename for Content-Disposition header",
"default": "document.pdf"
}
}
},
"Error": {
"type": "object",
"properties": {
"error": {
"type": "string",
"description": "Error message"
}
},
"required": [
"error"
]
}
}
},
"paths": {
"/v1/billing/checkout": {
"post": {
"tags": [
"Billing"
],
"summary": "Create a Stripe checkout session",
"description": "Creates a Stripe Checkout session for a Pro subscription (€9/month).\nReturns a URL to redirect the user to Stripe's hosted payment page.\nRate limited to 3 requests per hour per IP.\n",
"responses": {
"200": {
"description": "Checkout session created",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "Stripe Checkout URL to redirect the user to"
}
}
}
}
}
},
"413": {
"description": "Request body too large"
},
"429": {
"description": "Too many checkout requests"
},
"500": {
"description": "Failed to create checkout session"
}
}
}
},
"/v1/convert/html": {
"post": {
"tags": [
"Conversion"
],
"summary": "Convert HTML to PDF",
"description": "Converts HTML content to a PDF document. Bare HTML fragments are automatically wrapped in a full HTML document.",
"security": [
{
"BearerAuth": []
},
{
"ApiKeyHeader": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"allOf": [
{
"type": "object",
"required": [
"html"
],
"properties": {
"html": {
"type": "string",
"description": "HTML content to convert. Can be a full document or a fragment.",
"example": "<h1>Hello World</h1><p>My first PDF</p>"
},
"css": {
"type": "string",
"description": "Optional CSS to inject (only used when html is a fragment, not a full document)",
"example": "body { font-family: sans-serif; padding: 40px; }"
}
}
},
{
"$ref": "#/components/schemas/PdfOptions"
}
]
}
}
}
},
"responses": {
"200": {
"description": "PDF document",
"content": {
"application/pdf": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Missing html field"
},
"401": {
"description": "Missing API key"
},
"403": {
"description": "Invalid API key"
},
"415": {
"description": "Unsupported Content-Type (must be application/json)"
},
"429": {
"description": "Rate limit or usage limit exceeded"
},
"500": {
"description": "PDF generation failed"
}
}
}
},
"/v1/convert/markdown": {
"post": {
"tags": [
"Conversion"
],
"summary": "Convert Markdown to PDF",
"description": "Converts Markdown content to HTML and then to a PDF document.",
"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 *italic*."
},
"css": {
"type": "string",
"description": "Optional CSS to inject into the rendered HTML"
}
}
},
{
"$ref": "#/components/schemas/PdfOptions"
}
]
}
}
}
},
"responses": {
"200": {
"description": "PDF document",
"content": {
"application/pdf": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Missing markdown field"
},
"401": {
"description": "Missing API key"
},
"403": {
"description": "Invalid API key"
},
"415": {
"description": "Unsupported Content-Type"
},
"429": {
"description": "Rate limit or usage limit exceeded"
},
"500": {
"description": "PDF generation failed"
}
}
}
},
"/v1/convert/url": {
"post": {
"tags": [
"Conversion"
],
"summary": "Convert URL to PDF",
"description": "Fetches a URL and converts the rendered page to PDF. JavaScript is disabled for security.\nPrivate/internal IP addresses are blocked (SSRF protection). DNS is pinned to prevent rebinding.\n",
"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 (http or https only)",
"example": "https://example.com"
},
"waitUntil": {
"type": "string",
"enum": [
"load",
"domcontentloaded",
"networkidle0",
"networkidle2"
],
"default": "domcontentloaded",
"description": "When to consider navigation finished"
}
}
},
{
"$ref": "#/components/schemas/PdfOptions"
}
]
}
}
}
},
"responses": {
"200": {
"description": "PDF document",
"content": {
"application/pdf": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Missing/invalid URL or URL resolves to private IP"
},
"401": {
"description": "Missing API key"
},
"403": {
"description": "Invalid API key"
},
"415": {
"description": "Unsupported Content-Type"
},
"429": {
"description": "Rate limit or usage limit exceeded"
},
"500": {
"description": "PDF generation failed"
}
}
}
},
"/v1/demo/html": {
"post": {
"tags": [
"Demo"
],
"summary": "Convert HTML to PDF (demo)",
"description": "Public endpoint — no API key required. Rate limited to 5 requests per hour per IP.\nOutput PDFs include a DocFast watermark. Upgrade to Pro for clean output.\n",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"allOf": [
{
"type": "object",
"required": [
"html"
],
"properties": {
"html": {
"type": "string",
"description": "HTML content to convert",
"example": "<h1>Hello World</h1><p>My first PDF</p>"
},
"css": {
"type": "string",
"description": "Optional CSS to inject (used when html is a fragment)"
}
}
},
{
"$ref": "#/components/schemas/PdfOptions"
}
]
}
}
}
},
"responses": {
"200": {
"description": "Watermarked PDF document",
"content": {
"application/pdf": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Missing html field",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"415": {
"description": "Unsupported Content-Type"
},
"429": {
"description": "Demo rate limit exceeded (5/hour)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"503": {
"description": "Server busy"
},
"504": {
"description": "PDF generation timed out"
}
}
}
},
"/v1/demo/markdown": {
"post": {
"tags": [
"Demo"
],
"summary": "Convert Markdown to PDF (demo)",
"description": "Public endpoint — no API key required. Rate limited to 5 requests per hour per IP.\nMarkdown is converted to HTML then rendered to PDF with a DocFast watermark.\n",
"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 *italic*."
},
"css": {
"type": "string",
"description": "Optional CSS to inject"
}
}
},
{
"$ref": "#/components/schemas/PdfOptions"
}
]
}
}
}
},
"responses": {
"200": {
"description": "Watermarked PDF document",
"content": {
"application/pdf": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Missing markdown field"
},
"415": {
"description": "Unsupported Content-Type"
},
"429": {
"description": "Demo rate limit exceeded (5/hour)"
},
"503": {
"description": "Server busy"
},
"504": {
"description": "PDF generation timed out"
}
}
}
},
"/health": {
"get": {
"tags": [
"System"
],
"summary": "Health check",
"description": "Returns service health status including database connectivity and browser pool stats.",
"responses": {
"200": {
"description": "Service is healthy",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"degraded"
]
},
"version": {
"type": "string",
"example": "0.4.0"
},
"database": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"error"
]
},
"version": {
"type": "string",
"example": "PostgreSQL 17.4"
}
}
},
"pool": {
"type": "object",
"properties": {
"size": {
"type": "integer"
},
"active": {
"type": "integer"
},
"available": {
"type": "integer"
},
"queueDepth": {
"type": "integer"
},
"pdfCount": {
"type": "integer"
},
"restarting": {
"type": "boolean"
},
"uptimeSeconds": {
"type": "integer"
}
}
}
}
}
}
}
},
"503": {
"description": "Service is degraded (database issue)"
}
}
}
},
"/v1/recover": {
"post": {
"tags": [
"Account"
],
"summary": "Request API key recovery",
"description": "Sends a 6-digit verification code to the email address if an account exists.\nResponse is always the same regardless of whether the email exists (to prevent enumeration).\nRate limited to 3 requests per hour.\n",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"email"
],
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Email address associated with the API key"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Recovery code sent (or no-op if email not found)",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "recovery_sent"
},
"message": {
"type": "string"
}
}
}
}
}
},
"400": {
"description": "Invalid email format"
},
"429": {
"description": "Too many recovery attempts"
}
}
}
},
"/v1/recover/verify": {
"post": {
"tags": [
"Account"
],
"summary": "Verify recovery code and retrieve API key",
"description": "Verifies the 6-digit code sent via email and returns the API key if valid. Code expires after 15 minutes.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"email",
"code"
],
"properties": {
"email": {
"type": "string",
"format": "email"
},
"code": {
"type": "string",
"pattern": "^\\d{6}$",
"description": "6-digit verification code"
}
}
}
}
}
},
"responses": {
"200": {
"description": "API key recovered",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "recovered"
},
"apiKey": {
"type": "string",
"description": "The recovered API key"
},
"tier": {
"type": "string",
"enum": [
"free",
"pro"
]
}
}
}
}
}
},
"400": {
"description": "Invalid verification code or missing fields"
},
"410": {
"description": "Verification code expired"
},
"429": {
"description": "Too many failed attempts"
}
}
}
},
"/v1/templates": {
"get": {
"tags": [
"Templates"
],
"summary": "List available templates",
"description": "Returns a list of all built-in document templates with their required fields.",
"security": [
{
"BearerAuth": []
},
{
"ApiKeyHeader": []
}
],
"responses": {
"200": {
"description": "List of templates",
"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": "object",
"properties": {
"name": {
"type": "string"
},
"required": {
"type": "boolean"
},
"description": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
},
"401": {
"description": "Missing API key"
},
"403": {
"description": "Invalid API key"
}
}
}
},
"/v1/templates/{id}/render": {
"post": {
"tags": [
"Templates"
],
"summary": "Render a template to PDF",
"description": "Renders a built-in template with the provided data and returns a PDF.\nUse GET /v1/templates to see available templates and their required fields.\nSpecial fields: `_format` (page size), `_margin` (page margins), `_filename` (output filename).\n",
"security": [
{
"BearerAuth": []
},
{
"ApiKeyHeader": []
}
],
"parameters": [
{
"in": "path",
"name": "id",
"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 depend on template). Can also be passed at root level."
},
"_format": {
"type": "string",
"enum": [
"A4",
"Letter",
"Legal",
"A3",
"A5",
"Tabloid"
],
"default": "A4",
"description": "Page size override"
},
"_margin": {
"type": "object",
"properties": {
"top": {
"type": "string"
},
"right": {
"type": "string"
},
"bottom": {
"type": "string"
},
"left": {
"type": "string"
}
},
"description": "Page margin override"
},
"_filename": {
"type": "string",
"description": "Custom output filename"
}
}
}
}
}
},
"responses": {
"200": {
"description": "PDF document",
"content": {
"application/pdf": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Missing required template fields"
},
"401": {
"description": "Missing API key"
},
"403": {
"description": "Invalid API key"
},
"404": {
"description": "Template not found"
},
"500": {
"description": "Template rendering failed"
}
}
}
},
"/v1/signup/free": {
"post": {
"tags": [
"Account"
],
"summary": "Free signup (discontinued)",
"description": "Free accounts have been discontinued. Use the demo endpoint for testing\nor subscribe to Pro for production use.\n",
"deprecated": true,
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email"
}
}
}
}
}
},
"responses": {
"410": {
"description": "Free accounts discontinued",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Free accounts have been discontinued."
},
"demo_endpoint": {
"type": "string",
"example": "/v1/demo/html"
},
"pro_url": {
"type": "string",
"example": "https://docfast.dev/#pricing"
}
}
}
}
}
}
}
}
},
"/v1/usage": {
"get": {
"tags": [
"System"
],
"summary": "Usage statistics (admin only)",
"description": "Returns usage statistics for the authenticated user. Requires admin API key.",
"security": [
{
"BearerAuth": []
},
{
"ApiKeyHeader": []
}
],
"responses": {
"200": {
"description": "Usage statistics",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"month": {
"type": "string"
}
}
}
}
}
}
},
"403": {
"description": "Admin access required"
},
"503": {
"description": "Admin access not configured"
}
}
}
}
}
}