TrustVerify logoTrustVerify
Decorative footer background
TrustVerify logoTrustVerify

Identity and business verification for UK marketplaces. ID document and selfie checks, UK company and director checks, and a recorded decision on every check.

020 4542 7323

Solutions

  • All solutions
  • Identity (IDV/KYC)
  • Business (KYB)
  • Bot detection
  • AML & PEP screening
  • Seller verification (KYS)
  • UK registry checks
  • Ongoing monitoring
  • Review queue & trust score
  • Fraud checks
  • IP geolocation
  • Email validation
  • Escrow (secure transactions)

Industries

  • Marketplaces

Developers

  • Platform
  • Integrations
  • Developer docs
  • API reference
  • Webhooks
  • Changelog
  • API status
  • Help centre

Blog

  • All articles
  • Glossary
  • Compare
  • Sumsub alternatives
  • Onfido alternatives
  • Veriff alternatives

Company

  • About TrustVerify
  • Careers
  • Contact sales
  • Privacy policy
  • Cookie policy
  • Terms of service

© 2026 Magnificentech Solutions Ltd (Company No. 16321180), trading as TrustVerify. Registered in England & Wales. All rights reserved. · trustverify.co.uk

TrustVerify, Willow Farm, Choppington, Northumberland NE62 5EU · 020 4542 7323

  1. Blog/
  2. Developer/
  3. Rate Limits, Retries and Idempotency for Verification APIs
Developer

Rate Limits, Retries and Idempotency for Verification APIs

How verification API rate limits work, which errors to retry, how to back off properly and how to keep retries from creating duplicate checks.

Ayodele Michael Omotayo avatar
Ayodele Michael Omotayo
Founder & CEO, TrustVerify · 31 October 2026 · 8 min read

Most verification integrations work well in testing and then hit their first real problem on a busy day. A seller promotion goes out, a few hundred people sign up at once, and the onboarding service starts firing identity, business and screening checks as fast as it can. Some calls come back with 429. A few time out. The retry logic, written in an afternoon, sends them all again at the same moment.

None of this is unusual, and none of it is hard to handle once you know what the API is telling you. This post covers how per-minute limits and monthly allowances work, which errors are worth retrying, how to back off without making things worse, and how to stop retries from turning into duplicate checks.

Why verification APIs limit requests

Rate limits are not there to make integration harder. A verification call usually does real work behind the scenes: reading a document, comparing a face, querying a register or screening a name against sanctions and PEP lists. Some of that work depends on upstream sources with their own limits. A cap per key keeps one integration's burst from slowing down everyone else, and it keeps costs predictable for both sides.

For a marketplace, the useful way to think about limits is as a design input. If you know your per-minute ceiling, you can decide in advance what happens when a sign-up spike exceeds it: queue the work, spread it out, and tell the seller their check is in progress rather than showing them an error.

How TrustVerify reports limits

The rate limits and quotas page in our docs sets out the detail. In short, each API key has a per-minute limit set by its plan, and responses to key-authenticated calls carry three headers:

  • X-RateLimit-Limit: requests allowed per minute for this key
  • X-RateLimit-Remaining: requests left in the current minute
  • X-RateLimit-Reset: seconds until the minute resets

When you go over the limit, the API returns HTTP 429 with error: rate_limit_exceeded, a retryAfterSeconds field in the body and a Retry-After header. The instruction is simple: wait that long, then try again.

Separately from the per-minute limit, live checks count against your plan's monthly allowance. Where a finite allowance applies, responses carry X-Quota-Limit, X-Quota-Remaining and X-Quota-Reset. Allowances reset at 00:00 UTC on the first of each month. Sandbox calls do not count towards the allowance, which matters when you are load testing.

Some endpoints, including email and phone checks and adding a subject to ongoing monitoring, also count towards a daily cap. Going over that returns 429 with code: DAILY_CAP_EXCEEDED, and it resets at midnight UTC. A daily cap will not clear in a few seconds, so your code should tell it apart from a per-minute 429 and not keep retrying it all afternoon.

