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

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

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

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

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 });

Common Window Values

DurationMilliseconds
1 second1000
10 seconds10000
1 minute60000
5 minutes300000
1 hour3600000
1 day86400000

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.