Authentication
All /v1/* endpoints require an API key. A handful of utility routes are public and require no authentication.
Public routes (no auth)
| Path | Description |
|---|---|
GET /health | Health check, returns { ok: true, version: "…" } |
GET /llms.txt | Condensed API reference for AI agents |
GET /llms-full.txt | Full API reference for AI agents |
GET /openapi.json | OpenAPI 3.x spec |
Public under /v1/ without a key: GET /v1/pricing, GET /v1/status, POST /v1/keys/provision.
Everything else under /v1/ requires a valid API key.
Passing your API key
Use the x-api-key header. It is the canonical form and the one every example in these docs uses:
curl -H "x-api-key: ss_live_xxxxxxxxxxxxxxxxxxxx" …Authorization: Bearer ss_live_… is also accepted and resolves to the same key, so an existing
client that already sends a bearer token will work unchanged. When both headers are present,
x-api-key wins. This is the only page that documents the bearer form; prefer x-api-key
everywhere else.
Any request that omits both headers returns:
HTTP 401
{ "error": "API key required. Pass via x-api-key header." }Key format
Keys follow the pattern ss_<token>. The prefix is for visual identification only, any string that resolves to an active row in the api_keys table is accepted. Keys are stored as SHA-256 hashes; the plaintext is only available at creation time.
Getting a key
Dashboard (normal flow)
- Sign in at app.superscraper.dev (opens in a new tab).
- Go to Settings → API Keys and click Create key.
- Copy the key immediately, it is shown only once.
Self-serve provisioning (agents / scripts)
POST /v1/keys/provision is public, it is mounted ahead of the auth guard, so it needs no
existing key and no sign-in. It mints a fresh free-tier tenant and returns the plaintext key once:
curl -X POST https://api.superscraper.dev/v1/keys/provision \
-H "Content-Type: application/json" \
-d '{"label": "my-agent"}'{
"apiKey": "ss_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"tenantId": "8f3c…",
"tier": "free"
}Store apiKey immediately, it cannot be retrieved again. The route is IP rate-limited and issues
free-tier keys only; to do paid work, fund credits from the dashboard.
Key lifecycle
| State | Behaviour |
|---|---|
| Active | All /v1/* requests are allowed (subject to rate limits and tier quotas) |
| Revoked | Returns HTTP 401 "Invalid or revoked API key." on every request |
Keys can be revoked from the dashboard. Once revoked, they cannot be re-activated, create a new key instead.
Error responses
| Status | JSON | Cause |
|---|---|---|
| 401 | "API key required. Pass via x-api-key header." | No key header present |
| 401 | "Invalid or revoked API key." | Key not found in database or is_active = false |
Rate limits
Rate limits apply per key, per 60-second sliding window:
| Plan | Requests / minute |
|---|---|
| Free | 10 |
| Hobby | 60 |
| Pro | 200 |
| Scale | 600 |
| Custom | 3 000 |
Exceeding the limit returns HTTP 429 with a Retry-After: 60 header.
Security notes
- Keys are never logged. The server stores only the SHA-256 hash.
- All requests over plain HTTP are rejected (HTTPS only in production).
- Each request updates
last_used_aton the key row (fire-and-forget, non-blocking). - Treat keys like passwords: do not commit them to version control or expose them client-side. Use environment variables (
SUPERSCRAPER_API_KEY) in your applications.