API Reference

Complete reference for all getSnap.dev endpoints.

Complete endpoint index

30 operations across 27 unique paths. All endpoints live under https://api.getsnap.dev and require an X-API-Key header unless noted. The tables below link to detailed reference sections on this page, the dedicated teams doc and referrals doc, or the fully interactive Swagger UI.

Your API key is shown once. It appears in the response to POST /v1/signup and in your welcome email, and nowhere else. We store only a SHA-256 hash of it, which is enough to recognise the key you send but cannot be turned back into the key — so nobody, including us, can retrieve it later. Save it when you receive it. If you lose it, email support@getsnap.dev and we will revoke the old key and issue a new one.

Capture (7)

EndpointMethodDescription
/v1/screenshotPOSTCapture a screenshot or PDF (sync / async / binary).
/v1/screenshot/:idGETPoll async screenshot status.
/v1/batchPOSTBatch capture up to 100 URLs in one request.
/v1/videoPOSTScrolling video (MP4 or GIF), 2–30 seconds.
/v1/og-imagePOST1200×630 Open Graph / Twitter Card image with title + subtitle overlay.
/v1/diffPOSTVisual regression diff between two URLs (pixelmatch).
/v1/auditPOSTWCAG 2.0/2.1/2.2 accessibility audit (axe-core).

Signed render links (2)

EndpointMethodDescription
/v1/render-linkPOSTGenerate a signed URL for use in <img> tags.
/v1/renderGETServe screenshot from a signed URL (no auth header needed).

Scheduled captures (7)

EndpointMethodDescription
/v1/schedulesPOSTCreate a cron-driven scheduled capture.
/v1/schedulesGETList your scheduled captures.
/v1/schedules/:idGETFetch a scheduled capture.
/v1/schedules/:idPATCHUpdate cron / options / webhook / active flag.
/v1/schedules/:idDELETEDelete a schedule.
/v1/schedules/:id/runPOSTTrigger a schedule immediately.
/v1/schedules/:id/runsGETRecent execution history (last 100).

Teams (11) — full reference at /docs/teams.html

