Truthlocks enforces rate limits to ensure fair usage and platform stability. This guide explains limits by tier and how to handle rate limiting gracefully.
Limits by Tier
Tier Requests/min Attestations/day Issuers Keys/Issuer Free 60 100 2 2 Starter 300 10,000 10 5 Professional 1,000 100,000 50 10 Enterprise Custom Custom Unlimited Unlimited
Burst Capacity: All tiers include 2x burst capacity for up to 10 seconds.
This allows handling traffic spikes without immediate rate limiting.
Per-Endpoint Limits
Some endpoints have additional specific limits:
Endpoint Limit Window Reason POST /v1/attestations/mint100/min 60s Signing is CPU-intensive POST /v1/verifyNo limit - Public endpoint, cached POST /v1/issuers10/hour 1h Prevent issuer spam POST /v1/api-keys20/day 24h Security measure GET /v1/audit/events30/min 60s Database-heavy query
Every API response includes headers to help you track your usage:
HTTP / 1.1 200 OK
X-RateLimit-Limit : 1000
X-RateLimit-Remaining : 847
X-RateLimit-Reset : 1705147260
X-RateLimit-Policy : "1000;w=60"
Header Description X-RateLimit-LimitMaximum requests allowed in the window X-RateLimit-RemainingRequests remaining in current window X-RateLimit-ResetUnix timestamp when the window resets X-RateLimit-PolicyPolicy description (requests;window=seconds)
Handling 429 Responses
When you exceed the rate limit, you’ll receive a 429 status code:
HTTP / 1.1 429 Too Many Requests
Retry-After : 32
X-RateLimit-Limit : 1000
X-RateLimit-Remaining : 0
X-RateLimit-Reset : 1705147260
{
"code" : "RATE_LIMITED" ,
"message" : "Rate limit exceeded. Retry after 32 seconds." ,
"http_status" : 429 ,
"details" : {
"limit" : 1000 ,
"window_seconds" : 60 ,
"retry_after_seconds" : 32
}
}
Important: Always respect the Retry-After header. Repeatedly hitting
rate limits may result in temporary IP blocks.
Best Practices
Exponential Backoff
async function withBackoff < T >(
fn : () => Promise < T >,
maxRetries = 5 ,
baseDelayMs = 1000 ,
) : Promise < T > {
for ( let attempt = 0 ; attempt < maxRetries ; attempt ++ ) {
try {
return await fn ();
} catch ( error ) {
if ( error . status !== 429 || attempt === maxRetries - 1 ) {
throw error ;
}
const retryAfter = error . headers ?.[ "retry-after" ]
? parseInt ( error . headers [ "retry-after" ]) * 1000
: baseDelayMs * Math . pow ( 2 , attempt );
const jitter = Math . random () * 1000 ;
await new Promise (( r ) => setTimeout ( r , retryAfter + jitter ));
}
}
throw new Error ( "Max retries exceeded" );
}
Request Batching
// Instead of minting one at a time:
for ( const user of users ) {
await client . attestations . mint ({ ... });
}
// Batch with controlled concurrency:
import pLimit from 'p-limit' ;
const limit = pLimit ( 10 ); // Max 10 concurrent requests
const results = await Promise . all (
users . map ( user =>
limit (() => client . attestations . mint ({ ... }))
)
);
Monitor Usage
// Track remaining quota in your metrics
function trackRateLimit ( response : Response ) {
const remaining = response . headers . get ( "X-RateLimit-Remaining" );
const limit = response . headers . get ( "X-RateLimit-Limit" );
metrics . gauge ( "truthlock.ratelimit.remaining" , parseInt ( remaining ));
metrics . gauge (
"truthlock.ratelimit.usage_percent" ,
( 1 - parseInt ( remaining ) / parseInt ( limit )) * 100 ,
);
}
Requesting Quota Increases
If your usage requires higher limits:
Starter/Professional: Contact support with your use case and expected volume
Enterprise: Custom limits are negotiated during contract discussions
Temporary Increase: For events or migrations, request a temporary burst increase 48 hours in advance
Tip: Include metrics showing your current usage patterns and growth
projections when requesting increases.
Next Steps
Health & Readiness Monitor API health and your integration status.
SDK Examples See rate limit handling in real code.