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

CategoryLimitWindowEndpoints
Timestamp creationGenerous per-minutePer userPOST /api/timestamps
Read operationsHigher per-minutePer userGET endpoints (listings, details)
Payment operationsLower per-minutePer userPOST /api/payments/checkout
Account updatesModerate per-minutePer userPATCH /api/account, PATCH /api/settings

Public Endpoints

CategoryLimitWindowEndpoints
VerificationHigh per-minutePer IP/api/verify/*
Pack listingHigh per-minutePer IPGET /api/payments/packs
Health checkVery highPer IPGET /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

HeaderDescription
Retry-AfterSeconds 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:

  1. Batch files together — send multiple file hashes per API call
  2. Use scheduled timestamps — scheduled mode is designed for bulk workflows
  3. Respect 429 responses — implement backoff logic
  4. 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

SymptomCauseSolution
429 on every requestBurst of requests exceeded windowWait for Retry-After period, implement backoff
429 during normal useMay be sharing IP with other users (e.g., corporate NAT)Contact support with details
Intermittent 429sNear the limit boundaryAdd small delays between requests
429 on public endpointsIP-level limit hitCache 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.

Use the live product for timestamping and verification.

The company site owns the technical reference. The app handles runtime workflows.