EndpointMethodDescription
/v1/teamsPOSTCreate a new team (hoists creator's plan).
/v1/teamsGETList teams the caller belongs to.
/v1/teams/:id/membersGETList members with roles + join dates.
/v1/teams/:id/invitesPOSTInvite by email (owner / admin). 7-day TTL.
/v1/teams/acceptPOSTAccept an invite token.
/v1/teams/:id/leavePOSTLeave a team (non-owner).
/v1/teams/:id/transfer-ownershipPOSTTransfer ownership to another member. v1.12
/v1/teams/:idDELETEDissolve the team + cancel its Stripe sub. v1.12
/v1/teams/:id/checkoutPOSTStart Stripe Checkout for team-owned subscription. v1.13
/v1/teams/:id/portalPOSTStripe billing portal for the team. v1.13
/v1/teams/:id/billingGETTeam subscription status + next invoice date. v1.13

Personal billing (2)

EndpointMethodDescription
/v1/upgradePOSTStripe Checkout URL for a paid plan (or portal URL if already subscribed).
/v1/billingPOSTStripe billing portal URL for the caller's personal subscription.

Growth (1) — full reference at /docs/referrals.html

EndpointMethodDescription
/v1/referralsGETReferral code + share URL + aggregate stats + individual referrals.

Ops (5)

EndpointMethodDescription
/v1/usageGETCurrent-period usage + monthly limit + plan.
/v1/healthGETHealth check (unauthenticated).
/v1/signupPOSTCreate free account + API key. Optional plan upgrades via Checkout in the same call.
/v1/contactPOSTSend a support message (rate-limited per IP).
/v1/webhook/stripePOSTStripe webhook receiver (idempotent). Public but signature-verified.

The authoritative source for every endpoint's request / response schema is the Swagger UI. It's generated from the same Zod schemas that validate every request, so if the docs and the server ever disagree, Swagger UI is right. This page walks through the highest-value capture endpoints in narrative form with runnable examples; jump to Swagger for exhaustive per-field docs.

Capture Screenshot

POST /v1/screenshot

Captures a screenshot or PDF of a URL or HTML content. Returns either a CDN URL or raw binary data.

Request Headers

HeaderTypeDescription
x-api-keystring requiredYour API key
Content-Typestring requiredMust be application/json

Request Body

Note: Either url or html must be provided. You cannot use both in the same request.
ParameterTypeDefaultDescription
urlstring-The URL to capture. Must be a valid HTTP/HTTPS URL.
htmlstring-Raw HTML content to render and capture. Max 500KB. Useful for OG images, invoices, email previews.
formatstringpngOutput format: png, jpg, jpeg, webp, avif, or pdf
viewport_widthnumber1280Viewport width in pixels (320-3840)
viewport_heightnumber720Viewport height in pixels (200-2160)
full_pagebooleanfalseCapture the entire scrollable page
devicestringdesktopDevice emulation: desktop, mobile, or tablet
device_scale_factornumber1Device pixel ratio (0.5-3). Use 2 for Retina/HiDPI screenshots.
delaynumber0Wait time in ms before capture (0-10000). Useful for JS-rendered pages.
cssstring""Custom CSS to inject before capture (max 10KB)
jsstring""Custom JavaScript to execute before capture (max 10KB). Runs via page.evaluate().
dark_modebooleanfalseEmulate prefers-color-scheme: dark
qualitynumber80Image quality 1-100 (applies to JPG/WebP only)
remove_popupsbooleantrueRemove cookie banners, popups, chat widgets, and overlays (90+ selectors)
block_adsbooleantrueBlock ad network requests (100+ domains including DoubleClick, Taboola, Outbrain, Criteo, etc.)
selectorstring""CSS selector to capture a specific element instead of the full page
headersobject{}Custom HTTP headers to send with the request. Object of key: value string pairs.
cookiesarray[]Cookies to set before navigation. Array of objects with name, value, optional domain, path, httpOnly, secure. Max 50 cookies.
localestring""Browser locale (e.g. de-DE, fr-FR, ja-JP). Affects language headers and JS APIs.
timezonestring""IANA timezone ID (e.g. Europe/Berlin, America/New_York). Affects Date objects in page JS.
user_agentstring""Custom User-Agent string for the browser request.
lazy_loadbooleanfalseAuto-scroll the page to trigger lazy-loaded images before capture. Scrolls in 300px increments then returns to top.
wait_for_selectorstring""CSS selector to wait for before capture (up to 15s). Useful for SPAs and dynamically loaded content.
wait_for_network_idlebooleantrueWait for network to be idle before capture. Disable for pages with persistent connections.
hide_selectorsstring[][]Array of CSS selectors to hide (display:none) before capture. E.g. [".banner", "#cookie-popup"]
remove_selectorsstring[][]Array of CSS selectors to remove from the DOM before capture. Elements are completely deleted.
omit_backgroundbooleanfalseTransparent background for PNG screenshots. The page background becomes transparent.
click_selectorstring""CSS selector to click before capture (e.g. expand a menu). Waits up to 5s for the element.
scroll_to_selectorstring""CSS selector to scroll into view before capture.
extract_textbooleanfalseExtract the page's visible text content (innerText). Returned in extracted_text field.
extract_htmlbooleanfalseExtract the page's full HTML. Returned in extracted_html field.
response_typestringurlurl returns CDN link, binary returns raw image/PDF bytes
webhook_urlstring-If provided, the screenshot is captured asynchronously. Returns 202 immediately with a request_id. The result is POSTed to this URL when ready (3 retries, exponential backoff). Use GET /v1/screenshot/:request_id to poll status.
s3_uploadobject-Upload the screenshot to your own S3-compatible bucket. Object with: access_key_id, secret_access_key, bucket, region (required), endpoint (for DO Spaces, R2), path (key prefix), acl (e.g. public-read).
Rendering & emulation
reduced_motionbooleanfalseEmulate prefers-reduced-motion: reduce. Freezes CSS animations and transitions.
media_typestring""Emulate CSS media type. "" (default) uses screen; pass print to render as if printing.
click_acceptbooleanfalseBest-effort auto-click cookie-consent Accept buttons (OneTrust, Cookiebot, FundingChoices, generic "Accept all" heuristics).
press_escapebooleanfalseSend an Escape keypress after page load to dismiss modals.
bypass_cspbooleanfalseDisable the page's Content-Security-Policy. Required by some pages that block inline CSS/JS injection.
fail_if_selector_missingbooleanfalseReturn 500 capture_failed when wait_for_selector, click_selector, scroll_to_selector, or selector can't be found. By default missing selectors are silently ignored.
Request blocking
block_imagesbooleanfalseAbort all image requests. Great for text-heavy captures and speed.
block_fontsbooleanfalseAbort all web-font requests.
block_scriptsbooleanfalseAbort all <script> requests (renders a JS-free version of the page).
block_framesbooleanfalseAbort all <iframe> requests.
block_urlsstring[][]Array of URL substrings or wildcard patterns to block (e.g. ["*.chat.com/*", "tracker"]). Max 30 entries.
Region & full-page controls
clipobjectnullCapture a specific rectangle. Object with x, y, width, height in CSS pixels. Overrides full_page and selector.
full_page_max_heightnumber0Hard cap on full_page image height in pixels. 0 means no cap. Use to guard against infinite-scroll pages.
full_page_slicesbooleanfalseSplit the full-page capture into vertical strips (great for AI vision workflows that have a max image height). Returns a slices array in the response.
full_page_slice_heightnumber4000Max height per slice in pixels (200-16000).
full_page_slice_overlap_heightnumber0Pixel overlap between adjacent slices (0-2000). Useful when downstream OCR/vision models need context around the seam.
Data extraction
extract_metadatabooleanfalseReturn an extracted_metadata object with title, favicon, open_graph (map of all og:* tags), fonts (list of actually-loaded font families), http_status, http_status_text, and http_headers.
Response shape
attachment_namestring""Filename hint. Sets Content-Disposition: attachment; filename="<name>" when response_type: "binary". Also drives the user-S3 filename.
PDF options (only when format: "pdf")
pdf_page_sizestringA4Paper size: A0-A6, Letter, Legal, Tabloid, Ledger.
pdf_orientationstringportraitportrait or landscape.
pdf_margin_topstring20pxTop margin as a CSS unit string (e.g. 20px, 1cm, 0.5in).
pdf_margin_rightstring20pxRight margin.
pdf_margin_bottomstring20pxBottom margin.
pdf_margin_leftstring20pxLeft margin.
pdf_backgroundbooleantrueInclude CSS backgrounds when printing.
pdf_scalenumber1Rendering scale (0.1-2.0).
pdf_show_headerbooleanfalseRender a header on each page.
pdf_headerstring""HTML template for the header. Uses Chromium's template syntax: <span class="pageNumber"></span>, <span class="totalPages"></span>, <span class="title"></span>, <span class="url"></span>, <span class="date"></span>.
pdf_show_footerbooleanfalseRender a footer on each page.
pdf_footerstring""HTML template for the footer (same syntax as header).
pdf_page_rangestring""Page range filter (e.g. 1-5,8,11-13).
pdf_titlestring""PDF document title metadata (visible in most PDF viewers).
pdf_subjectstring""PDF document subject metadata.
pdf_authorstring""PDF document author metadata.
pdf_keywordsstring""PDF document keywords metadata (comma or space separated).
pdf_creatorstring""PDF document creator metadata.
Proxy / geo routing
proxy_urlstring""Bring-your-own proxy URL. Supports http, https, socks5, socks5h. Credentials may live in the URL userinfo (http://user:pass@host:port) or be split into proxy_username/proxy_password. Wins over proxy_country.
proxy_usernamestring""Proxy auth username. Overrides any userinfo in proxy_url.
proxy_passwordstring""Proxy auth password. Overrides any userinfo in proxy_url.
proxy_countrystring""Managed geo pool: ISO 3166-1 alpha-2 country code (US, DE, JP, etc.). Requires the deployment to have PROXY_URL_TEMPLATE configured. Returns 500 proxy_pool_not_configured when the pool is not enabled.

HTML Rendering Example

curl -X POST https://api.getsnap.dev/v1/screenshot \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<html><body style=\"padding:40px;font-family:sans-serif\"><h1>Hello World</h1><p>Generated by getSnap.dev</p></body></html>",
    "viewport_width": 1200,
    "viewport_height": 630,
    "format": "png"
  }'

Retina Screenshot Example

curl -X POST https://api.getsnap.dev/v1/screenshot \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://stripe.com",
    "device_scale_factor": 2,
    "format": "png"
  }'

