Menu
Docs/Webhooks

Webhooks

Get notified when things happen — screenshots complete, requests fail, or your usage reaches a threshold. SnapSharp sends signed HTTP POST requests to your endpoint.

Manage webhooks in Dashboard → Settings → Webhooks.

Events

EventWhen it fires
screenshot.completedA screenshot, OG image, or HTML-to-image request succeeded
screenshot.failedA request failed (timeout, unreachable URL, etc.)
usage.threshold.80Monthly usage hit 80% of your plan limit
usage.threshold.100Monthly usage hit 100% — requests will be rejected

Payload format

All webhook payloads follow this structure:

{
  "event": "screenshot.completed",
  "timestamp": "2026-03-25T14:30:00.000Z",
  "data": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "endpoint": "/v1/screenshot",
    "url": "https://example.com",
    "status_code": 200,
    "response_time_ms": 1247,
    "cached": false
  }
}

Event-specific data

screenshot.completed: request_id, endpoint, url, status_code, response_time_ms, cached, format, size_bytes

screenshot.failed: request_id, endpoint, url, status_code, error_message

usage.threshold.80 / usage.threshold.100: current_usage, limit, percentage, plan

Signature verification

Every webhook request includes an HMAC-SHA256 signature to verify authenticity.

Headers

HeaderValue
Content-Typeapplication/json
User-AgentSnapSharp-Webhook/1.0
X-Webhook-IdUnique delivery ID
X-Webhook-Signaturesha256=<hex HMAC>
X-Webhook-TimestampISO 8601 timestamp
X-Webhook-AttemptAttempt number (1, 2, or 3)

Verifying the signature

The signature is computed over the raw request body using your webhook secret:

import crypto from 'crypto';

function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
const isValid = verifyWebhook(
  rawBody,
  req.headers['x-webhook-signature'],
  'whsec_your_webhook_secret'
);
import hmac
import hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Always verify the signature before processing the payload. Never trust unverified webhook requests.

Retry policy

If your endpoint returns a non-2xx status code or doesn't respond within 10 seconds, SnapSharp retries with exponential backoff:

AttemptDelay
1stImmediate
2nd30 seconds
3rd5 minutes
4th (final)1 hour

After 3 failed retries, the delivery is marked as failed. You can see delivery history in the dashboard.

Creating a webhook

Via dashboard

  1. Go to Settings → Webhooks in your dashboard
  2. Enter the endpoint URL (must be HTTPS)
  3. Select the events you want to receive
  4. Save — your webhook secret is shown once, copy it

Testing

Use the Test button next to any webhook to send a sample payload. This helps verify your endpoint is working before real events fire.

Delivery history

Each webhook shows its recent deliveries with:

  • Event type and timestamp
  • HTTP status code from your endpoint
  • Response body (first 1KB)
  • Attempt number

View delivery history in Dashboard → Settings → Webhooks → expand any webhook.

Best practices

  • Respond quickly — return a 200 within 5 seconds. Process the payload asynchronously if your handler does heavy work.
  • Handle duplicates — use the X-Webhook-Id header to deduplicate. The same event may be delivered more than once during retries.
  • Verify signatures — always check X-Webhook-Signature to confirm the request came from SnapSharp.
  • Use HTTPS — webhook URLs must use HTTPS. HTTP endpoints are rejected.