{"openapi":"3.1.0","info":{"title":"Shotium API","version":"1.0.0","summary":"Screenshot and Open Graph image rendering.","description":"Turn any public URL into an image, or render a 1200×630 Open Graph card from a typed template. Every endpoint returns image bytes on success and RFC 9457 problem+json on failure. A render is billed only when an image is successfully delivered; failed renders never bill.","contact":{"name":"Shotium support","email":"support@shotium.com","url":"https://shotium.com/contact"},"termsOfService":"https://shotium.com/terms","license":{"name":"Proprietary","url":"https://shotium.com/terms"}},"servers":[{"url":"https://api.shotium.com/v1","description":"Production"}],"externalDocs":{"description":"API reference","url":"https://shotium.com/docs"},"tags":[{"name":"Rendering","description":"Screenshot and OG image endpoints."},{"name":"Account","description":"Key introspection."}],"paths":{"/screenshot":{"get":{"tags":["Rendering"],"operationId":"takeScreenshot","summary":"Render any public URL to an image","description":"Renders the target URL in a real browser and returns the image bytes. Identical parameter sets are served from a 24-hour cache (cache hits are billed as renders).","security":[{"bearerAuth":[]}],"parameters":[{"name":"url","in":"query","required":true,"description":"The http(s) URL to render. Fragments are ignored. URLs resolving to private network ranges are rejected.","schema":{"type":"string","format":"uri","minLength":1,"maxLength":2048},"example":"https://example.com"},{"name":"width","in":"query","description":"Viewport width in pixels.","schema":{"type":"integer","minimum":1,"maximum":3840,"default":1280}},{"name":"height","in":"query","description":"Viewport height in pixels. Ignored for the captured height when full_page is true.","schema":{"type":"integer","minimum":1,"maximum":2160,"default":800}},{"name":"full_page","in":"query","description":"Capture the entire scroll height instead of just the viewport, up to 20000px.","schema":{"type":"string","enum":["true","false","1","0"],"default":"false"}},{"name":"format","in":"query","description":"Output image format.","schema":{"type":"string","enum":["png","jpeg","webp"],"default":"png"}},{"name":"quality","in":"query","description":"Encoder quality for lossy formats. Ignored when format is png.","schema":{"type":"integer","minimum":1,"maximum":100,"default":80}}],"responses":{"200":{"description":"Rendered image bytes.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"invalid_params or invalid_url.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"unauthorized — missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"blocked_target — the URL resolves to a blocked network range.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"rate_limited or quota_exceeded.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}},"502":{"description":"render_failed or storage_error. Not billed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"504":{"description":"render_timeout — the render did not finish within 30 seconds. Not billed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/og-image":{"post":{"tags":["Rendering"],"operationId":"createOgImage","summary":"Render an Open Graph image from a template","description":"Renders a 1200×630 image from a built-in template. Best for build-time generation; for images embedded in public HTML use the signed-URL form of GET /og-image instead. The JSON body must declare a Content-Length of at most 16384 bytes; chunked request bodies are rejected.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OgImageRequest"},"example":{"template":"blog","params":{"title":"Shipping fast without breaking things","author":"Ada L."},"format":"png"}}}},"responses":{"200":{"description":"Rendered 1200×630 image bytes.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"invalid_params — unknown template or template parameters failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"unauthorized — missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"rate_limited or quota_exceeded.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}},"502":{"description":"render_failed or storage_error. Not billed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"504":{"description":"render_timeout. Not billed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Rendering"],"operationId":"getSignedOgImage","summary":"Render an Open Graph image from a signed URL","description":"Authenticated by HMAC signature rather than an API key, so the URL is safe to embed in public HTML. Build the canonical query by dropping sig, sorting keys in byte order, RFC 3986-encoding each key and value, and joining as k=v&k=v; then sig = hex(HMAC-SHA256(canonical, signing_secret)). Responses carry Cache-Control: public, max-age=86400, immutable so the CDN edge absorbs crawler traffic — edge hits cost nothing. Template parameters are passed as additional query parameters.","security":[],"parameters":[{"name":"template","in":"query","required":true,"description":"Template id.","schema":{"type":"string","enum":["blog","product","podcast","event","minimal"]}},{"name":"uid","in":"query","required":true,"description":"Your user id, issued alongside your API key.","schema":{"type":"string","format":"uuid"}},{"name":"sig","in":"query","required":true,"description":"Hex-encoded HMAC-SHA256 of the canonical query string.","schema":{"type":"string"}},{"name":"format","in":"query","description":"Output image format.","schema":{"type":"string","enum":["png","jpeg"],"default":"png"}}],"responses":{"200":{"description":"Rendered 1200×630 image bytes.","headers":{"Cache-Control":{"description":"Always public, max-age=86400, immutable.","schema":{"type":"string"}}},"content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"invalid_params — unknown template, duplicate query keys, or parameters failed validation.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"unauthorized — missing uid/sig or signature verification failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"rate_limited or quota_exceeded.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}},"502":{"description":"render_failed or storage_error. Not billed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"504":{"description":"render_timeout. Not billed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/me":{"get":{"tags":["Account"],"operationId":"getCurrentKey","summary":"Verify an API key","description":"Validates the key and returns its metadata. Renders nothing, bills nothing, and does not touch your quota — the standard health check for stored credentials.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The key is valid.","content":{"application/json":{"schema":{"type":"object","required":["key_prefix","key_name"],"properties":{"key_prefix":{"type":"string","description":"Non-secret prefix identifying the key."},"key_name":{"type":["string","null"],"description":"Label given to the key when it was issued."}}},"example":{"key_prefix":"sk_live_a1b2c3","key_name":"production"}}}},"401":{"description":"unauthorized — missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"rate_limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Send your API key as `Authorization: Bearer sk_live_…`. Keys are revocable from the account page."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details. `type` is a stable enum you can branch on programmatically.","required":["type","title","status"],"properties":{"type":{"type":"string","enum":["unauthorized","invalid_params","invalid_url","blocked_target","render_timeout","render_failed","storage_error","quota_exceeded","rate_limited","internal_error"]},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"}},"example":{"type":"quota_exceeded","title":"Monthly quota exceeded","status":429,"detail":"monthly quota and credits exhausted; upgrade or buy credits at https://shotium.com/pricing"}},"OgImageRequest":{"type":"object","required":["template"],"properties":{"template":{"type":"string","enum":["blog","product","podcast","event","minimal"],"description":"Template id. See https://shotium.com/og-templates for each template's parameters."},"params":{"type":"object","description":"Template-specific parameters. Values are strings, max 2048 characters each.","additionalProperties":{"type":"string","maxLength":2048},"default":{}},"format":{"type":"string","enum":["png","jpeg"],"default":"png"}}}}}}