Limits and retries
Requests stop at 30 seconds, concurrency should stay low, and every POST should carry an Idempotency-Key. Together they mean a retry is never charged twice.
30-second request cap
The API stops any request that runs longer than 30 seconds and returns 504 timeout. Set your HTTP client's timeout a little above that, for example 35 seconds, so you receive our response rather than your own timeout.
Keep concurrency low
Send a few requests at a time, not a burst. For bulk work, queue the requests and let a small number of workers take them in turn.
If you send too many, the API returns 429 rate-limited with a Retry-After header. Wait that many seconds before you try again.
HTTP/1.1 429 Too Many Requests
Retry-After: 5
Daily limit
Each account can make 5,000 paid calls and 1,000 test calls a day. The counts start again at midnight UTC. Past a limit, calls return 429 rate-limited with "code": "daily_limit" in the body. Do not retry those: stop until midnight UTC. If you need more paid calls, write to us and we will raise the limit.
Always send an Idempotency-Key
Send a new Idempotency-Key, such as a UUID, with every POST /partners/v1/valuations. Keep it with the request, and reuse it only to retry that same request.
- Retry with the same key and you are charged once, however many times you retry.
- Retry while the first call is still running and you get
409 request-in-progress. Wait, then retry with the same key. - Send the key with a different request and you get
422 idempotency-key-reused. Use a new key for a new request.
What to retry
| Status | Type | Retry | How |
|---|---|---|---|
401 | Token | Once | Get a new token first |
409 | request-in-progress | Yes | After a short wait, with the same key |
429 | rate-limited | Yes, unless its code is daily_limit | After Retry-After seconds |
503 | data-unavailable | Yes | Shortly, with the same key. Never charged. |
504 | timeout | Yes | With the same key |
400 403 404 422 | See Errors | No | Fix the request or the account first |
A retry loop
const RETRY = new Set([409, 429, 503, 504]);
async function valueWithRetries(body, token) {
const key = crypto.randomUUID(); // one key for every attempt at this valuation
for (let attempt = 0; attempt < 4; attempt++) {
const res = await fetch("https://api.checkmystreet.co.uk/partners/v1/valuations", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": key,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(35000),
});
if (!RETRY.has(res.status)) return res;
// A daily limit lasts until midnight UTC: hand it back rather than wait.
if (res.status === 429 && (await res.clone().json()).code === "daily_limit") return res;
const wait = Number(res.headers.get("Retry-After")) || 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
}
throw new Error("Valuation failed after 4 attempts");
}