{"openapi": "3.0.3", "info": {"title": "Hermes Visual Infrastructure APIs", "description": "14 REST APIs for visual infrastructure, website analysis, and AI agent pipelines. Visual Infrastructure Bundle: Screenshot API (sync, batch, async queue + webhooks) + Chart Rendering API (Chart.js config \u2192 PNG/JPEG) \u2014 one key covers both. Also includes: dead link checker, SEO audit, HTML-to-image, performance check, tech stack detector, SSL certificate checker. Built for AI agent pipelines \u2014 per-call pricing aligns with agent consumption patterns.", "version": "3.0.0", "contact": {"name": "Hermes Agent", "email": "hermes-agent@agentmail.to", "url": "https://hermesforge.dev/"}}, "servers": [{"url": "https://hermesforge.dev", "description": "Production server"}], "paths": {"/api/deadlinks": {"get": {"operationId": "checkDeadLinks", "summary": "Find broken links on any webpage", "description": "Crawls a website and checks all links for broken responses (4xx, 5xx, connection failures). Returns broken links, redirect chains, and health score.", "parameters": [{"name": "url", "in": "query", "required": true, "description": "The URL to crawl for broken links", "schema": {"type": "string", "example": "https://example.com"}}, {"name": "max_pages", "in": "query", "required": false, "description": "Maximum internal pages to crawl (1-50)", "schema": {"type": "integer", "default": 20, "maximum": 50}, "example": 50}, {"name": "max_duration", "in": "query", "required": false, "description": "Maximum crawl duration in seconds. Returns partial results with timed_out: true if exceeded.", "schema": {"type": "integer", "minimum": 10, "maximum": 120, "example": 60}}, {"name": "mode", "in": "query", "required": false, "description": "Crawl mode: 'full' (deep crawl with browser) or 'quick' (sub-second, homepage only)", "schema": {"type": "string", "enum": ["full", "quick"], "default": "full"}, "example": "quick"}, {"name": "format", "in": "query", "required": false, "description": "Output format: json, csv, github (CI/CD annotations), or markdown", "schema": {"type": "string", "enum": ["json", "csv", "github", "markdown"], "default": "json"}, "example": "json"}, {"name": "github", "in": "query", "required": false, "description": "GitHub repo (owner/repo) to check README links", "schema": {"type": "string", "example": "facebook/react"}}, {"name": "threshold", "in": "query", "required": false, "description": "Health score threshold for CI/CD PASS/FAIL gating (0-100)", "schema": {"type": "integer", "minimum": 0, "maximum": 100}, "example": 10}, {"name": "check_only", "in": "query", "required": false, "description": "Filter links: 'internal' or 'external' only", "schema": {"type": "string", "enum": ["internal", "external"]}, "example": "https://example.com/specific-page"}], "responses": {"200": {"description": "Crawl completed. Returns broken links, redirect warnings, and health score.", "content": {"application/json": {"schema": {"type": "object", "properties": {"target": {"type": "string"}, "pages_crawled": {"type": "integer"}, "total_links_checked": {"type": "integer"}, "broken_count": {"type": "integer"}, "broken_links": {"type": "array", "items": {"type": "object"}}, "summary": {"type": "object", "properties": {"health_score": {"type": "number"}, "broken_images": {"type": "integer"}, "redirects_found": {"type": "integer"}}}}}}}}}}}, "/api/seo": {"get": {"operationId": "auditSEO", "summary": "Audit a webpage's SEO factors", "description": "Checks title, meta description, headings hierarchy, image alt text, canonical tags, Open Graph tags, robots directives, and more.", "parameters": [{"name": "url", "in": "query", "required": true, "description": "The URL to audit", "schema": {"type": "string", "example": "https://example.com"}}], "responses": {"200": {"description": "SEO audit results with scores and recommendations.", "content": {"application/json": {"schema": {"type": "object", "properties": {"url": {"type": "string"}, "score": {"type": "number"}, "checks": {"type": "object"}, "recommendations": {"type": "array", "items": {"type": "string"}}}}}}}}}}, "/api/screenshot": {"get": {"operationId": "captureScreenshot", "summary": "Capture a screenshot of any URL", "description": "Renders the page in a real browser (Chromium) and returns an image. Supports PNG, JPEG, WebP, and PDF formats. Features include dark mode, retina scaling, CSS element capture, ad blocking, and custom JavaScript injection. Rate limits: free 50/day, Starter 200/day, Pro 1000/day, Business 5000/day.", "parameters": [{"name": "url", "in": "query", "required": true, "description": "The URL to screenshot", "schema": {"type": "string", "example": "https://example.com"}}, {"name": "viewport", "in": "query", "required": false, "description": "Device viewport preset. Overrides width/height. Options: mobile (375x812), tablet (768x1024), desktop (1280x720), desktop_hd (1920x1080), macbook (1440x900), iphone_14 (390x844), pixel_7 (412x915), ipad_pro (1024x1366), og (1200x630), twitter (1200x675), linkedin (1200x627). Add _landscape suffix for landscape orientation on mobile/tablet.", "schema": {"type": "string", "enum": ["mobile", "mobile_landscape", "tablet", "tablet_landscape", "desktop", "desktop_hd", "desktop_4k", "macbook", "iphone_se", "iphone_14", "iphone_14_pro_max", "pixel_7", "galaxy_s21", "ipad_mini", "ipad_pro", "linkedin", "twitter", "facebook", "og"]}, "example": "mobile"}, {"name": "width", "in": "query", "required": false, "description": "Viewport width in pixels (overridden by viewport preset)", "schema": {"type": "integer", "default": 1280}, "example": 1280}, {"name": "height", "in": "query", "required": false, "description": "Viewport height in pixels", "schema": {"type": "integer", "default": 720}, "example": 720}, {"name": "full_page", "in": "query", "required": false, "description": "Capture full page (true) or viewport only (false)", "schema": {"type": "boolean", "default": true}, "example": true}, {"name": "clip", "in": "query", "required": false, "description": "Crop region as x,y,width,height in pixels. Example: 0,0,400,300 captures the top-left 400x300 area. Ignored when full_page=true.", "schema": {"type": "string"}, "example": "0,0,800,600"}, {"name": "format", "in": "query", "required": false, "description": "Image format: png, jpeg, webp, or pdf", "schema": {"type": "string", "enum": ["png", "jpeg", "webp", "pdf"], "default": "png"}, "example": "webp"}, {"name": "dark_mode", "in": "query", "required": false, "description": "Emulate dark mode (prefers-color-scheme: dark)", "schema": {"type": "boolean", "default": false}, "example": true}, {"name": "scale", "in": "query", "required": false, "description": "Device scale factor for retina screenshots (1, 2, or 3)", "schema": {"type": "integer", "enum": [1, 2, 3], "default": 1}, "example": 2}, {"name": "selector", "in": "query", "required": false, "description": "CSS selector to capture a specific element instead of the full page", "schema": {"type": "string", "example": "#main-content"}}, {"name": "delay", "in": "query", "required": false, "description": "Wait time in ms after page load before capture (max 10000)", "schema": {"type": "integer", "default": 0, "maximum": 10000}, "example": 2000}, {"name": "quality", "in": "query", "required": false, "description": "Image quality for JPEG and WebP (1-100)", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 80}, "example": 85}, {"name": "block_ads", "in": "query", "required": false, "description": "Block ads, trackers, and cookie banners before capture", "schema": {"type": "boolean", "default": false}, "example": true}, {"name": "js", "in": "query", "required": false, "description": "Custom JavaScript to execute before capture (max 2000 chars)", "schema": {"type": "string", "maxLength": 2000}, "example": "document.querySelector(\".cookie-banner\")?.remove()"}, {"name": "wait_for", "in": "query", "description": "CSS selector to wait for before capturing. Useful for SPAs and dynamically loaded content.", "required": false, "schema": {"type": "string"}, "example": "#main-content"}, {"name": "http_username", "in": "query", "description": "HTTP Basic Auth username for password-protected pages (e.g., Grafana, Kibana dashboards). Requires API key.", "required": false, "schema": {"type": "string"}, "example": "user"}, {"name": "http_password", "in": "query", "description": "HTTP Basic Auth password. Requires API key.", "required": false, "schema": {"type": "string"}, "example": "pass"}, {"name": "accept_language", "in": "query", "description": "Browser Accept-Language header for localized screenshots. Sets both the HTTP header and browser locale. Examples: fr-FR, de-DE, ja-JP, pt-BR. Alias: lang.", "required": false, "schema": {"type": "string"}, "example": "fr-FR"}], "responses": {"200": {"description": "Screenshot image in the requested format", "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"}}}}}}}, "/api/charts/render": {"post": {"operationId": "renderChart", "summary": "Render a Chart.js config to PNG/JPEG image", "description": "Accepts a Chart.js-compatible configuration JSON object and returns a rendered PNG or JPEG image. Supports all Chart.js chart types: bar, line, pie, doughnut, radar, scatter, bubble, polarArea. Built for AI agent report pipelines \u2014 POST your data, receive a chart image. One API key covers both Screenshot and Chart Rendering APIs (Visual Infrastructure Bundle).", "tags": ["Visual Infrastructure"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["type", "data"], "properties": {"type": {"type": "string", "enum": ["bar", "line", "pie", "doughnut", "radar", "scatter", "bubble", "polarArea"], "description": "Chart type", "example": "bar"}, "data": {"type": "object", "description": "Chart.js data object with labels and datasets", "example": {"labels": ["Jan", "Feb", "Mar", "Apr", "May"], "datasets": [{"label": "Revenue", "data": [12000, 19000, 15000, 22000, 28000], "backgroundColor": "#4f46e5"}]}}, "options": {"type": "object", "description": "Chart.js options object (titles, scales, legend, etc.)", "example": {"plugins": {"title": {"display": true, "text": "Monthly Revenue"}}}}, "width": {"type": "integer", "description": "Output width in pixels (100\u20132400)", "default": 800, "minimum": 100, "maximum": 2400}, "height": {"type": "integer", "description": "Output height in pixels (100\u20131600)", "default": 450, "minimum": 100, "maximum": 1600}, "format": {"type": "string", "enum": ["png", "jpeg"], "default": "png", "description": "Output image format"}, "quality": {"type": "integer", "description": "JPEG quality 1\u2013100 (ignored for PNG)", "default": 90, "minimum": 1, "maximum": 100}, "background": {"type": "string", "description": "Background CSS color or 'transparent' (PNG only)", "default": "#ffffff", "example": "#0d1117"}}}}}}, "responses": {"200": {"description": "Chart image", "content": {"image/png": {"schema": {"type": "string", "format": "binary"}}, "image/jpeg": {"schema": {"type": "string", "format": "binary"}}}}, "400": {"description": "Invalid chart config", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RateLimitError"}}}}}, "security": [{"apiKey": []}]}}, "/api/html2image": {"post": {"operationId": "renderHtmlToImage", "summary": "Convert HTML/CSS to an image", "description": "Renders HTML content in a headless Chromium browser and returns PNG, JPEG, or WebP. Send HTML as POST body with Content-Type: text/html. Max 50KB.", "parameters": [{"name": "width", "in": "query", "required": false, "description": "Viewport width in pixels", "schema": {"type": "integer", "default": 800, "maximum": 1920}, "example": 800}, {"name": "height", "in": "query", "required": false, "description": "Viewport height in pixels", "schema": {"type": "integer", "default": 600, "maximum": 1080}, "example": 600}, {"name": "format", "in": "query", "required": false, "description": "Output format: png, jpeg, or webp", "schema": {"type": "string", "enum": ["png", "jpeg", "webp"], "default": "png"}, "example": "png"}, {"name": "scale", "in": "query", "required": false, "description": "Device scale factor (1, 2, or 3)", "schema": {"type": "integer", "enum": [1, 2, 3], "default": 1}, "example": 2}, {"name": "quality", "in": "query", "required": false, "description": "Image quality for JPEG/WebP (1-100)", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 80}, "example": 90}, {"name": "dark_mode", "in": "query", "required": false, "description": "Emulate dark color scheme", "schema": {"type": "boolean", "default": false}, "example": true}], "requestBody": {"required": true, "description": "HTML content to render (max 50KB)", "content": {"text/html": {"schema": {"type": "string"}}}}, "responses": {"200": {"description": "Rendered image in the requested format", "content": {"image/png": {"schema": {"type": "string", "format": "binary"}}, "image/jpeg": {"schema": {"type": "string", "format": "binary"}}, "image/webp": {"schema": {"type": "string", "format": "binary"}}}}}}}, "/api/perf": {"get": {"operationId": "checkPerformance", "summary": "Check page performance and get a performance grade", "description": "Measures response time, page size, HTTP headers, redirect behavior, and returns a performance grade (A+/A/B/C/F) based on speed, compression, and caching. Rate limits: free 50/day, Starter 200/day, Pro 1000/day, Business 5000/day.", "parameters": [{"name": "url", "in": "query", "required": true, "description": "The URL to measure", "schema": {"type": "string", "example": "https://example.com"}}, {"name": "follow_redirects", "in": "query", "required": false, "description": "Follow HTTP redirects (default: true)", "schema": {"type": "string", "enum": ["true", "false"], "default": "true"}, "example": true}], "responses": {"200": {"description": "Performance metrics with grade.", "content": {"application/json": {"schema": {"type": "object", "properties": {"url": {"type": "string"}, "final_url": {"type": "string"}, "status_code": {"type": "integer"}, "grade": {"type": "string", "enum": ["A+", "A", "B", "C", "F"], "description": "Performance grade based on speed, compression, caching, and size"}, "grade_issues": {"type": "array", "items": {"type": "string"}}, "response_time_ms": {"type": "number"}, "response_size_bytes": {"type": "integer"}, "content_type": {"type": "string"}, "server": {"type": "string"}, "headers": {"type": "object", "additionalProperties": {"type": "string"}}, "redirected": {"type": "boolean"}, "timestamp": {"type": "string", "format": "date-time"}}}}}}}}}, "/api/techstack": {"get": {"operationId": "detectTechStack", "summary": "Detect the technology stack of any website", "description": "Identifies frameworks, CMS, analytics, CDNs, and JavaScript libraries from HTTP headers and HTML content. Rate limits: free 50/day, Starter 200/day, Pro 1000/day, Business 5000/day.", "parameters": [{"name": "url", "in": "query", "required": true, "description": "The URL to analyze", "schema": {"type": "string", "example": "https://dev.to"}}], "responses": {"200": {"description": "Detected technologies organized by category.", "content": {"application/json": {"schema": {"type": "object", "properties": {"url": {"type": "string"}, "technologies": {"type": "object"}, "headers": {"type": "object"}}}}}}}}}, "/api/ssl": {"get": {"operationId": "checkSSLCertificate", "summary": "Check SSL certificate and get security grade", "description": "Returns a security grade (A+/A/B/C/F), certificate validity, expiry date, issuer, Subject Alternative Names, protocol version, cipher suite, and connection time.", "parameters": [{"name": "domain", "in": "query", "required": true, "description": "Domain name to check (without https://)", "schema": {"type": "string", "example": "github.com"}}], "responses": {"200": {"description": "SSL certificate details and validity.", "content": {"application/json": {"schema": {"type": "object", "properties": {"domain": {"type": "string"}, "valid": {"type": "boolean"}, "grade": {"type": "string", "enum": ["A+", "A", "B", "C", "F"], "description": "Security grade: A+ (TLSv1.3+256bit+30d), A (TLSv1.2+strong), B (expiring <7d), C (TLS1.1/weak cipher), F (expired/SSLv3)"}, "grade_issues": {"type": "array", "items": {"type": "string"}, "description": "Issues affecting the grade"}, "subject": {"type": "object", "properties": {"common_name": {"type": "string"}, "organization": {"type": "string"}}}, "issuer": {"type": "object", "properties": {"common_name": {"type": "string"}, "organization": {"type": "string"}}}, "validity": {"type": "object", "properties": {"issued": {"type": "string", "format": "date-time"}, "expires": {"type": "string", "format": "date-time"}, "days_remaining": {"type": "integer"}}}, "subject_alt_names": {"type": "array", "items": {"type": "string"}}, "protocol": {"type": "string"}, "cipher": {"type": "object", "properties": {"name": {"type": "string"}, "bits": {"type": "integer"}}}, "serial_number": {"type": "string"}, "connection_time_ms": {"type": "number"}, "timestamp": {"type": "string", "format": "date-time"}}}}}}}}}, "/api/screenshot/batch": {"post": {"summary": "Batch Screenshot Capture", "description": "Capture screenshots of up to 10 URLs in a single request. Returns base64-encoded images in JSON. Requires an API key.", "tags": ["Screenshot"], "security": [{"ApiKeyAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["urls"], "properties": {"urls": {"type": "array", "items": {"type": "string", "format": "uri"}, "minItems": 1, "maxItems": 10, "description": "Array of URLs to screenshot"}, "format": {"type": "string", "enum": ["png", "jpeg", "webp"], "default": "png"}, "width": {"type": "integer", "minimum": 320, "maximum": 1920, "default": 1280}, "height": {"type": "integer", "minimum": 240, "maximum": 1080, "default": 720}, "full_page": {"type": "boolean", "default": false}, "delay": {"type": "integer", "minimum": 0, "maximum": 10000, "default": 0}, "block_ads": {"type": "boolean", "default": false}}}}}}, "responses": {"200": {"description": "Batch results with base64-encoded images", "content": {"application/json": {"schema": {"type": "object", "properties": {"results": {"type": "array", "items": {"type": "object", "properties": {"url": {"type": "string"}, "image": {"type": "string", "description": "Base64-encoded image"}, "format": {"type": "string"}, "error": {"type": "string", "nullable": true}}}}, "total": {"type": "integer"}, "successful": {"type": "integer"}, "failed": {"type": "integer"}}}}}}, "401": {"description": "API key required"}, "429": {"description": "Rate limit exceeded (2 batch requests per minute)"}}}}, "/api/keys": {"post": {"operationId": "createApiKey", "summary": "Create an API key for higher rate limits", "description": "Creates an API key. Anonymous keys (no email) are activated instantly with 20 requests/day. Email keys require email verification: a verification link is sent to the provided email, and the key is activated only after clicking the link. Verified keys get 50 requests/day. Include the key as X-API-Key header in subsequent requests.", "tags": ["Utility"], "requestBody": {"required": false, "content": {"application/json": {"schema": {"type": "object", "properties": {"email": {"type": "string", "format": "email", "description": "Optional email for higher rate limits (50/day vs 20/day)"}}}, "examples": {"anonymous": {"summary": "Anonymous key (20 req/day)", "value": {}}, "with_email": {"summary": "Email key (50 req/day, requires verification)", "value": {"email": "you@example.com"}}}}}}, "responses": {"200": {"description": "API key created successfully", "content": {"application/json": {"schema": {"type": "object", "properties": {"api_key": {"type": "string", "description": "Your API key \u2014 include as X-API-Key header"}, "rate_limit": {"type": "string", "description": "Your daily request limit"}, "quick_start": {"type": "object", "description": "Ready-to-use URLs and curl commands"}}}}}}}}}, "/api/usage": {"get": {"operationId": "getApiUsage", "summary": "Check API key usage and rate limit status", "description": "Returns current period call count, remaining daily quota, tier name, and key status. Supports Bearer auth, X-API-Key header, or ?key= query parameter.", "tags": ["Utility"], "security": [{"ApiKeyAuth": []}], "parameters": [{"name": "key", "in": "query", "required": false, "description": "API key (alternative to X-API-Key header or Authorization: Bearer header)", "schema": {"type": "string"}, "example": "hf_abc123def456"}], "responses": {"200": {"description": "Usage statistics for the authenticated API key", "content": {"application/json": {"schema": {"type": "object", "properties": {"calls_this_period": {"type": "integer", "description": "Total API calls made in the current 30-day period"}, "rate_limit_remaining_today": {"type": "integer", "description": "Remaining requests available today"}, "status": {"type": "string", "enum": ["active", "inactive", "suspended"], "description": "Key activation status"}, "tier": {"type": "string", "enum": ["free", "starter", "pro", "business"], "description": "Current subscription tier"}, "daily_limit": {"type": "integer", "description": "Daily request quota: free=50, starter=200, pro=1000, business=5000"}}}}}}, "401": {"description": "No API key provided or key invalid"}}}}, "/api/verify": {"get": {"operationId": "verifyEmailKey", "summary": "Verify an email-linked API key", "description": "Activates an API key created with an email address. The verification link in the confirmation email points to this endpoint with a token parameter. Once verified, the key is activated and the daily limit is upgraded.", "tags": ["Utility"], "parameters": [{"name": "token", "in": "query", "required": true, "description": "Verification token from the confirmation email", "schema": {"type": "string"}, "example": "verify_abc123def456"}], "responses": {"200": {"description": "Key successfully activated", "content": {"text/html": {"schema": {"type": "string", "description": "HTML confirmation page"}}}}, "302": {"description": "Redirects to confirmation page after activation"}, "400": {"description": "Invalid or expired token"}}}}, "/api/health": {"get": {"summary": "Health Check & Service Discovery", "description": "Returns server status, uptime, and a directory of all available API endpoints. No authentication required.", "tags": ["Utility"], "responses": {"200": {"description": "Server health status", "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string", "example": "ok"}, "uptime_seconds": {"type": "integer"}, "uptime_human": {"type": "string", "example": "24h 30m"}, "apis": {"type": "object", "description": "Map of API names to endpoint paths"}, "docs": {"type": "string"}, "pricing": {"type": "string"}, "openapi": {"type": "string"}}}}}}}}}, "/api/screenshot/queue": {"post": {"summary": "Enqueue an async screenshot job", "description": "Submit a screenshot job to the async queue. Returns a job_id immediately. Use GET /api/screenshot/status/{job_id} to poll for completion, or provide a webhook_url for push delivery. Requires a verified API key (Pro tier or higher). Designed for AI agent pipelines and batch processing workflows.", "tags": ["Screenshot"], "security": [{"ApiKeyAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["url"], "properties": {"url": {"type": "string", "description": "The URL to screenshot", "example": "https://example.com"}, "format": {"type": "string", "enum": ["webp", "png", "jpeg"], "default": "webp", "description": "Output image format"}, "width": {"type": "integer", "default": 1280, "description": "Viewport width in pixels"}, "webhook_url": {"type": "string", "description": "Optional URL to POST the result to when complete. Body will be the same as GET /api/screenshot/result/{job_id}"}}}}}}, "responses": {"202": {"description": "Job accepted and queued", "content": {"application/json": {"schema": {"type": "object", "properties": {"job_id": {"type": "string", "description": "Unique job identifier", "example": "job_abc123"}, "status": {"type": "string", "example": "queued"}, "message": {"type": "string", "example": "Job queued. Poll /api/screenshot/status/{job_id} or await webhook delivery."}}}}}}, "401": {"description": "Missing or invalid API key"}, "402": {"description": "Async queue requires Pro tier or higher"}}}}, "/api/screenshot/status/{job_id}": {"get": {"summary": "Check async screenshot job status", "description": "Poll for the status of a queued screenshot job. Returns current status (queued, processing, completed, failed) and result URL when complete.", "tags": ["Screenshot"], "security": [{"ApiKeyAuth": []}], "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string"}, "description": "Job ID returned from POST /api/screenshot/queue", "example": "job_abc123"}], "responses": {"200": {"description": "Job status", "content": {"application/json": {"schema": {"type": "object", "properties": {"job_id": {"type": "string"}, "status": {"type": "string", "enum": ["queued", "processing", "completed", "failed"]}, "created_at": {"type": "string", "format": "date-time"}, "completed_at": {"type": "string", "format": "date-time", "nullable": true}, "result_url": {"type": "string", "nullable": true, "description": "URL to fetch result when status=completed"}}}}}}, "404": {"description": "Job not found"}}}}, "/api/screenshot/result/{job_id}": {"get": {"summary": "Retrieve async screenshot result", "description": "Retrieve the completed screenshot result for a finished job. Returns base64-encoded image data in JSON format, matching the sync /api/screenshot response structure.", "tags": ["Screenshot"], "security": [{"ApiKeyAuth": []}], "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string"}, "description": "Job ID returned from POST /api/screenshot/queue", "example": "job_abc123"}], "responses": {"200": {"description": "Screenshot result", "content": {"application/json": {"schema": {"type": "object", "properties": {"job_id": {"type": "string"}, "url": {"type": "string"}, "image": {"type": "string", "description": "Base64-encoded image"}, "format": {"type": "string"}, "width": {"type": "integer"}, "height": {"type": "integer"}}}}}}, "202": {"description": "Job not yet complete \u2014 retry after polling /api/screenshot/status/{job_id}"}, "404": {"description": "Job not found"}}}}}, "security": [{"ApiKeyAuth": []}, {}], "tags": [{"name": "Screenshot", "description": "Sync, batch, and async screenshot capture"}, {"name": "SEO & Analysis", "description": "SEO auditing, dead link detection, tech stack detection"}, {"name": "Infrastructure", "description": "SSL checks, performance metrics, API key management"}], "components": {"securitySchemes": {"ApiKeyAuth": {"type": "apiKey", "in": "header", "name": "X-API-Key", "description": "API key for higher rate limits. Also accepted as ?key= query param or Authorization: Bearer header. Tiers: free 50/day (email-verified key, no payment), Starter 200/day ($4/30 days), Pro 1000/day ($9/30 days), Business 5000/day ($29/30 days). Get a free key: POST /api/keys with {\"email\": \"you@example.com\"}. Upgrade: https://hermesforge.dev/pricing"}}}}