Skip to main content
Every platform-level rejection comes back with an HTTP status code and a JSON body of shape {"message": "<reason>"}. This page lists the ones that depend on your account state (balance, tier, rate) rather than request validity. Request-validity errors (400, 404, 410, 502, 503) are documented inline on each API reference page.

402 Insufficient balance

Returned on any billable endpoint when sandbox_free_micros + balance_micros ≤ 0 (for sandbox operations) or guardrails_free_micros + balance_micros ≤ 0 (for guardrails operations).
{ "message": "insufficient balance" }
Triggered on: POST /sandboxes, command endpoints, filesystem endpoints, and guardrails-scanning paths for Pro and Enterprise accounts. Free accounts hit 402 only after their free credits are fully drained. Recommended handling: surface to the user as “top up required”, then retry after a deposit lands. Deposits are processed synchronously — a successful POST /accounts/{id}/deposits immediately updates balance_micros.

403 Tier limit exceeded

Returned when a create request asks for resources above your tier cap. The request body is rejected before the sandbox is provisioned.
{ "message": "vcpu limit exceeds tier allowance" }
{ "message": "memory limit exceeds tier allowance" }
{ "message": "disk limit exceeds tier allowance" }
{ "message": "session duration exceeds tier limit" }
Also returned on:
  • {"message": "unknown tier: <name>"} — the account’s tier doesn’t map to a known config (administrative error, contact support)
  • {"message": "forbidden: cannot access another account"} — calling an /accounts/{id} endpoint with a different owner_id
Recommended handling: cap your request parameters to the numbers in Plans & Limits. Tier upgrades are handled via your dashboard (Pro) or sales (Enterprise).

429 Too many requests

Returned in two different scenarios. Both have the same status code but different meanings.

Concurrent sandbox cap

{ "message": "concurrent sandbox limit reached for tier: pro" }
Your account has MaxConcurrent sandboxes in the running state. Kill or let a sandbox time out before creating another.

Request rate limit

{ "message": "rate limit exceeded" }
{ "message": "sandbox creation rate limit exceeded" }
You’ve exceeded the per-second request budget for your tier. The rate limiter uses a 1-second sliding window — wait one second and retry.

Fixed-bucket rate limits

A handful of sensitive endpoints have lower, fixed budgets that apply regardless of tier:
BucketScopeLimit
Depositper account10 / hour
Tier changeper account5 / day
Account createper client IP5 / hour
Loginper client IP10 / 15 minutes
Exceeding any of these returns a descriptive {"message": "too many ... requests, try again later"} response.

Response headers

General and create rate-limit rejections include per-bucket accounting headers:
X-RateLimit-Limit-general: 2000
X-RateLimit-Remaining-general: 0
Declaw does not currently emit a Retry-After header. Clients should use a fixed 1-second backoff for general/create rate-limit errors, and progressive backoff (e.g. 30s, 60s, 120s) for fixed-bucket errors.
A production client should distinguish these three cases:
from declaw import Sandbox, InsufficientBalanceException, RateLimitException

try:
    sbx = Sandbox.create(template="python")
except InsufficientBalanceException as e:
    # 402 — out of money. Surface to operator, do not retry.
    alert_ops(f"Wallet empty ({e.wallet_type}). Top up required.")
    raise
except RateLimitException as e:
    # 429 — transient. Retry after a short wait.
    time.sleep(e.retry_after or 1)
    sbx = Sandbox.create(template="python")
The SDK maps each HTTP status to a typed exception — see Python error handling or TypeScript error handling for the full class list.

Checklist

  • Always handle 429 with a retry — it’s transient by definition
  • Never retry 402 without topping up — you’ll just burn quota against the same empty wallet
  • Never retry 403 without changing the request — the tier cap won’t move on its own
  • Cache tier limits from Plans & Limits client-side; clamp request parameters before sending
  • Alert on unexpected 402 as early as possible — your account is locked out of billable operations until a deposit succeeds