Read the headers before you hit the wall

The cheapest 429 is the one you never receive. Because every key-authenticated response carries X-RateLimit-Remaining, a client can slow itself down before it reaches zero.

A simple pattern works for most marketplaces:

  1. Put verification calls through a single worker queue rather than calling the API directly from web requests.
  2. After each response, record the remaining count and the reset time.
  3. When remaining drops low, pause the worker until the reset time passes.
  4. Keep the seller-facing flow honest. Show "we're checking your details" and send the result when it arrives.

This keeps bursts inside your limit without anyone noticing, and it means a sign-up spike becomes a slightly longer queue rather than a wall of errors. It also makes your logs much easier to read, because you are not mixing real failures with self-inflicted ones.

Watch the quota headers too. If X-Quota-Remaining is falling faster than expected mid-month, you want to know on a Tuesday, not on the morning it reaches zero.

Which errors to retry

Retrying everything is the most common mistake. Our docs are specific: retry 429, 500 and 503 only. Do not retry other 4xx errors, because they will fail again.

It helps to sort responses into three groups:

Retry after a wait. A 429 from the per-minute limit, and 500 or 503 responses, are usually temporary. Back off and try again.

Do not retry, fix the request. A 400 validation error, a 401 for a bad key, a 404 for a check that does not exist on your account, or a 409 conflict all mean something about the request is wrong. Sending it again unchanged will produce the same answer. Log it, alert on it, and fix the cause. The errors reference lists the codes you will see.

Do not retry today. A daily cap 429 will not clear until midnight UTC. Queue the work for later, or treat it as a sign that the cap no longer matches your volume.

Timeouts sit awkwardly between these. If your client gave up waiting, you do not know whether the server finished the work. That is where idempotency matters, and we come back to it below.

Back off properly

When you do retry, use exponential backoff with jitter, and honour Retry-After when it is present.

Exponential backoff means each retry waits longer than the last: perhaps one second, then two, then four, up to a ceiling. Jitter adds a random element to each wait so that a hundred workers that failed at the same moment do not all retry at the same moment too. Without jitter, you get synchronised waves of retries that keep hitting the limit.

A sketch of the logic:

attempt = 0
loop:
  response = call_api()
  if response.status in (429, 500, 503) and attempt < max_attempts:
      if response has Retry-After:
          wait = Retry-After seconds
      else:
          wait = random(0, base * 2 ** attempt), capped
      sleep(wait)
      attempt += 1
      continue
  return response

Set a maximum number of attempts. After that, move the job to a dead-letter queue and alert someone. A check that has failed five times is not going to succeed on the sixth because you were patient.

Idempotency: making retries safe

A retry is only safe if doing the same thing twice has the same effect as doing it once. For read requests, such as fetching a check result or a report, that is naturally true. For requests that create something, such as starting a new verification, it is not automatic.

The risk is easy to picture. Your client sends a KYC check, the server processes it, and the response is lost on the way back. Your client sees a timeout and sends it again. Now there are two checks for one seller, both counted against your allowance, and possibly two different results in your records.

The TrustVerify API does not take an Idempotency-Key header, so build idempotency on your side:

  • Record intent before calling. Store a row in your database saying "KYC check requested for seller 123" with a status of pending, before the API call goes out.
  • Use your own reference. Keep a stable internal ID for each verification attempt, and store the check ID the API returns against it.
  • Check before re-sending. On a timeout, look up whether a check ID was stored or whether a result has arrived by webhook before you create a new one.
  • Prefer reads after ambiguity. If you have a check ID, fetch its status instead of starting again.

Some operations are idempotent by design. Adding someone to ongoing monitoring who is already enrolled is one: POST /api/v1/aml/monitor returns 200 with the existing monitor and alreadyEnrolled: true, rather than creating a second enrolment or using another monitoring slot. Check other endpoints in the API reference rather than assuming.