Custom JS Injection Example

curl -X POST https://api.getsnap.dev/v1/screenshot \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "js": "document.querySelector(\".sidebar\").style.display = \"none\";"
  }'

Authenticated Page with Cookies

curl -X POST https://api.getsnap.dev/v1/screenshot \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.example.com/dashboard",
    "cookies": [
      {"name": "session_id", "value": "abc123", "domain": "app.example.com"},
      {"name": "auth_token", "value": "xyz789"}
    ],
    "headers": {"Authorization": "Bearer your-token"}
  }'

Localized Screenshot

curl -X POST https://api.getsnap.dev/v1/screenshot \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://google.com",
    "locale": "de-DE",
    "timezone": "Europe/Berlin"
  }'

Response (URL mode)

200 OK
{
  "url": "https://getsnap-screenshots.fra1.cdn.digitaloceanspaces.com/screenshots/a1b2c3d4/req_abc123.png",
  "cached": false,
  "request_id": "req_abc123",
  "response_time_ms": 2340
}

Additional fields appear conditionally:

Response (Binary mode)

200 OK

Returns raw bytes with the appropriate Content-Type header (image/png, image/jpeg, image/webp, image/avif, or application/pdf). When attachment_name is set, a Content-Disposition: attachment; filename="…" header is also sent so browsers offer a download prompt instead of rendering the image.

