Error Codes
All error responses follow a consistent format:
{ "error": { "code": "error_code", "message": "Human-readable description", "request_id": "req_xxx" }}HTTP Status Codes
Section titled “HTTP Status Codes”400 Bad Request
Section titled “400 Bad Request”Invalid request body or missing required fields.
{ "error": { "code": "bad_request", "message": "Missing or invalid \"namespace\" field", "request_id": "req_a1b2c3d4..." }}Common causes:
- Invalid JSON body
- Missing required field (
namespace,identifier,limit,window) - Invalid field type (e.g., string instead of number for
limit) - Negative or zero values for
limitorwindow
Fix: Check your request body matches the expected format:
{ "namespace": "api", "identifier": "user_123", "limit": 100, "window": 60000}401 Unauthorized
Section titled “401 Unauthorized”Missing or invalid API key.
{ "error": { "code": "unauthorized", "message": "Invalid API key format", "request_id": "req_a1b2c3d4..." }}Common causes:
- Missing
Authorizationheader - Invalid key format (doesn’t match
ts_limiter_{mode}_{32chars}) - Revoked API key
- Using wrong product key (e.g.,
ts_cache_on TinyLimiter)
Fix: Verify your API key:
# CorrectAuthorization: Bearer ts_limiter_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
# Wrong productAuthorization: Bearer ts_cache_live_xxx # ❌ Wrong prefix for TinyLimiter402 Payment Required
Section titled “402 Payment Required”Live mode key requires active subscription.
{ "error": { "code": "payment_required", "message": "Live mode API keys require an active subscription. Subscribe at dashboard.tinyscale.io or use a test mode key.", "request_id": "req_a1b2c3d4..." }}Common causes:
- Using live key without subscription
- Subscription canceled or expired
- Payment method declined
Fix:
- Subscribe at dashboard.tinyscale.io
- Or switch to a test mode key (
ts_limiter_test_)
429 Too Many Requests
Section titled “429 Too Many Requests”Rate limit exceeded on the management API itself.
{ "error": { "code": "rate_limited", "message": "Too many requests", "request_id": "req_a1b2c3d4..." }}500 Internal Server Error
Section titled “500 Internal Server Error”Server-side error.
{ "error": { "code": "internal_error", "message": "Internal server error", "request_id": "req_a1b2c3d4..." }}What to do:
- Retry the request after a brief delay
- If persistent, check our status page
- Contact support with the
request_id
Error Handling Best Practices
Section titled “Error Handling Best Practices”async function checkRateLimit(userId) { try { const response = await fetch('https://limiter.tinyscale.io/v1/check', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.TINYSCALE_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ namespace: 'api', identifier: userId, limit: 100, window: 60000, }), });
if (!response.ok) { const error = await response.json();
switch (response.status) { case 401: console.error('Invalid API key:', error.error.message); // Fall through - allow request (fail open) return true; case 402: console.error('Subscription required:', error.error.message); // Fall through - allow request (fail open) return true; case 500: console.error('TinyScale error:', error.error.request_id); // Fail open - don't block users due to our outage return true; default: console.error('Unexpected error:', error); return true; } }
const { data } = await response.json(); return data.allowed;
} catch (networkError) { // Network failure - fail open console.error('Network error calling TinyScale:', networkError); return true; }}Fail Open vs Fail Closed
Section titled “Fail Open vs Fail Closed”Fail open (recommended): If TinyScale is unavailable, allow the request.
// Fail open - don't block legitimate usersif (error) return true;Fail closed: If TinyScale is unavailable, reject the request.
// Fail closed - strict enforcementif (error) return false;Debugging
Section titled “Debugging”Include the request_id from error responses when contacting support:
Request ID: req_a1b2c3d4e5f6g7h8i9j0k1l2You can also check response headers:
curl -i https://limiter.tinyscale.io/v1/check ...# X-Request-Id: req_a1b2c3d4e5f6g7h8i9j0k1l2