Rate Limits
Which endpoints have rate limits today, and how to handle a 429 response.
Why we rate-limit
Rate limits protect:
- Upstream providers from being overloaded — most SignCare APIs proxy to government or financial systems with their own limits.
- Other clients from being starved of capacity.
- You from runaway loops accidentally burning through your quota.
Which endpoints are limited
Most endpoints have no rate limit today. This includes eSign: creating a request, checking status, revoking, re-initiating, extending expiry and fetching the audit trail are not limited. Only the endpoints below are. Limits are counted per App ID (the X-API-APP-ID header) unless the table says otherwise.
| Endpoint | Limit | Counted per |
|---|---|---|
POST /api/v1/StockHoldingEStamp/generate and POST /api/v1/StockHoldingEStamp/bulk-generate | 50 requests per second | App ID |
POST /api/v1/aadhaar-ovse/init, /qr-intent and /app-callback | 10 requests per second | App ID |
GET /api/v1/aadhaar-ovse/result/{txnId} and the event read endpoints | 30 requests per second | App ID |
POST /api/v1/aadhaar-ovse/events and PATCH /api/v1/aadhaar-ovse/events/{eventId} | 1 request per 5 minutes | App ID |
POST /api/v1/aadhaar/secure-qr/read | 30 requests per minute | App ID |
POST /api/v1/esign/dsc-bulk-sign | 10 requests per minute | App ID |
POST /api/v1/esign/resendInvitation | 1 request per 5 minutes | App ID |
POST /api/v1/dgft/iec-lookup, POST /api/v1/dgft/itchs-policy and POST /api/v1/GujRera/verify | 1 request per 5 minutes | App ID |
POST /api/v1/template/render, POST /api/v1/template/design and GET /api/v1/template/design/{templateId} | 50 requests per minute | App ID and client IP |
Limits work like a token bucket: you can burst up to the limit, then requests are allowed again as the bucket refills evenly over the time window. Limits can change, so always handle a 429 (see below).
Need a higher limit for one of these endpoints? See Need higher limits? below.
What a 429 looks like
When you exceed a limit the API answers with HTTP 429 Too Many Requests and this body. It does not send a Retry-After header.
{
"data": "",
"message": "Too many requests. Please wait before retrying.",
"statusCode": 429,
"success": false
}Handling 429 correctly
1. Wait for the limit window
There is no Retry-After header, so wait for the endpoint's window from the table above before retrying: about 1 second for the per-second limits, up to 1 minute for the per-minute limits and 5 minutes for the "1 request per 5 minutes" endpoints.
2. Use exponential backoff with jitter
Don't hammer the API with immediate retries. Use this pattern:
async function callWithBackoff(fn, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const res = await fn();
if (res.status !== 429) return res;
const backoff = Math.min(Math.pow(2, attempt) * 1000, 30_000);
const jitter = Math.random() * 500;
await new Promise((resolve) => setTimeout(resolve, backoff + jitter));
}
throw new Error('Max retry attempts exceeded');
}3. Batch and queue on your side
If you're onboarding many users at once, queue the requests on your side and drain at a steady rate rather than bursting.
4. Monitor and alert
Track the frequency of 429s in your logs. A sudden spike usually means:
- A runaway loop
- Load beyond your contracted rate
- An upstream provider in degraded state
Need higher limits?
Contact support@signcare.io with:
- Your API Key (never your secret — just the ID prefix is enough)
- Expected requests per minute / per day
- Which endpoint(s)
- Business justification (volume, campaign, seasonality)
We can often increase limits within hours for contracted customers.
Fair-use limits on free accounts
Free / evaluation accounts are restricted to Stage only and share a global soft limit. Contact us for a paid account to unlock production capacity.