Response (Webhook mode)

202 Accepted
{
  "request_id": "req_abc123",
  "status": "pending",
  "message": "Screenshot is being captured. Result will be POSTed to your webhook_url.",
  "status_url": "https://api.getsnap.dev/v1/screenshot/req_abc123"
}

When the screenshot is ready, getSnap.dev will POST to your webhook_url:

{
  "event": "screenshot.completed",
  "request_id": "req_abc123",
  "url": "https://getsnap-screenshots.fra1.cdn.digitaloceanspaces.com/screenshots/a1b2c3d4/req_abc123.png",
  "cached": false,
  "response_time_ms": 6500
}

Batch Capture

POST /v1/batch

Capture screenshots of multiple URLs in a single request. Processes URLs sequentially and returns all results. Supports up to 100 URLs per batch.

Request Body

ParameterTypeDefaultDescription
urlsstring[] required-Array of URLs to capture (1-100 URLs)
All other parameters from POST /v1/screenshot are supported (format, viewport_width, device_scale_factor, block_ads, etc.) and apply to every URL in the batch.
webhook_urlstring-If provided, returns 202 immediately and POSTs all results when complete.

Example

curl -X POST https://api.getsnap.dev/v1/batch \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://stripe.com",
      "https://github.com",
      "https://example.com"
    ],
    "format": "png",
    "device_scale_factor": 2,
    "block_ads": true
  }'

Response (Synchronous)

200 OK
{
  "batch_id": "batch_abc123",
  "count": 3,
  "succeeded": 3,
  "failed": 0,
  "response_time_ms": 12500,
  "results": [
    {
      "url": "https://cdn.../screenshots/abc/req_1.png",
      "source_url": "https://stripe.com",
      "cached": false,
      "request_id": "req_1"
    },
    {
      "url": "https://cdn.../screenshots/def/req_2.png",
      "source_url": "https://github.com",
      "cached": false,
      "request_id": "req_2"
    },
    {
      "url": "https://cdn.../screenshots/ghi/req_3.png",
      "source_url": "https://example.com",
      "cached": false,
      "request_id": "req_3"
    }
  ]
}

Response (Async with webhook_url)

202 Accepted
{
  "batch_id": "batch_abc123",
  "status": "pending",
  "count": 3,
  "message": "Batch capture started. Results will be POSTed to your webhook_url.",
  "status_url": "https://api.getsnap.dev/v1/screenshot/batch_abc123"
}

Screenshot Status

GET /v1/screenshot/:request_id

Check the status of an async webhook screenshot or batch request. Only accessible with the same API key that created the request.

Response

200 OK
{
  "request_id": "req_abc123",
  "status": "completed",
  "created_at": "2026-08-25T12:00:00",
  "completed_at": "2026-08-25T12:00:07",
  "result": {
    "event": "screenshot.completed",
    "url": "https://getsnap-screenshots.fra1.cdn.digitaloceanspaces.com/screenshots/a1b2c3d4/req_abc123.png"
  }
}

Possible status values: pending, processing, completed, failed.

Error Responses

400 Bad Request
{
  "error": "validation_error",
  "message": "Invalid request body",
  "details": { "url": ["Either 'url' or 'html' must be provided"] }
}
402 Payment Required
{
  "error": "quota_exceeded",
  "message": "Monthly limit of 100 screenshots reached. Upgrade your plan.",
  "used": 100,
  "limit": 100
}
500 Internal Server Error
{
  "error": "capture_failed",
  "message": "Navigation timeout exceeded",
  "request_id": "req_abc123"
}

Capture Scrolling Video

POST /v1/video

Records a smoothly-scrolling capture of a URL as an MP4 or GIF. Uses Chrome DevTools' Page.screencast protocol for high-fps frame sampling and encodes the result with ffmpeg.

