{ "openapi": "3.1.0", "info": { "title": "SnapAPI - Screenshot & Web Data API", "version": "2.0.0", "description": "Professional screenshot, PDF, video, scraping, content extraction, and AI analysis API. Convert any URL into structured data or visual captures with a single API call. Powered by headless Chromium.\n\n## Authentication\n\nAll API endpoints (except Auth and Health) require one of:\n- `X-Api-Key: sk_live_xxx` header (recommended for server-side)\n- `Authorization: Bearer sk_live_xxx` header\n- `?access_key=sk_live_xxx` query parameter (for GET endpoints)\n\nDashboard endpoints use JWT Bearer tokens obtained from `/auth/login`.\n\n## Rate Limits\n\n| Plan | Requests/month | Rate |\n|------|---------------|------|\n| Free | 100 | 10/min |\n| Starter | 5,000 | 60/min |\n| Pro | 50,000 | 300/min |\n\nRate limit headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`", "contact": { "email": "support@snapapi.pics", "url": "https://snapapi.pics" } }, "servers": [ { "url": "https://api.snapapi.pics", "description": "Production" } ], "security": [ { "ApiKeyAuth": [] } ], "components": { "securitySchemes": { "ApiKeyAuth": { "type": "apiKey", "in": "header", "name": "x-api-key", "description": "Your SnapAPI API key" }, "BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "JWT access token obtained from /auth/login or /auth/refresh" } }, "headers": { "X-RateLimit-Limit": { "schema": { "type": "integer" }, "description": "Max requests per window" }, "X-RateLimit-Remaining": { "schema": { "type": "integer" }, "description": "Remaining requests" }, "X-RateLimit-Reset": { "schema": { "type": "integer" }, "description": "Window reset time (unix ms)" }, "X-Request-Id": { "schema": { "type": "string" }, "description": "Unique request identifier for debugging" } }, "schemas": { "Error": { "type": "object", "properties": { "statusCode": { "type": "integer" }, "error": { "type": "string" }, "message": { "type": "string" } } }, "ScreenshotRequest": { "type": "object", "properties": { "url": { "type": "string", "format": "uri", "example": "https://example.com" }, "html": { "type": "string", "maxLength": 5000000, "description": "Raw HTML to render" }, "markdown": { "type": "string", "maxLength": 1000000, "description": "Markdown to render" }, "format": { "type": "string", "enum": [ "png", "jpeg", "webp", "avif", "pdf" ], "default": "png" }, "quality": { "type": "integer", "minimum": 1, "maximum": 100, "default": 80 }, "device": { "type": "string", "enum": [ "desktop-1080p", "desktop-1440p", "desktop-4k", "macbook-pro-13", "macbook-pro-16", "imac-24", "iphone-12", "iphone-13", "iphone-14", "iphone-14-pro", "iphone-15", "iphone-15-pro", "iphone-15-pro-max", "iphone-se", "ipad", "ipad-mini", "ipad-air", "ipad-pro-11", "ipad-pro-12.9", "pixel-7", "pixel-8", "pixel-8-pro", "samsung-galaxy-s23", "samsung-galaxy-s24", "samsung-galaxy-tab-s9" ] }, "width": { "type": "integer", "minimum": 100, "maximum": 3840, "default": 1280 }, "height": { "type": "integer", "minimum": 100, "maximum": 2160, "default": 800 }, "deviceScaleFactor": { "type": "number", "minimum": 1, "maximum": 3, "default": 1 }, "isMobile": { "type": "boolean", "default": false }, "hasTouch": { "type": "boolean", "default": false }, "isLandscape": { "type": "boolean", "default": false }, "fullPage": { "type": "boolean", "default": false }, "fullPageScrollDelay": { "type": "integer", "default": 400 }, "fullPageMaxHeight": { "type": "integer", "maximum": 50000 }, "selector": { "type": "string", "description": "CSS selector to capture specific element" }, "clipX": { "type": "integer" }, "clipY": { "type": "integer" }, "clipWidth": { "type": "integer" }, "clipHeight": { "type": "integer" }, "delay": { "type": "integer", "minimum": 0, "maximum": 30000, "default": 0 }, "timeout": { "type": "integer", "minimum": 1000, "maximum": 60000, "default": 30000 }, "waitUntil": { "type": "string", "enum": [ "load", "domcontentloaded", "networkidle" ], "default": "load" }, "waitForSelector": { "type": "string" }, "darkMode": { "type": "boolean", "default": false }, "reducedMotion": { "type": "boolean", "default": false }, "css": { "type": "string", "maxLength": 100000, "description": "Custom CSS (Starter+)" }, "javascript": { "type": "string", "maxLength": 100000, "description": "Custom JS (Pro+)" }, "hideSelectors": { "type": "array", "items": { "type": "string" }, "maxItems": 50 }, "clickSelector": { "type": "string" }, "clickDelay": { "type": "integer" }, "blockAds": { "type": "boolean", "default": false, "description": "Block ads (Starter+)" }, "blockTrackers": { "type": "boolean", "default": false, "description": "Block trackers (Pro+)" }, "blockCookieBanners": { "type": "boolean", "default": false }, "blockChatWidgets": { "type": "boolean", "default": false }, "blockResources": { "type": "array", "items": { "type": "string", "enum": [ "document", "stylesheet", "image", "media", "font", "script", "xhr", "fetch", "websocket" ] } }, "userAgent": { "type": "string" }, "extraHeaders": { "type": "object", "additionalProperties": { "type": "string" } }, "cookies": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "value": { "type": "string" }, "domain": { "type": "string" }, "path": { "type": "string" } } } }, "httpAuth": { "type": "object", "properties": { "username": { "type": "string" }, "password": { "type": "string" } } }, "proxy": { "type": "object", "properties": { "server": { "type": "string", "format": "uri" }, "username": { "type": "string" }, "password": { "type": "string" } } }, "geolocation": { "type": "object", "properties": { "latitude": { "type": "number" }, "longitude": { "type": "number" }, "accuracy": { "type": "number" } } }, "timezone": { "type": "string", "example": "America/New_York" }, "locale": { "type": "string", "example": "en-US" }, "pdfOptions": { "type": "object", "properties": { "pageSize": { "type": "string", "enum": [ "a4", "a3", "a5", "letter", "legal", "tabloid", "custom" ] }, "landscape": { "type": "boolean" }, "printBackground": { "type": "boolean" }, "scale": { "type": "number", "minimum": 0.1, "maximum": 2 }, "marginTop": { "type": "string" }, "marginBottom": { "type": "string" }, "marginLeft": { "type": "string" }, "marginRight": { "type": "string" }, "headerTemplate": { "type": "string" }, "footerTemplate": { "type": "string" }, "displayHeaderFooter": { "type": "boolean" }, "pageRanges": { "type": "string" } } }, "thumbnail": { "type": "object", "properties": { "enabled": { "type": "boolean" }, "width": { "type": "integer" }, "height": { "type": "integer" }, "fit": { "type": "string", "enum": [ "cover", "contain", "fill" ] } } }, "failOnHttpError": { "type": "boolean", "default": false }, "failIfContentMissing": { "type": "array", "items": { "type": "string" } }, "failIfContentContains": { "type": "array", "items": { "type": "string" } }, "cache": { "type": "boolean", "default": false, "description": "Enable caching (Pro+)" }, "cacheTtl": { "type": "integer", "minimum": 60, "maximum": 2592000, "default": 86400 }, "responseType": { "type": "string", "enum": [ "binary", "base64", "json" ], "default": "binary" }, "includeMetadata": { "type": "boolean", "default": false }, "extractMetadata": { "type": "object", "properties": { "fonts": { "type": "boolean" }, "colors": { "type": "boolean" }, "links": { "type": "boolean" }, "httpStatusCode": { "type": "boolean" } } }, "storage": { "type": "object", "properties": { "enabled": { "type": "boolean" }, "destination": { "type": "string", "enum": [ "snapapi", "user_s3" ] } } }, "async": { "type": "boolean", "default": false }, "webhookUrl": { "type": "string", "format": "uri" }, "webhookHeaders": { "type": "object", "additionalProperties": { "type": "string" } } } }, "ScreenshotJsonResponse": { "type": "object", "properties": { "success": { "type": "boolean", "example": true }, "cached": { "type": "boolean" }, "data": { "type": "string", "description": "Base64-encoded image data" }, "format": { "type": "string", "example": "png" }, "width": { "type": "integer", "example": 1280 }, "height": { "type": "integer", "example": 800 }, "fileSize": { "type": "integer" }, "took": { "type": "integer", "description": "Response time in ms" }, "metadata": { "type": "object" }, "storage": { "type": "object", "properties": { "id": { "type": "string" }, "url": { "type": "string" } } } } }, "AsyncJobResponse": { "type": "object", "properties": { "success": { "type": "boolean" }, "async": { "type": "boolean" }, "jobId": { "type": "string" }, "status": { "type": "string", "enum": [ "pending", "processing", "completed", "failed" ] }, "statusUrl": { "type": "string" } } }, "BatchRequest": { "type": "object", "required": [ "urls" ], "properties": { "urls": { "type": "array", "items": { "type": "string", "format": "uri" }, "minItems": 1, "maxItems": 100 }, "format": { "type": "string", "enum": [ "png", "jpeg", "webp", "avif", "pdf" ], "default": "png" }, "quality": { "type": "integer", "default": 80 }, "width": { "type": "integer", "default": 1280 }, "height": { "type": "integer", "default": 800 }, "fullPage": { "type": "boolean", "default": false }, "darkMode": { "type": "boolean", "default": false }, "blockAds": { "type": "boolean", "default": false }, "blockCookieBanners": { "type": "boolean", "default": false }, "webhookUrl": { "type": "string", "format": "uri" } } }, "VideoRequest": { "type": "object", "required": [ "url" ], "properties": { "url": { "type": "string", "format": "uri" }, "format": { "type": "string", "enum": [ "webm", "mp4", "gif" ], "default": "webm" }, "width": { "type": "integer", "minimum": 320, "maximum": 1920, "default": 1280 }, "height": { "type": "integer", "minimum": 240, "maximum": 1080, "default": 720 }, "duration": { "type": "integer", "minimum": 1, "maximum": 30, "default": 5, "description": "Duration in seconds" }, "fps": { "type": "integer", "minimum": 10, "maximum": 30, "default": 25 }, "scrolling": { "type": "boolean", "default": false }, "scrollSpeed": { "type": "integer", "default": 100 }, "darkMode": { "type": "boolean", "default": false }, "blockAds": { "type": "boolean", "default": false }, "blockCookieBanners": { "type": "boolean", "default": false }, "delay": { "type": "integer", "default": 0 }, "responseType": { "type": "string", "enum": [ "binary", "base64", "json" ], "default": "binary" } } }, "ExtractRequest": { "type": "object", "required": [ "url" ], "properties": { "url": { "type": "string", "format": "uri" }, "type": { "type": "string", "enum": [ "html", "text", "markdown", "article", "links", "images", "metadata", "structured" ], "default": "markdown" }, "selector": { "type": "string", "description": "CSS selector to target" }, "waitFor": { "type": "string", "description": "Wait for selector before extracting" }, "timeout": { "type": "integer", "minimum": 1000, "maximum": 60000, "default": 30000 }, "darkMode": { "type": "boolean", "default": false }, "blockAds": { "type": "boolean", "default": false }, "blockCookieBanners": { "type": "boolean", "default": false }, "includeImages": { "type": "boolean", "default": true }, "maxLength": { "type": "integer", "minimum": 100, "maximum": 500000 }, "cleanOutput": { "type": "boolean", "default": true } } }, "ExtractResponse": { "type": "object", "properties": { "success": { "type": "boolean" }, "type": { "type": "string" }, "url": { "type": "string" }, "data": { "description": "Extracted content (format depends on type param)" }, "responseTime": { "type": "integer" } } }, "AnalyzeRequest": { "type": "object", "required": [ "url", "prompt", "apiKey" ], "properties": { "url": { "type": "string", "format": "uri" }, "prompt": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Analysis prompt for the LLM" }, "provider": { "type": "string", "enum": [ "openai", "anthropic" ], "default": "openai" }, "apiKey": { "type": "string", "description": "Your own LLM provider API key (BYOK)" }, "model": { "type": "string", "description": "Model override (e.g. gpt-4o, claude-sonnet-4-20250514)" }, "jsonSchema": { "type": "object", "description": "JSON schema for structured LLM output" }, "timeout": { "type": "integer", "default": 30000 }, "waitFor": { "type": "string" }, "blockAds": { "type": "boolean", "default": true }, "blockCookieBanners": { "type": "boolean", "default": true }, "includeScreenshot": { "type": "boolean", "default": false }, "includeMetadata": { "type": "boolean", "default": true }, "maxContentLength": { "type": "integer", "default": 50000 } } }, "AnalyzeResponse": { "type": "object", "properties": { "success": { "type": "boolean" }, "url": { "type": "string" }, "metadata": { "type": "object", "properties": { "url": { "type": "string" }, "title": { "type": "string" }, "description": { "type": "string" } } }, "analysis": { "description": "LLM analysis (string or structured object)" }, "provider": { "type": "string" }, "model": { "type": "string" }, "responseTime": { "type": "integer" } } }, "UsageResponse": { "type": "object", "properties": { "used": { "type": "integer", "example": 150 }, "limit": { "type": "integer", "example": 1000 }, "remaining": { "type": "integer", "example": 850 }, "resetAt": { "type": "string", "format": "date-time" } } }, "UserObject": { "type": "object", "properties": { "id": { "type": "string" }, "email": { "type": "string", "format": "email" }, "name": { "type": "string" }, "plan": { "type": "string", "enum": [ "free", "starter", "pro" ] }, "avatarUrl": { "type": "string", "nullable": true }, "emailVerified": { "type": "boolean" }, "isAdmin": { "type": "boolean" }, "createdAt": { "type": "string", "format": "date-time" } } }, "AuthResponse": { "type": "object", "properties": { "success": { "type": "boolean", "example": true }, "user": { "$ref": "#/components/schemas/UserObject" }, "accessToken": { "type": "string", "description": "JWT access token (15 min expiry). Store in memory only." }, "message": { "type": "string" } } }, "ScrapeRequest": { "type": "object", "required": [ "url" ], "properties": { "url": { "type": "string", "format": "uri", "description": "URL to scrape" }, "type": { "type": "string", "enum": [ "text", "html", "links", "markdown", "metadata" ], "default": "text", "description": "Output format" }, "pages": { "type": "integer", "minimum": 1, "maximum": 10, "default": 1, "description": "Number of paginated pages to scrape" }, "waitMs": { "type": "integer", "minimum": 0, "maximum": 30000, "default": 0, "description": "Wait time in ms after page load" }, "proxy": { "type": "string", "description": "Custom proxy URL (http://user:pass@host:port)" }, "premiumProxy": { "type": "boolean", "description": "Use managed residential proxy pool" }, "blockResources": { "type": "boolean", "default": false, "description": "Block images, media, and fonts" }, "locale": { "type": "string", "maxLength": 20, "description": "Browser locale (e.g. en-US)" } } }, "ScrapeResponse": { "type": "object", "properties": { "success": { "type": "boolean" }, "results": { "type": "array", "items": { "type": "object", "properties": { "page": { "type": "integer" }, "url": { "type": "string" }, "data": { "type": "string", "description": "Scraped content (string or JSON string for links/metadata)" } } } } } }, "ApiKey": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string", "description": "Full key value (only returned on create/regenerate)", "example": "sk_live_abc123..." }, "name": { "type": "string" }, "createdAt": { "type": "string", "format": "date-time" }, "lastUsedAt": { "type": "string", "format": "date-time", "nullable": true }, "expiresAt": { "type": "string", "format": "date-time", "nullable": true }, "isActive": { "type": "boolean" }, "permissions": { "type": "array", "items": { "type": "string", "enum": [ "screenshot", "pdf", "metadata", "batch" ] } } } }, "StoredFile": { "type": "object", "properties": { "id": { "type": "string" }, "storageType": { "type": "string", "enum": [ "local", "user_s3" ] }, "originalUrl": { "type": "string" }, "format": { "type": "string" }, "fileSize": { "type": "integer" }, "width": { "type": "integer", "nullable": true }, "height": { "type": "integer", "nullable": true }, "url": { "type": "string", "nullable": true, "description": "Signed URL to access the file" }, "thumbnailUrl": { "type": "string", "nullable": true }, "createdAt": { "type": "string", "format": "date-time" } } } } }, "paths": { "/v1/ping": { "get": { "operationId": "ping", "summary": "Ping", "description": "Simple health check. Returns OK status and timestamp.", "tags": [ "Health" ], "security": [], "responses": { "200": { "description": "OK", "headers": { "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "example": "ok" }, "timestamp": { "type": "integer", "example": 1708372800000 } } }, "example": { "status": "ok", "timestamp": 1708372800000 } } } } } } }, "/health": { "get": { "operationId": "healthCheck", "summary": "Health Check", "tags": [ "Health" ], "security": [], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string" }, "timestamp": { "type": "string", "format": "date-time" } } } } } } } } }, "/health/detailed": { "get": { "operationId": "healthDetailed", "summary": "Detailed Health Check", "description": "Returns status of database, Redis, and job queue.", "tags": [ "Health" ], "security": [], "responses": { "200": { "description": "All systems healthy" }, "503": { "description": "One or more systems degraded" } } } }, "/v1/screenshot": { "post": { "operationId": "takeScreenshot", "summary": "Take Screenshot", "description": "Capture a screenshot of any URL, HTML, or Markdown. Supports full-page, device emulation, dark mode, ad blocking, custom CSS/JS, caching, async processing, webhooks, and cloud storage.", "tags": [ "Screenshot" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScreenshotRequest" }, "examples": { "simple": { "summary": "Basic screenshot", "value": { "url": "https://example.com", "format": "png" } }, "fullPage": { "summary": "Full page + dark mode", "value": { "url": "https://example.com", "fullPage": true, "darkMode": true, "blockAds": true } }, "mobile": { "summary": "iPhone 15 Pro", "value": { "url": "https://example.com", "device": "iphone-15-pro" } }, "html": { "summary": "Render HTML", "value": { "html": "
Rendered by SnapAPI
", "format": "png", "width": 800, "height": 600 } } } } } }, "responses": { "200": { "description": "Screenshot captured successfully", "headers": { "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" }, "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" }, "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" }, "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" } }, "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "application/pdf": { "schema": { "type": "string", "format": "binary" } }, "application/json": { "schema": { "$ref": "#/components/schemas/ScreenshotJsonResponse" } } } }, "202": { "description": "Async job accepted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AsyncJobResponse" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Invalid or missing API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "Feature not available on your plan", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "description": "Rate limit or quota exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "get": { "operationId": "takeScreenshotGet", "summary": "Take Screenshot (GET)", "description": "Simple GET endpoint for screenshots via query parameters.", "tags": [ "Screenshot" ], "parameters": [ { "name": "url", "in": "query", "required": true, "schema": { "type": "string", "format": "uri" } }, { "name": "format", "in": "query", "schema": { "type": "string", "enum": [ "png", "jpeg", "webp", "avif", "pdf" ], "default": "png" } }, { "name": "quality", "in": "query", "schema": { "type": "integer" } }, { "name": "width", "in": "query", "schema": { "type": "integer", "default": 1280 } }, { "name": "height", "in": "query", "schema": { "type": "integer", "default": 800 } }, { "name": "full_page", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "dark_mode", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "block_ads", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "block_cookie_banners", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "cache", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "response_type", "in": "query", "schema": { "type": "string", "enum": [ "binary", "base64", "json" ], "default": "binary" } } ], "responses": { "200": { "description": "Screenshot captured" }, "400": { "description": "Validation error" }, "401": { "description": "Invalid API key" } } } }, "/v1/pdf": { "post": { "operationId": "generatePdf", "summary": "Generate PDF", "description": "Generate a PDF from any URL or HTML. Supports page sizes, margins, headers/footers, and scaling.", "tags": [ "PDF" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScreenshotRequest" }, "example": { "url": "https://example.com", "pdfOptions": { "pageSize": "a4", "landscape": false, "printBackground": true } } } } }, "responses": { "200": { "description": "PDF generated", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Validation error" }, "401": { "description": "Invalid API key" } } } }, "/v1/screenshot/batch": { "post": { "operationId": "batchScreenshots", "summary": "Batch Screenshots", "description": "Submit up to 100 URLs for batch processing. Returns a job ID to poll for results.", "tags": [ "Screenshot" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchRequest" }, "example": { "urls": [ "https://example.com", "https://google.com" ], "format": "png", "width": 1280 } } } }, "responses": { "202": { "description": "Batch job accepted", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "jobId": { "type": "string" }, "status": { "type": "string" }, "total": { "type": "integer" }, "message": { "type": "string" } } } } } }, "429": { "description": "Quota exceeded" } } } }, "/v1/screenshot/batch/{jobId}": { "get": { "operationId": "getBatchStatus", "summary": "Get Batch Job Status", "tags": [ "Screenshot" ], "parameters": [ { "name": "jobId", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Batch job status with results" }, "404": { "description": "Job not found or expired" } } } }, "/v1/screenshot/async/{jobId}": { "get": { "operationId": "getAsyncStatus", "summary": "Get Async Screenshot Status", "tags": [ "Screenshot" ], "parameters": [ { "name": "jobId", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "includeData", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] }, "description": "Include base64 data in response" } ], "responses": { "200": { "description": "Async job status" }, "404": { "description": "Job not found or expired" } } } }, "/v1/video": { "post": { "operationId": "recordVideo", "summary": "Record Video", "description": "Record a video of a webpage with optional scrolling. Supports WebM, MP4, and GIF output. Costs 5 credits per recording.", "tags": [ "Video" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VideoRequest" }, "examples": { "basic": { "summary": "5-second recording", "value": { "url": "https://example.com", "duration": 5, "format": "mp4" } }, "scrolling": { "summary": "Scrolling video", "value": { "url": "https://example.com", "duration": 10, "scrolling": true, "scrollSpeed": 150, "format": "webm" } } } } } }, "responses": { "200": { "description": "Video recorded", "headers": { "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" } }, "content": { "video/webm": { "schema": { "type": "string", "format": "binary" } }, "video/mp4": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } }, "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "data": { "type": "string" }, "format": { "type": "string" }, "width": { "type": "integer" }, "height": { "type": "integer" }, "duration": { "type": "integer" }, "fileSize": { "type": "integer" }, "took": { "type": "integer" } } } } } }, "400": { "description": "Validation error" }, "429": { "description": "Quota exceeded" }, "503": { "description": "Server busy (max concurrent videos reached)" } } } }, "/v1/extract": { "post": { "operationId": "extractContent", "summary": "Extract Web Content", "description": "Extract content from any webpage as HTML, text, markdown, article, links, images, metadata, or structured data. Optimized for LLM consumption.", "tags": [ "Extract" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractRequest" }, "examples": { "markdown": { "summary": "Extract as markdown", "value": { "url": "https://example.com", "type": "markdown" } }, "article": { "summary": "Extract article (Readability)", "value": { "url": "https://blog.example.com/post", "type": "article" } }, "structured": { "summary": "Structured extraction", "value": { "url": "https://example.com", "type": "structured", "maxLength": 10000 } }, "links": { "summary": "Extract all links", "value": { "url": "https://example.com", "type": "links" } } } } } }, "responses": { "200": { "description": "Content extracted", "headers": { "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtractResponse" } } } }, "400": { "description": "Validation error" }, "401": { "description": "Invalid API key" } } }, "get": { "operationId": "extractContentGet", "summary": "Extract Web Content (GET)", "tags": [ "Extract" ], "parameters": [ { "name": "url", "in": "query", "required": true, "schema": { "type": "string", "format": "uri" } }, { "name": "type", "in": "query", "schema": { "type": "string", "enum": [ "html", "text", "markdown", "article", "links", "images", "metadata", "structured" ], "default": "markdown" } }, { "name": "selector", "in": "query", "schema": { "type": "string" } }, { "name": "max_length", "in": "query", "schema": { "type": "integer" } }, { "name": "clean", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ], "default": "true" } }, { "name": "block_ads", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "block_cookies", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } } ], "responses": { "200": { "description": "Content extracted" }, "400": { "description": "Validation error" } } } }, "/v1/analyze": { "post": { "operationId": "analyzeWebpage", "summary": "AI-Powered Web Analysis", "description": "Analyze any webpage using your own LLM API key (BYOK). Supports OpenAI and Anthropic. Optionally get structured JSON output via jsonSchema. Perfect for competitive intelligence, compliance audits, and data extraction.", "tags": [ "Analyze" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnalyzeRequest" }, "examples": { "basic": { "summary": "Basic analysis", "value": { "url": "https://example.com", "prompt": "Summarize the main content", "provider": "openai", "apiKey": "sk-..." } }, "structured": { "summary": "Structured output", "value": { "url": "https://example.com/pricing", "prompt": "Extract all pricing plans", "provider": "openai", "apiKey": "sk-...", "jsonSchema": { "type": "object", "properties": { "plans": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "string" }, "features": { "type": "array", "items": { "type": "string" } } } } } }, "required": [ "plans" ], "additionalProperties": false } } } } } } }, "responses": { "200": { "description": "Analysis complete", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnalyzeResponse" } } } }, "400": { "description": "Validation error" }, "401": { "description": "Invalid SnapAPI key" }, "502": { "description": "LLM provider error" } } } }, "/v1/usage": { "get": { "operationId": "getUsage", "summary": "Get API Usage", "description": "Check your current API usage and remaining quota.", "tags": [ "Usage" ], "responses": { "200": { "description": "Usage data", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageResponse" }, "example": { "used": 150, "limit": 1000, "remaining": 850, "resetAt": "2026-03-01T00:00:00.000Z" } } } }, "401": { "description": "Invalid API key" } } } }, "/v1/devices": { "get": { "operationId": "listDevices", "summary": "List Device Presets", "description": "Get all available device presets (desktop, mobile, tablet) for screenshot emulation.", "tags": [ "Utilities" ], "security": [], "responses": { "200": { "description": "Device presets grouped by category" } } } }, "/v1/capabilities": { "get": { "operationId": "getCapabilities", "summary": "API Capabilities", "description": "Get supported formats, features, and limits.", "tags": [ "Utilities" ], "security": [], "responses": { "200": { "description": "API capabilities" } } } }, "/v1/scrape": { "post": { "operationId": "scrapeWebpage", "summary": "Scrape Webpage", "description": "Scrape content from any URL. Returns text, HTML, markdown, links, or metadata. Supports pagination for multi-page crawls, custom proxies, and resource blocking.", "tags": [ "Scrape" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeRequest" }, "examples": { "text": { "summary": "Scrape as plain text", "value": { "url": "https://example.com", "type": "text" } }, "markdown": { "summary": "Scrape as markdown (LLM-ready)", "value": { "url": "https://example.com", "type": "markdown" } }, "links": { "summary": "Extract all links", "value": { "url": "https://example.com", "type": "links" } }, "metadata": { "summary": "Extract page metadata", "value": { "url": "https://example.com", "type": "metadata" } }, "multipage": { "summary": "3-page scrape", "value": { "url": "https://example.com/blog", "type": "text", "pages": 3, "waitMs": 500 } } } } } }, "responses": { "200": { "description": "Content scraped successfully", "headers": { "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeResponse" } } } }, "400": { "description": "Validation error or invalid URL", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Invalid or missing API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "description": "Rate limit or quota exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Scrape failed (site unreachable or timeout)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "get": { "operationId": "scrapeWebpageGet", "summary": "Scrape Webpage (GET)", "description": "Simple GET version of the scrape endpoint using query parameters.", "tags": [ "Scrape" ], "parameters": [ { "name": "url", "in": "query", "required": true, "schema": { "type": "string", "format": "uri" }, "description": "URL to scrape" }, { "name": "type", "in": "query", "schema": { "type": "string", "enum": [ "text", "html", "links" ], "default": "text" } }, { "name": "pages", "in": "query", "schema": { "type": "integer", "default": 1 } }, { "name": "wait_ms", "in": "query", "schema": { "type": "integer", "default": 0 } }, { "name": "block_resources", "in": "query", "schema": { "type": "string", "enum": [ "true", "false" ] } }, { "name": "locale", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Content scraped", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScrapeResponse" } } } }, "400": { "description": "Validation error" }, "401": { "description": "Invalid API key" } } } }, "/auth/register": { "post": { "operationId": "register", "summary": "Register", "description": "Create a new account with email and password. A verification email is sent automatically. Rate limited to 3 requests/minute per IP.", "tags": [ "Auth" ], "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "email", "password" ], "properties": { "email": { "type": "string", "format": "email" }, "password": { "type": "string", "minLength": 8, "description": "Minimum 8 characters" }, "name": { "type": "string", "maxLength": 100, "description": "Optional display name" } } }, "example": { "email": "user@example.com", "password": "securepass123", "name": "Jane Developer" } } } }, "responses": { "200": { "description": "Registration successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "400": { "description": "Email already registered or invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "429": { "description": "Rate limited (3/min per IP)" } } } }, "/auth/login": { "post": { "operationId": "login", "summary": "Login", "description": "Authenticate with email and password. Returns a JWT access token and sets a HttpOnly refresh token cookie. Rate limited to 5 requests/minute per IP.", "tags": [ "Auth" ], "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "email", "password" ], "properties": { "email": { "type": "string", "format": "email" }, "password": { "type": "string" } } }, "example": { "email": "user@example.com", "password": "securepass123" } } } }, "responses": { "200": { "description": "Login successful. `refresh_token` set as HttpOnly cookie.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "401": { "description": "Invalid credentials", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "403": { "description": "Account disabled" }, "429": { "description": "Rate limited (5/min per IP)" } } } }, "/auth/google": { "post": { "operationId": "googleAuth", "summary": "Google OAuth", "description": "Sign in or register using a Google ID token obtained from Google Sign-In.", "tags": [ "Auth" ], "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "credential" ], "properties": { "credential": { "type": "string", "description": "Google ID token from Google Sign-In" } } } } } }, "responses": { "200": { "description": "Authentication successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "400": { "description": "Invalid Google token" }, "501": { "description": "Google OAuth not configured" } } } }, "/auth/github": { "post": { "operationId": "githubAuth", "summary": "GitHub OAuth", "description": "Sign in or register using a GitHub OAuth authorization code.", "tags": [ "Auth" ], "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "code" ], "properties": { "code": { "type": "string", "description": "GitHub OAuth authorization code" } } } } } }, "responses": { "200": { "description": "Authentication successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "400": { "description": "Invalid or expired authorization code" }, "501": { "description": "GitHub OAuth not configured" } } } }, "/auth/apple": { "post": { "operationId": "appleAuth", "summary": "Apple Sign-In", "description": "Sign in or register using an Apple ID token.", "tags": [ "Auth" ], "security": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "idToken" ], "properties": { "idToken": { "type": "string", "description": "Apple ID token" }, "user": { "type": "object", "description": "User info (only sent on first sign-in)", "properties": { "email": { "type": "string", "format": "email" }, "name": { "type": "object", "properties": { "firstName": { "type": "string" }, "lastName": { "type": "string" } } } } } } } } } }, "responses": { "200": { "description": "Authentication successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "400": { "description": "Invalid Apple token" } } } }, "/auth/refresh": { "post": { "operationId": "refreshToken", "summary": "Refresh Token", "description": "Exchange the `refresh_token` HttpOnly cookie for a new access token. Rotates the refresh token on each use.", "tags": [ "Auth" ], "security": [], "responses": { "200": { "description": "New access token issued", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "401": { "description": "No refresh token cookie or token expired/invalid" } } } }, "/auth/logout": { "post": { "operationId": "logout", "summary": "Logout", "description": "Invalidate the current session and clear the refresh token cookie.", "tags": [ "Auth" ], "security": [], "responses": { "200": { "description": "Logged out successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" } } } } } } } } }, "/auth/me": { "get": { "operationId": "getCurrentUser", "summary": "Get Current User", "description": "Get the authenticated user's profile. Requires `Authorization: Bearer