ProofSnap ProofSnap API docs

ProofSnap API Documentation

The ProofSnap API loads any URL in a browser on ProofSnap's servers and returns a sealed evidence package: screenshot, page HTML, metadata, an evidence PDF and a SHA-256 manifest signed with RSA-4096 and anchored with OpenTimestamps. Base URL: https://api.getproofsnap.com/v1. Authenticate with an API key as a Bearer token. Documentation updated October 2026.

The examples below read the base URL from a shell variable: export PROOFSNAP_API_BASE=https://api.getproofsnap.com/v1

Getting started

  1. 1

    Create an API key

    Sign in to the Dashboard, open Developers, then API keys, and create a key. It is shown only once, so store it safely. Keys start with ps_live_ or ps_test_.

  2. 2

    Request your first capture

    Pass the key as a Bearer token. The call returns 202 right away with a capture_id and status: "processing".

    curl -X POST "$PROOFSNAP_API_BASE/captures" \
      -H "Authorization: Bearer ps_live_..." \
      -H "Content-Type: application/json" \
      -d '{"url": "https://example.com"}'
  3. 3

    Get the result

    Poll GET /captures/{capture_id} until status is completed or failed. A completed capture includes package_url (a presigned ZIP link valid for up to 24 hours) and manifest_hash. To get a fresh link, fetch the capture again. Instead of polling, set options.webhook_url to an HTTPS endpoint to receive a signed (HMAC-SHA256) capture.completed or capture.failed event.

    curl "$PROOFSNAP_API_BASE/captures/cap_..." \
      -H "Authorization: Bearer ps_live_..."
  4. 4

    Verify the package

    POST /captures/{capture_id}/verify re-checks every declared SHA-256 hash and the RSA-4096 manifest signature against the stored files and returns match, modified or invalid. Anyone can also run the scripts in the package's verification/ folder offline, or look up the SHA-256 of manifest.json in the public ledger with GET /ledger/{hash}. Neither requires an API key.

    curl -X POST "$PROOFSNAP_API_BASE/captures/cap_.../verify" \
      -H "Authorization: Bearer ps_live_..."

Authentication

Send the API key in the Authorization: Bearer ps_live_... header. Keys start with ps_live_ or ps_test_. A live key creates billable captures; a test key creates complete, watermarked evaluation packages that are not billed. A live key on an account with no linked billing account works as a test key. A missing key returns 401 MISSING_API_KEY; an unknown or revoked key returns 401 INVALID_API_KEY. Website Archive keys are read-only (403 PLAN_API_READ_ONLY). Three routes need no key: GET /health, GET /ledger/{hash} and GET /matter-verify.

A new account starts in the sandbox with 50 free test captures. Test-mode usage is limited to 200 units per account per UTC day (429 TEST_MODE_DAILY_LIMIT), packages are watermarked "TEST - NOT FOR LEGAL USE", and include_eidas requires a live key (403 EIDAS_REQUIRES_LIVE_KEY).

Webhooks

Set options.webhook_url per request, or create account-level webhook subscriptions with POST /webhook-subscriptions. Deliveries follow the Standard Webhooks format: the webhook-id, webhook-timestamp and webhook-signature headers (v1, an HMAC-SHA256 computed over the ID, timestamp and body with a whsec_ secret). Event types: capture.completed, capture.failed, capture.anchor_confirmed, certify.completed, certify.failed, redaction.completed, redaction.failed, monitor.change_detected and schedule.paused. capture.anchor_confirmed and schedule.paused go to account-level subscriptions only. Every event is also retained for 30 days in GET /events. A delivery times out after 10 seconds and is retried after 5 minutes, 30 minutes, 2 hours, 8 hours and 24 hours. When you rotate the secret, both the old and the new secret sign deliveries for 24 hours.

Deliveries to a per-request webhook_url are signed with the secret of the API key that made the request. That secret is shown once, when you create the key under Developers in the Dashboard. A subscription has its own secret, returned once when you create it. Verify the signature over the raw body before parsing, reject any webhook-timestamp that differs from your server time by more than 5 minutes and process each webhook-id once. Any Standard Webhooks library does this for you.

Rate limits and errors

Billable requests (POST /captures, /captures/batch, /compare, /captures/{capture_id}/redact and /certify-hash, plus verify, legal holds, export jobs and imports) are limited per account in fixed 60-second windows, shared across all of the account's API keys and its Dashboard session. A batch or a multi-hash certification uses one unit per URL or hash. Units per window: sandbox 10, Developer 60, Startup 120, Growth 300, Legal Solo 60, Legal Company 120, Website Archive 60, Archive only 30. Responses from these routes carry RateLimit-Policy and RateLimit headers plus the legacy X-RateLimit-* headers; a 429 response also includes Retry-After.

Live captures count toward the plan's monthly limit (402 QUOTA_EXCEEDED); requests from an account with a past-due subscription return 402 PAYMENT_REQUIRED. Each account can run only a limited number of captures at once (429 CONCURRENT_CAPTURE_LIMIT). Send an Idempotency-Key header so that a retry within 24 hours returns the original result with Idempotent-Replay: true instead of creating a second capture. Errors are returned as JSON with error.code, error.message and, where useful, error.details; include the X-Request-ID response header value when you contact support. The full list of codes is in the reference below.

Endpoints at a glance

  • Captures: POST /captures, POST /captures/batch (2 to 50 URLs), GET /captures, GET /captures/hosts, GET /captures/{capture_id}, PATCH and DELETE /captures/{capture_id}, POST /captures/{capture_id}/verify
  • Review: POST /captures/{capture_id}/redact, POST /compare, POST /certify-hash (up to 100 hashes)
  • Automation: /scheduled-captures (with /runs), /webhook-subscriptions, GET /webhook-events/{capture_id}, GET /events, GET /captures/events
  • Legal: /matters (seal, export, share), POST /legal-holds, /imports, /captures/export-jobs
  • Account and public: GET /whoami, GET /health, GET /ledger/{hash}, GET /matter-verify

Full reference

Every endpoint with its parameters, responses and schemas, generated from the OpenAPI 3 specification. Download the specification as openapi.json. There is no official SDK: generate a client with any OpenAPI 3 generator, and verify webhooks with any Standard Webhooks library.