Errors and limits
The refusals every keyed call shares, in the interface description's own words: one row per status code, the calls that answer it, and the count each scope allows per key in one fixed minute. The one error shape a refusal carries stands on the API reference.
The status codes
Every refusal the document's calls answer, one row per status code. Each sentence is the document's own, and the calls named under it answer with exactly that sentence.
| Status | What it answers |
|---|---|
| 400 | The query could not be read. Answered by The request body could not be read. Answered by |
| 401 | The key is missing, malformed, unknown, revoked or expired. Answered by |
| 403 | The key does not carry the scope, or the wallets name chains outside the distributor's scope. The call is also refused with 403, nothing read, when the distributor is paused, suspended or closed, when the key is paused, or when the key presents from an origin it does not allow. Answered by The key does not carry the scope. The call is also refused with 403, nothing read, when the distributor is paused, suspended or closed, when the key is paused, or when the key presents from an origin it does not allow. Answered by The key does not carry the scope, or the challenge itself was refused: the venue is paused or not a self-custody venue, the benefit is not a claimable offer, or a wallet sits on a chain the venue does not serve. The call is also refused with 403, nothing read, when the distributor is paused, suspended or closed, when the key is paused, or when the key presents from an origin it does not allow. Answered by The key does not carry the scope, or the claim itself was refused: the challenge was never verified, was issued for another distributor or another benefit, or the holder's own world refused the claim, and the attested subject's statement the same - unsigned or unverifiable, expired, naming an instrument the distributor does not list or the registry no longer keeps active, naming another tenant, or for a benefit the account's holder already claimed once. The call is also refused with 403, nothing read, when the distributor is paused, suspended or closed, when the key is paused, or when the key presents from an origin it does not allow. Answered by The key does not carry the scope, or the fulfilment was already confirmed: the confirm that stands is the one that landed first. The call is also refused with 403, nothing read, when the distributor is paused, suspended or closed, when the key is paused, or when the key presents from an origin it does not allow. Answered by The key does not carry the scope, or the return address is not one the distributor's profile allows. The call is also refused with 403, nothing read, when the distributor is paused, suspended or closed, when the key is paused, or when the key presents from an origin it does not allow. Answered by |
| 404 | No claim answers this id under this distributor's key: an unknown id, or one another distributor's key recorded. The answer is the same for both, so no claim id can be probed. Answered by No fulfilment answers this id under this distributor's key: an unknown id, or one another distributor's key recorded. The answer is the same for both, so no fulfilment id can be probed. Answered by No Connect session answers this id under this distributor's key: an unknown id, a malformed id, or one another distributor's key created. The answer is the same for both, so no session id can be probed. Answered by |
| 409 | The claim the id names stands rejected or taken back, so it carries no redemption link to reissue. Answered by |
| 429 | The key made too many calls this minute, or the platform has used today's live wallet reads; the Retry-After header names the seconds until the next window opens, or until the reads open again. Nothing was read. Answered by The key made too many calls this minute. The Retry-After header names the seconds until the next window opens. Nothing was read. Answered by |
| 500 | The read failed inside Yutai. Nothing was changed. Answered by |
| 503 | The data source this read needs is not live yet, or the owners' blockchain switch does not allow the read, so the read is refused. Nothing was read. Answered by The data source this read needs is not live yet, so the read is refused. Nothing was read. Answered by |
The limits
Once the key a call presents stands, the call is counted, per key and per scope, in one fixed window of 60 seconds that starts on the minute. A call past the scope's own count is refused without being counted: the refusal answers the one error shape the Errors section carries, and its Retry-After header names the seconds to wait until the next window opens.
- holders.resolve
- At most 60 calls per key and scope in the window.
- credentials.read
- At most 60 calls per key and scope in the window.
- benefits.list
- At most 60 calls per key and scope in the window.
- eligibility.read
- At most 120 calls per key and scope in the window.
- availability.read
- At most 600 calls per key and scope in the window.
- claims.write
- At most 60 calls per key and scope in the window.
- connect.write
- At most 60 calls per key and scope in the window.
- connect.read
- At most 60 calls per key and scope in the window.
- How long an answer stands
- Each read's answer is private to the distributor that asked and may stand for 60 seconds.
A call past its scope's count answers the 429 row above: nothing was read, and the Retry-After header names when the next window opens.
When a call is limited
A limited call answers the status line, the Retry-After header and the error body below, with the interface description's own sentence for the refusal most calls share.
HTTP/1.1 429 Too Many Requests
Retry-After: 23
{
"message": "The key made too many calls this minute. The Retry-After header names the seconds until the next window opens. Nothing was read."
}The loop reads that header, waits the seconds it names and tries the same call again at most three times.
async function callWithWait(url, options) {
for (let attempt = 0; attempt < 3; attempt += 1) {
const response = await fetch(url, options);
if (response.status !== 429) return response;
const seconds = Number(response.headers.get("Retry-After"));
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}
throw new Error("the call was limited after three tries");
}