Credit cost: 1 credit per second of video (rounded up, minimum 1). A 5-second clip costs 5 credits; a 30-second clip costs 30.

Request Headers

HeaderTypeDescription
x-api-keystring requiredYour API key
Content-Typestring requiredMust be application/json

Request Body

ParameterTypeDefaultDescription
urlstring required-The URL to record. Must be a valid HTTP/HTTPS URL.
formatstringmp4mp4 or gif.
viewport_widthnumber1280Viewport width in pixels (320-1920).
viewport_heightnumber720Viewport height in pixels (200-1080).
devicestringdesktopdesktop, mobile, or tablet.
device_scale_factornumber1Retina scale (0.5-2). Capped smaller than screenshots for encoding tractability.
fpsnumber15Frames per second (10-30).
duration_msnumber5000Total duration in milliseconds (2000-30000).
qualitynumber701-100. Drives MP4 CRF (higher = better quality) or GIF palette generation.
remove_popupsbooleantrueRemove cookie banners / popups before recording.
block_adsbooleantrueBlock ad requests.
dark_modebooleanfalseEmulate prefers-color-scheme: dark.
delaynumber0Extra ms to wait after page load before recording begins (0-10000).
cssstring""Custom CSS to inject before recording.
jsstring""Custom JavaScript to execute before recording.
wait_for_selectorstring""Wait for a CSS selector before recording starts.
wait_for_network_idlebooleantrueWait for network idle before recording.
headers, cookies, locale, timezone, user_agent-Same semantics as the screenshot endpoint.
proxy_url, proxy_username, proxy_password, proxy_country-Same semantics as the screenshot endpoint.
response_typestringurlurl returns CDN link, binary returns raw MP4/GIF bytes.
attachment_namestring""Sets Content-Disposition: attachment; filename="…" on binary responses.
webhook_urlstring-If provided, returns 202 immediately and POSTs a video.completed event to this URL when done.
s3_uploadobject-Same shape as the screenshot endpoint.

Example

curl -X POST https://api.getsnap.dev/v1/video \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://stripe.com",
    "format": "mp4",
    "duration_ms": 8000,
    "fps": 20,
    "viewport_width": 1280,
    "viewport_height": 720,
    "quality": 75
  }'

Response (URL mode)

200 OK
{
  "url": "https://getsnap-screenshots.fra1.cdn.digitaloceanspaces.com/videos/ONE9iLdU/vid_ONE9iLdUbWKeijB6.mp4",
  "request_id": "vid_ONE9iLdUbWKeijB6",
  "format": "mp4",
  "duration_ms": 8000,
  "frame_count": 160,
  "fps": 20,
  "bytes": 2109440,
  "credits_charged": 8,
  "response_time_ms": 10432
}

Response (Webhook mode)

202 Accepted
{
  "request_id": "vid_ONE9iLdUbWKeijB6",
  "status": "pending",
  "message": "Video is being captured. Result will be POSTed to your webhook_url.",
  "credits_reserved": 8
}

When the video is ready, getSnap.dev will POST a video.completed event to your webhook (or video.failed on error) using the same delivery, retry, and HMAC-signature semantics as the schedules webhook.

Create Scheduled Capture

POST /v1/schedules

Creates a cron-driven scheduled capture. On each tick the worker runs takeScreenshot(), uploads to the CDN, optionally POSTs to your webhook, and logs a row in schedule_runs.

Request Body

ParameterTypeDefaultDescription
namestring required-Human-friendly name for the schedule (1-100 chars).
cronstring required-Standard 5- or 6-field UNIX cron expression. Validated with cron-parser. Examples: 0 9 * * MON-FRI, */15 * * * *, 0 0 1 * *.
timezonestringUTCIANA timezone the cron runs in (e.g. Europe/Berlin, America/New_York).
optionsobject required-The full /v1/screenshot options blob to use for every run. Must include url or html.
webhook_urlstring-Optional URL to POST each result to. Get a schedule.completed or schedule.failed event.
webhook_secretstring-Optional HMAC-SHA256 secret. When set, deliveries include X-Webhook-Signature: sha256=hex(hmac(secret, ts + "." + body)) and X-Webhook-Timestamp headers so you can verify authenticity.
is_activebooleantrueStart immediately. Pass false to create paused.

Example