The webhook side of the same problem

Idempotency also applies in the other direction. TrustVerify retries webhook deliveries up to three times with exponential backoff, uses a 10-second timeout and does not follow redirects. That means your endpoint can receive the same event more than once, for example if it processed the event but responded slowly.

Every delivery carries an X-TrustVerify-Delivery-Id header. Store the IDs you have processed and ignore repeats. Respond quickly with a 2xx and do heavy processing afterwards, so you do not trigger retries you did not need. Our planned post on KYC webhooks and decision handling goes into this in more detail. [Planned URL, live on publication.]

Test it before a busy day does

The sandbox is the right place to try all of this. Test keys start with tv_test_sk_, sandbox calls do not count towards your monthly allowance, and you can push your worker queue hard enough to see a 429 without affecting live sellers. The sandbox guide explains what test data to use.

Things worth testing on purpose:

  • what your queue does when X-RateLimit-Remaining reaches zero
  • whether your client reads Retry-After correctly
  • that 400 and 401 responses are not retried
  • that a forced timeout does not create a second check
  • that a duplicate webhook delivery is ignored

Key takeaways

  • Read X-RateLimit-Remaining and slow down before you hit 429.
  • Retry only 429, 500 and 503, with exponential backoff, jitter and Retry-After.
  • Treat a daily cap 429 differently from a per-minute one.
  • Make create calls safe to retry by recording intent and check IDs on your side.
  • De-duplicate webhooks using X-TrustVerify-Delivery-Id.

Next step

Read the full limits and headers reference, then try it against the sandbox. Open the TrustVerify quickstart.

Frequently asked questions

What happens when I exceed the per-minute limit?
You get HTTP 429 with `error: rate_limit_exceeded`, a `retryAfterSeconds` value and a `Retry-After` header. Wait that long and retry.
Do sandbox calls use my monthly allowance?
No. Sandbox calls do not count towards the monthly allowance, so you can test load behaviour safely.
When does the monthly allowance reset?
At 00:00 UTC on the first of each month. Daily caps reset at midnight UTC.
Should I retry a 400 or 404?
No. Those mean the request needs fixing. Only 429, 500 and 503 are worth retrying.
How do I avoid processing the same webhook twice?
Store each `X-TrustVerify-Delivery-Id` you handle and skip any you have already seen.

See TrustVerify in action

KYC, KYB, AML screening and fraud prevention in one place, with published pricing.

Book a 30-minute demoSee pricingRead the API docs
Ayodele Michael Omotayo avatar

Ayodele Michael Omotayo

Founder & CEO, TrustVerify

Founder and CEO of TrustVerify. Building identity and business verification for UK marketplaces, with every decision recorded.

LinkedIn →

Related posts

Cover image: KYC Webhooks and Decision Handling for Marketplaces

Developer

KYC Webhooks and Decision Handling for Marketplaces

A practical guide to consuming KYC and fraud webhooks on a marketplace: signatures, retries, idempotency and mapping decisions to seller states.

Cover image: Using the TrustVerify Sandbox: Test Keys and Your First Check

Developer

Using the TrustVerify Sandbox: Test Keys and Your First Check

A developer guide to the TrustVerify sandbox: test and live keys, deterministic synthetic results, magic test values and what the sandbox does not cover.

Cover image: Pulling Verification Reports via API

Developer

Pulling Verification Reports via API

How to fetch KYC, KYB and AML screening reports by API, check they exist, download the PDF and assemble an evidence bundle for audit.

On this page

  • Why verification APIs limit requests
  • How TrustVerify reports limits
  • Read the headers before you hit the wall
  • Which errors to retry
  • Back off properly
  • Idempotency: making retries safe
  • The webhook side of the same problem
  • Test it before a busy day does
  • Key takeaways
  • Next step