Authentication
API keys
Every request must be authenticated with a Bearer token. Get one from your dashboard.
POST /api/v1/screenshot HTTP/1.1
Authorization: Bearer sho_live_a1b2c3d4e5f6_…
Content-Type: application/json
{ "url": "https://example.com" }
Alternative auth headers (use whichever you prefer):
X-API-Key: sho_live_a1b2c3d4e5f6_…
Or as query string (only for GET endpoints like /v1/render):
?access_key=sho_live_a1b2c3d4e5f6&signature=…
Key format
Keys look like sho_<env>_<short>_<secret>:
sho_live_a1b2c3d4e5f6_d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5
└──────────────────┘ └──────────────────────────────────────────────┘
short secret
(visible part) (revealed once at creation)
shortis shown in your dashboard and is sent asaccess_keyfor signed URLs.secret(the full key) is shown only once at creation. If you lose it, rotate the key — the old key is revoked, a new one is generated.- Keys are revealable from the dashboard if your account was created after Nov 2025.
Signed URLs (no header auth)
For embeddable use cases (<img src=...>, Markdown, no-code tools), generate a signed URL with HMAC-SHA256:
$secret = 'sho_live_a1b2c3d4e5f6_…full_key…';
$short = 'sho_live_a1b2c3d4e5f6';
$params = [
'url' => 'https://example.com',
'full_page' => '1',
'access_key' => $short,
];
ksort($params);
$canonical = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
$sig = hash_hmac('sha256', $canonical, $secret);
echo "https://api/v1/render?{$canonical}&signature={$sig}";
Embed in HTML:
<img src="https://api/v1/render?url=…&access_key=…&signature=…" />
Cache TTL = 24h. Same URL+options served twice → second hit is free (X-Cache: HIT), no debit.
See Signed URLs for the full spec.
Security notes
- Keep your secret server-side only. Don't expose it in client-side JS.
- Rotate keys on suspected compromise.
- Revoked keys return
401 invalid_api_keyimmediately. - Rate limits are enforced per API key (see Rate limits).