Skip to main content
A request can be refused in three ways that look alike but need different handling, so this page keeps them apart. The API does not send X-RateLimit-Limit, X-RateLimit-Remaining or X-RateLimit-Reset headers, so Retry-After is the only header to read. Handle a 429 on any endpoint: a rate limit can apply to any request.

Rate limits

A rate limit caps how many requests you can make in a minute. Two kinds apply. Your plan’s API rate limit. It is set per plan, in requests per minute, and varies from plan to plan. The figure for each plan is on the pricing pages linked under Plan quotas. Listing and restoring deleted items. These operations (the Data Recovery operations) have limits of their own, the same for every plan. The paths below are relative to https://api.rootkey.ai/api-v1/. Listing deleted items - 600 requests per minute, shared by:
  • GET /platform/vaults/deleted
  • GET /platform/files/deleted
  • GET /platform/records/deleted
Restoring deleted items - 120 requests per minute, shared by:
  • PATCH /platform/vaults/{vaultAddress}/restore
  • PATCH /platform/files/{fileId}/restore
  • PATCH /platform/records/{recordId}/restore
These two limits count requests per client IP address, the public address your requests reach ROOTKey from, whatever API key they carry. Servers that reach ROOTKey through the same outbound address, behind a NAT gateway for example, share one count. A count starts again at zero at the beginning of every clock minute; it is not a sliding window. Over a rate limit, the API refuses the request with a 429 Too Many Requests, a Retry-After header, and a JSON error:
Retry-After is the number of seconds to wait before you send the request again, and retryAfter in the error repeats it. For the limits on deleted items it is the time until the next clock minute begins, so between 1 and 60. The refused request was not carried out, so sending it again after that wait is safe.

Plan quotas

Your plan sets quotas: the number of API requests you can make each month, and how many files, records and vaults you can hold. Every API request counts toward the monthly quota of API requests. A request that would take you over a quota is refused with usage_limit_exceeded, a 400. Its details object names the quota and has an upgrade_url. This is not a rate limit, and it comes without Retry-After. The same request sent a few seconds later fails the same way until the quota resets or the plan changes, so do not retry it automatically. Plan quotas, and the API rate limit of each plan, are listed on the pricing pages: To define a plan for your needs, contact [email protected].

When ROOTKey is too busy

When ROOTKey is too busy to take a request for a moment, it answers 503 Service Unavailable with errorCode service_unavailable and a Retry-After header of a few seconds. retryAfterSeconds in the error repeats it. Nothing was wrong with the request, and the same request a moment later will very likely succeed: wait the number of seconds in Retry-After, then send it again. The number differs a little from one response to the next on purpose, so clients that were refused together do not all come back together. If the request was an upload, check before you send it again. In the rare case where the busy moment came after ROOTKey had sent the file for anchoring, the file may be anchored already; creation_outcome_unknown describes how to check.

On-premise installations

An on-premise installation answers on your own address, and the ingress in front of it can also limit requests per client IP address. A request over that limit is refused by the ingress, not by the API: it gets a 503 with no Retry-After header and no JSON error. Treat it like any other 503 and wait, a little longer each time it repeats, before you send the request again. Ask whoever runs the installation what the limit is; it is set in their configuration.

Blockchain writes

Operations that anchor to the blockchain (RKP-1) are additionally bound by Polygon block times: the API accepts the write and answers with the operation PENDING and its transaction hash, and the anchor is confirmed once the transaction is mined. RKP-2 and RKP-3 are in development and not available yet. The protocol overview says what each protocol offers.

Handling limits in your integration

Send a request again only when it is safe to, and wait as long as the response asks. A 429 is always safe to repeat, and a 503 is safe to repeat for a request that only reads. Retrying a failed request on the errors page says which other failures are safe and what to check first.
Recommendations:
  • Use the Retry-After value instead of a fixed backoff, and add a little random delay (jitter) so that clients refused together do not come back together
  • Spread requests evenly over the minute instead of sending them in bursts
  • Pace bulk work on deleted items to stay under the limits above: 120 restores a minute is two a second
  • Do not retry usage_limit_exceeded; it fails the same way until the quota resets or the plan changes
  • Do not retry other failures automatically unless the errors page says they are safe to retry

Test keys

A test API key is subject to the same plan quotas as a live key, and the limits above that count requests by client IP address apply to it in the same way.

If you reach a limit

  • 429 on listing or restoring deleted items - spread the requests over time. These limits count per client IP address and are the same for every plan, so a larger plan does not raise them. If a legitimate workload needs more, contact [email protected].
  • Any other 429 - spread the requests over the minute, or view plans for a plan with a higher rate limit.
  • usage_limit_exceeded - view plans and upgrade, or contact [email protected] to define a plan for your needs.
  • 503 that keeps coming back - contact [email protected] quoting the requestId from the error response.