Legacy TinyLimiter documentation. About this product
Base URL
https://limiter.tinyscale.io
POST /v1/check
Check and consume a rate limit. Returns whether the request is allowed and the remaining quota.
Request
POST /v1/check
Authorization: Bearer ts_limiter_{mode}_{key}
Content-Type: application/json
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
namespace | string | Yes | Group for rate limits (e.g., "api", "auth") |
identifier | string | Yes | Unique ID within namespace (e.g., user ID, IP) |
limit | number | Yes | Maximum requests allowed in window |
window | number | Yes | Time window in milliseconds |
Example Request
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']
Response
{
"data": {
"allowed": true,
"remaining": 95,
"limit": 100,
"reset_at": 1703980800000,
"namespace": "api",
"identifier": "user_123"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
allowed | boolean | Whether the request is within the rate limit |
remaining | number | Requests remaining in current window |
limit | number | Maximum requests allowed (echoed from request) |
reset_at | number | Unix timestamp (ms) when window resets |
namespace | string | Namespace (echoed from request) |
identifier | string | Identifier (echoed from request) |
Namespaces
Namespaces let you create separate rate limit buckets. Common patterns:
| Namespace | Use Case | Example Config |
|---|---|---|
api | General API calls | 100 req/min |
auth | Login attempts | 5 req/min |
ai | Expensive operations | 10 req/hour |
export | Data exports | 5 req/day |
upload | File uploads | 20 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 });
Common Window Values
| Duration | Milliseconds |
|---|---|
| 1 second | 1000 |
| 10 seconds | 10000 |
| 1 minute | 60000 |
| 5 minutes | 300000 |
| 1 hour | 3600000 |
| 1 day | 86400000 |
Rate Limit Headers
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,
});
Health Check
GET /v1/health
Returns service status. No authentication required.
{
"data": {
"status": "healthy",
"product": "limiter",
"version": "v1",
"timestamp": "2024-12-25T10:00:00.000Z"
}
}
Request IDs
Every response includes an X-Request-Id header for debugging:
X-Request-Id: req_a1b2c3d4e5f6g7h8i9j0k1l2
Include this ID when contacting support.