Rate Limits
API requests are rate-limited based on your workspace's subscription tier. Rate limiting is enforced by AWS API Gateway Usage Plans.
Tier Limits
| Tier | Requests / Minute | Daily Quota |
|---|---|---|
| Free | 30 | Unlimited |
| Starter | 60 | Unlimited |
| Team | 300 | Unlimited |
| Enterprise | 1,000 | Unlimited |
Every tier can create an API key, including free. What a key can do is what varies: a workspace an agent registered for itself has no calling capacity until a person verifies a mobile number for it. See registerWorkspace.
Exceeding Limits
When you exceed the per-minute request rate, the API returns 403 Forbidden, not 429. Rate limiting is enforced in the API Gateway authorizer, which can only deny with 403 and cannot send a Retry-After header, so there is nothing to wait on. A rate-limited 403 is indistinguishable from a scope denial: back off with jitter rather than treating it as permanent. The separate 429 is the concurrency ceiling — too many runs already in flight — and it does not carry a Retry-After either; wait for a run to finish.
# A per-minute rate limit is refused by the API Gateway
# authorizer, which can only deny with 403 and cannot attach a body
# or a Retry-After header.
curl -v -H "x-api-key: YOUR_API_KEY" \
https://api.nopaque.co.uk/mapping
# Response when rate limited:
# HTTP/1.1 403 Forbidden
#
# Indistinguishable from a scope denial, so back off and retry
# rather than treating it as permanent. There is no Retry-After
# to wait on: use exponential backoff with jitter.Best Practices
- Implement exponential backoff with jitter for retries
- Cache responses when possible to reduce request volume
- Use polling intervals of 5-10 seconds for status checks (avoid tight loops)
- Contact support if you need higher limits for Enterprise tier
Automatic retry in the SDKs
The Nopaque SDKs auto-retry on 429 responses, honouring a Retry-After header when one is present and falling back to exponential jitter when it is not — which is the usual case, since this API does not send that header. Defaults: 3 retries with exponential jitter, capped at 8 seconds. You can tune or disable this behavior.
They do not auto-retry the rate-limited 403, because a 403 is ordinarily a permanent scope or workspace denial and retrying it would be wrong. If you are driving the API hard enough to hit the per-minute limit, handle that back-off yourself.
from nopaque import Nopaque
# Disable retries entirely
client = Nopaque(max_retries=0)
# Custom retry count + observability hook
def log_retry(attempt, err, next_delay):
print(f"attempt {attempt}: {type(err).__name__} → retrying in {next_delay:.1f}s")
client = Nopaque(max_retries=5, on_retry=log_retry)
# Per-call override
job = client.mapping.get("map_abc123", request_options={"max_retries": 0})Important: POST requests that create or mutate state are only retried on 429 and pre-flight connection errors, never on 5xx or in-flight timeouts. This avoids duplicate side effects since the API does not support idempotency keys. If you need to retry a POST after a 5xx, call the method again yourself.