curl -X POST https://api.getsnap.dev/v1/schedules \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "morning traffic dashboard",
    "cron": "0 9 * * MON-FRI",
    "timezone": "Europe/Berlin",
    "options": {
      "url": "https://dash.example.com",
      "format": "png",
      "full_page": true,
      "viewport_width": 1600
    },
    "webhook_url": "https://my-app.com/webhooks/getsnap",
    "webhook_secret": "a-strong-shared-secret-abcd1234"
  }'

Response

201 Created
{
  "id": "sched_SVVnySRhW-xbqYrE",
  "name": "morning traffic dashboard",
  "cron": "0 9 * * MON-FRI",
  "timezone": "Europe/Berlin",
  "options": { "url": "https://dash.example.com", "format": "png", "full_page": true, "viewport_width": 1600 },
  "webhook_url": "https://my-app.com/webhooks/getsnap",
  "has_webhook_secret": true,
  "is_active": true,
  "next_run_at": "2026-09-21T07:00:00.000Z",
  "created_at": "2026-09-20 07:05:26",
  "updated_at": "2026-09-20 07:05:26"
}

List Scheduled Captures

GET /v1/schedules

Returns every schedule owned by the API key that made the request. Sorted newest-first.

Response

200 OK
{
  "count": 2,
  "schedules": [ /* Schedule objects, same shape as Create response */ ]
}

Fetch Scheduled Capture

GET /v1/schedules/:id

Returns one schedule by ID. 404 if it doesn't exist or isn't owned by the requesting key.

Update Scheduled Capture

PATCH /v1/schedules/:id

Every top-level field is optional. Provide only what changes. Editing cron, timezone, or is_active is fully synchronized with the underlying queue: the old repeatable job is removed and a new one registered atomically.

To clear webhook_url or webhook_secret, pass an empty string.

Example (pause a schedule)

curl -X PATCH https://api.getsnap.dev/v1/schedules/sched_SVVnySRhW-xbqYrE \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'

Delete Scheduled Capture

DELETE /v1/schedules/:id

Deletes the schedule, unregisters it from the queue, and drops its schedule_runs history.

200 OK
{ "deleted": true, "id": "sched_SVVnySRhW-xbqYrE" }

Trigger Scheduled Capture Now

POST /v1/schedules/:id/run

Fires a one-off ad-hoc run of the schedule without touching the cron. Useful for testing a new schedule end-to-end before waiting for the next tick.

202 Accepted
{
  "schedule_id": "sched_SVVnySRhW-xbqYrE",
  "status": "queued",
  "message": "Capture queued; result will be delivered via webhook (if configured) and appear in /runs."
}

List Schedule Runs

GET /v1/schedules/:id/runs

Returns the last 100 execution records for a schedule (older rows are pruned automatically to keep history bounded).

200 OK
{
  "schedule_id": "sched_SVVnySRhW-xbqYrE",
  "count": 3,
  "runs": [
    {
      "id": "run_mX4RpcnmpBLYhdXd",
      "status": "completed",
      "result_url": "https://getsnap-screenshots.fra1.cdn.digitaloceanspaces.com/screenshots/scheduled/…/run_mX4RpcnmpBLYhdXd.png",
      "error": null,
      "response_ms": 1373,
      "webhook_status": 200,
      "started_at": "2026-09-20 07:09:04",
      "completed_at": "2026-09-20 07:09:05"
    }
  ]
}
POST /v1/render-link

Generate a signed render link URL. Use the returned URL in <img> tags, OG meta tags, or anywhere that accepts an image URL. The link serves screenshots via GET requests without exposing your API key.

Request Body

Accepts the same parameters as POST /v1/screenshot (url, html, format, viewport_width, etc.).

Response

200 OK
{
  "render_url": "https://api.getsnap.dev/v1/render?url=https%3A%2F%2Fexample.com&format=png&signature=abc123&key=pk_...",
  "message": "Use this URL in <img> tags or anywhere that accepts an image URL."
}

Render (Signed URL)

GET /v1/render

Serves a screenshot from a signed render link. Redirects to the CDN URL. No authentication header needed — the signature in the URL verifies the request. Generated by POST /v1/render-link.

Get Usage

GET /v1/usage

Returns your current billing period usage statistics.

Request Headers

HeaderTypeDescription
x-api-keystring requiredYour API key

Response

200 OK
{
  "period": "2026-08",
  "used": 847,
  "limit": 5000,
  "plan": "starter",
  "remaining": 4153
}

Health Check

GET /v1/health

Returns the API service status. No authentication required.

Response

200 OK
{
  "status": "ok",
  "timestamp": "2026-08-22T12:00:00.000Z",
  "version": "1.0.0"
}