Skip to content

API Reference

https://limiter.tinyscale.io

Check and consume a rate limit. Returns whether the request is allowed and the remaining quota.

POST /v1/check
Authorization: Bearer ts_limiter_{mode}_{key}
Content-Type: application/json
FieldTypeRequiredDescription
namespacestringYesGroup for rate limits (e.g., "api", "auth")
identifierstringYesUnique ID within namespace (e.g., user ID, IP)
limitnumberYesMaximum requests allowed in window
windownumberYesTime window in milliseconds
Terminal window
curl -X POST https://limiter.tinyscale.io/v1/check \
-H "Authorization: Bearer ts_limiter_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"namespace": "api",
"identifier": "user_123",
"limit": 100,
"window": 60000
}'
const response = await fetch('https://limiter.tinyscale.io/v1/check', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
namespace: 'api',
identifier: 'user_123',
limit: 100,
window: 60000,
}),
});
const { data } = await response.json();
import requests
response = requests.post(
'https://limiter.tinyscale.io/v1/check',
headers={
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json',
},
json={
'namespace': 'api',
'identifier': 'user_123',
'limit': 100,
'window': 60000,
},
)
data = response.json()['data']
{
"data": {
"allowed": true,
"remaining": 95,
"limit": 100,
"reset_at": 1703980800000,
"namespace": "api",
"identifier": "user_123"
}
}
FieldTypeDescription
allowedbooleanWhether the request is within the rate limit
remainingnumberRequests remaining in current window
limitnumberMaximum requests allowed (echoed from request)
reset_atnumberUnix timestamp (ms) when window resets
namespacestringNamespace (echoed from request)
identifierstringIdentifier (echoed from request)

Namespaces let you create separate rate limit buckets. Common patterns:

NamespaceUse CaseExample Config
apiGeneral API calls100 req/min
authLogin attempts5 req/min
aiExpensive operations10 req/hour
exportData exports5 req/day
uploadFile uploads20 req/hour

Each (namespace, identifier) pair has its own counter:

// These are separate rate limits
await check({ namespace: 'api', identifier: 'user_1', limit: 100, window: 60000 });
await check({ namespace: 'auth', identifier: 'user_1', limit: 5, window: 60000 });
DurationMilliseconds
1 second1000
10 seconds10000
1 minute60000
5 minutes300000
1 hour3600000
1 day86400000

Consider adding these headers to your API responses:

res.set({
'X-RateLimit-Limit': data.limit,
'X-RateLimit-Remaining': data.remaining,
'X-RateLimit-Reset': data.reset_at,
});
GET /v1/health

Returns service status. No authentication required.

{
"data": {
"status": "healthy",
"product": "limiter",
"version": "v1",
"timestamp": "2024-12-25T10:00:00.000Z"
}
}

Every response includes an X-Request-Id header for debugging:

X-Request-Id: req_a1b2c3d4e5f6g7h8i9j0k1l2

Include this ID when contacting support.