Envelope
Every endpoint shares one response envelope:
| Case | HTTP | Body |
|---|---|---|
| Sync success | 200 | { "success": true, "data": …, "credit_cost": 1 } |
| Async accepted | 202 | { "success": true, "data": { "job_id": "…", "status_url": "…" } } |
| Error | 4xx/5xx | { "success": false, "error": { "code": "…", "message": "…" } } |
Error codes
| Code | HTTP | Meaning / what to do |
|---|---|---|
INVALID_REQUEST | 400 | Schema/validation failure — message names the field. |
UNAUTHORIZED | 401 | Missing, malformed, or revoked key. |
INSUFFICIENT_CREDITS | 402 | Not enough credits — call was not billed. Top up or reduce limit. |
FORBIDDEN | 403 | e.g. playground key used externally, protected resource. |
JOB_NOT_FOUND / NOT_FOUND | 404 | Job/monitor/key not found (or belongs to another team). |
TARGET_TIMEOUT | 408 | Target page didn't render in time — not billed; retry with larger timeout/wait_for. |
RATE_LIMITED | 429 | Per-plan rate cap — honor Retry-After, back off. |
TARGET_BLOCKED | 403 | Target refused the request (bot protection) — we don't bypass it. |
TARGET_UNREACHABLE | 502 | DNS/TLS/unreachable target. |
PROVIDER_ERROR | 502 | Upstream capture provider failed — not billed; retry with backoff (honor Retry-After when present). |
INTERNAL_ERROR | 500 | Our bug — not billed; retry with backoff. |
Whether a call was billed is always visible via
credit_cost in the envelope and in
GET /v1/account/activity.