Rate Limits & Errors
StableHTTP status codes, rate limiting, and troubleshooting common API errors.
HTTP status codes
The API uses standard HTTP status codes to indicate success or failure:
| Code | Meaning | Description |
|---|---|---|
200 | OK | Request succeeded. Response body contains the address data. |
400 | Bad Request | The postcode or query is missing or in an invalid format. |
401 | Unauthorised | API key is missing, invalid, or revoked. |
404 | Not Found | The postcode or address is correctly formatted but does not exist in PAF. On a charged endpoint this is not charged: the credit is returned before the response is sent — see Credit usage. On the getAddress.io-compatible /find, a malformed postcode also returns 404 (as getAddress.io-style clients expect), and that one is free. |
422 | Unprocessable | A partial postcode matches too many addresses to return complete (postcode_too_broad). Use a longer postcode — a sector such as M20 2, or a full postcode. Retrying gives the same answer. On a charged endpoint it uses a credit, which we return to your account within a few days — no need to contact us. |
429 | No Credits | Your credit balance is exhausted. (Native and getAddress.io-compatible endpoints.) |
402 | Payment Required | Credit balance exhausted — Loqate-compatible endpoints only. |
503 | Service Unavailable | Temporary problem on our side. Safe to retry after a short wait. |
500 | Internal Server Error | Something went wrong on our end. Retry after a short delay. |
Error response format
Native (/v1) and Loqate responses return a machine-readable error code and a human-readable message:
{
"error": "invalid_postcode",
"message": "The postcode format is invalid."
}Validation failures (400) may also include a details array. The getAddress.io-compatible endpoints instead return a single Message field, matching getAddress.io's format.
Request limits
Requests are rate-limited per IP address at our network edge: up to 100 requests in any 10 seconds, on every path except /health. Go over it and requests from that IP get a 429 for the next 10 seconds. This 429 comes from the edge (Cloudflare), so its body isn't the API's JSON error format — retry after a short pause rather than parsing it.
That's different from the 429 for an empty credit balance on the native and getAddress.io-compatible endpoints, which is JSON: { "error": "rate_limited", "message": "Out of credits. Top up at snapaddress.io/dashboard." }.
Beyond that, your throughput is bounded by your credit balance — each completed lookup spends one credit (see below). Type-ahead suggestion requests are free, but still require a balance above zero.
If the search backend is briefly unavailable you may receive a 503. This is transient — retry after a short delay with exponential backoff.
Credit usage
SnapAddress is billed as one-off credit packs, not a monthly subscription. One credit is spent per completed lookup.
A lookup is a request that returns address data: a full postcode lookup, or an address selected from autocomplete. Searching as the customer types is free, so a completed address search normally uses one lookup. Opening a second suggestion uses another, and so does each further page of a postcode with more than 100 addresses.
| Charged — 1 credit | Free — needs a key with a balance above zero |
|---|---|
GET /v1/postcodes/{postcode} | GET /v1/autocomplete |
GET /v1/addresses/{udprn} | GET /autocomplete/{query} (getAddress.io-compatible) |
GET /find/{postcode} (getAddress.io-compatible) | Loqate Find |
GET /get/{id} (getAddress.io-compatible) | |
Loqate Retrieve |
GET /plan is read-only: it never spends a credit and works at a zero balance.
The free endpoints are not unmetered — they are part of an address capture flow that ends in a lookup. They still need credits on the account, so at a zero balance suggestions stop too (429 on the native and getAddress.io endpoints, 402 on Loqate).
A lookup that finds nothing is not charged. A charged endpoint returning 404 — a valid query with no matching address — does not spend a credit: no address data is returned, so it is not a Transaction under Royal Mail's definition. The same goes for a page beyond the last page, which returns 200 with no addresses. Follow next_page rather than counting pages all the same.
Requests rejected before the search runs never spend a credit: malformed queries (400, or 404 on /find), missing or revoked keys (401), and requests refused for an empty balance (429 / 402). A credit is taken before the search executes, so in the rare case where the backend then fails (503 / 500) it has already been spent — we restore it automatically before the error response is sent, and it shows on your dashboard as a credit adjustment. If you ever see one that wasn't, tell us.
A partial postcode too broad to return complete (422) has already been searched, so on a charged endpoint it uses a credit; we return it to your account within a few days (it shows as a “Credit adjustment”), with no need to contact us. Use a longer postcode rather than retrying.
GET /v1/postcodes/{postcode} returns up to 100 addresses per request. Postcodes holding more than 100 addresses are paged with the page parameter, and each page is a separate lookup.
Credits are spent oldest-first — the soonest-to-expire pack is used before newer ones. Check your remaining balance on the dashboard or via the API (GET /plan).
Credit packs are valid for 12 months from purchase; the free trial credits are valid for 3 months. Unused credits expire at the end of that period — a Royal Mail PAF licensing requirement that every licensed provider works under. Topping up does not extend the validity of credits you already hold.
| Pack | Lookups | Price | Per lookup |
|---|---|---|---|
| Free | 100 | £0 | — |
| Starter | 500 | £17.50 | 3.5p |
| Standard | 2,000 | £60 | 3p |
| Business | 5,000 | £140 | 2.8p |
| Pro | 15,000 | £375 | 2.5p |
Prices are current at the time of writing — see the pricing page for the latest.
Running out of credits
When your balance reaches zero, lookups are rejected — not silently billed or queued:
- Native (
/v1/...) and getAddress.io-compatible endpoints return429. - Loqate-compatible endpoints return
402. Loqate itself reports this as error 3, "Account out of credit", in the response body rather than as an HTTP status, so a client moving from Loqate should check for402— see Migrating from Loqate.
Buy another credit pack from the pricing page to resume. The WooCommerce plugin falls back to manual address entry when credits run out, so checkout keeps taking orders.
Common issues
"The postcode format is invalid." (400)
The postcode contains characters that are not valid in a UK postcode. Ensure you are passing only the postcode, without additional text or special characters.
Query too short (400)
The autocomplete endpoint requires at least 2 characters. Single-character queries return a 400 error. Check q.length >= 2 client-side before calling the API to avoid unnecessary errors. Autocomplete is free, so this costs you nothing either way — it just saves a round-trip.
"Unauthorised" (401)
- Check that your API key is correct and has not been revoked
- On the native
/v1endpoints, pass the key as thex-api-keyheader. The getAddress.io and Loqate compatibility endpoints also accept it as a query parameter (api-keyfor getAddress.io,Keyfor Loqate) to match the APIs they replace. - Confirm that your account is active
"Postcode not found" (404)
The postcode is syntactically valid but does not exist in the Royal Mail PAF database. This can happen with:
- Newly created postcodes that have not yet been added to PAF
- Postcodes that have been terminated
- Typos that happen to match valid postcode formatting
"No credits" (429 or 402)
Your credit balance is exhausted. Native and getAddress.io endpoints return 429; Loqate endpoints return 402. Buy another credit pack from the pricing page to resume.
Timeouts
If requests are timing out, check:
- Your server can reach
api.snapaddress.ioover HTTPS (port 443) - No firewall or proxy is blocking the connection
A 503 response means the search backend is briefly unavailable — retry after a short delay.
If the issue persists, email snapaddress@clearpathlabs.co.uk.