API Rate Limits
Rate Limit Overview
TimeProof applies rate limiting to protect service quality and ensure fair access for all users. Limits are designed to be generous for normal usage — you’re unlikely to hit them during typical interactive use. Automated integrations processing high volumes should be designed with these limits in mind.
Limit Categories
Authenticated Endpoints
| Category | Limit | Window | Endpoints |
|---|---|---|---|
| Timestamp creation | Generous per-minute | Per user | POST /api/timestamps |
| Read operations | Higher per-minute | Per user | GET endpoints (listings, details) |
| Payment operations | Lower per-minute | Per user | POST /api/payments/checkout |
| Account updates | Moderate per-minute | Per user | PATCH /api/account, PATCH /api/settings |
Public Endpoints
| Category | Limit | Window | Endpoints |
|---|---|---|---|
| Verification | High per-minute | Per IP | /api/verify/* |
| Pack listing | High per-minute | Per IP | GET /api/payments/packs |
| Health check | Very high | Per IP | GET /health |
Public verification endpoints intentionally have higher limits because verification by third parties is a core feature of the platform.
Handling Rate Limit Responses
When you exceed a rate limit, the API returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{
"error": "Rate limit exceeded",
"retryAfter": 30
}
Response Headers
| Header | Description |
|---|---|
Retry-After | Seconds to wait before retrying |
Best Practices
Implement Exponential Backoff
When you receive a 429 response, don’t retry immediately. Use exponential backoff:
async function apiCallWithBackoff(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = parseInt(
response.headers.get('Retry-After') || '5'
);
const backoff = retryAfter * Math.pow(2, attempt);
await new Promise(resolve =>
setTimeout(resolve, backoff * 1000)
);
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Batch Operations
Instead of timestamping files one at a time, batch them into a single API call. The timestamp endpoint accepts multiple files in one request — this is more efficient and uses fewer API calls:
// Inefficient: 10 API calls
for (const file of files) {
await fetch('/api/timestamps', {
method: 'POST',
body: JSON.stringify({ files: [file], anchorMode: 'scheduled' })
});
}
// Efficient: 1 API call
await fetch('/api/timestamps', {
method: 'POST',
body: JSON.stringify({ files: allFiles, anchorMode: 'scheduled' })
});
Cache Where Possible
Responses that don’t change frequently can be cached locally:
- Credit packs — pack details rarely change; cache for hours
- Organization details — cache for minutes, invalidate on updates
- Verification results — once a hash is verified, the result is permanent
Avoid Polling
Instead of polling the timestamp status endpoint repeatedly, use the WebSocket notification channel. TimeProof sends real-time notifications when:
- A timestamp job is anchored
- A payment is confirmed
- Credits are added to your account
This eliminates the need for frequent polling and reduces your API call volume significantly.
Rate Limits for Common Workflows
Interactive Web Usage
Normal web interface usage — creating a few timestamps, checking balances, browsing activity — operates well within all rate limits. You won’t encounter 429 responses during typical interactive sessions.
Automated Timestamping
For automated systems processing files in bulk:
- Batch files together — send multiple file hashes per API call
- Use scheduled timestamps — scheduled mode is designed for bulk workflows
- Respect 429 responses — implement backoff logic
- Monitor your usage — check the response headers for limit information
Verification Services
If you’re building a verification service that checks timestamps on behalf of users:
- Public verification endpoints have generous limits
- Cache positive results — verified hashes don’t un-verify
- Spread requests over time rather than bursting
Troubleshooting Rate Limits
| Symptom | Cause | Solution |
|---|---|---|
| 429 on every request | Burst of requests exceeded window | Wait for Retry-After period, implement backoff |
| 429 during normal use | May be sharing IP with other users (e.g., corporate NAT) | Contact support with details |
| Intermittent 429s | Near the limit boundary | Add small delays between requests |
| 429 on public endpoints | IP-level limit hit | Cache results, reduce request frequency |
Rate Limits and Organizations
When acting on behalf of an organization, rate limits still apply per authenticated user — not per organization. This means a single user managing org timestamps has the same limits as when managing personal timestamps. Multiple authenticated users within an organization each have their own rate limit quotas.
Related Guides
- API Overview — introduction to the full API
- API Timestamp Endpoints — batch timestamps efficiently
- Troubleshooting Common Issues — solutions for common problems
- Batch Timestamping — reduce API calls with batching
Use the live product for timestamping and verification.
The company site owns the technical reference. The app handles runtime workflows.