Do not expose your API key in client-side code. Make API calls from your server and return the results to your frontend.
API Reference
StableComplete reference for the SnapAddress API — endpoints, authentication, and request format.
Base URL
https://api.snapaddress.io/v1
All API requests must use HTTPS. The getAddress.io and Loqate compatibility endpoints are mounted at the root (https://api.snapaddress.io), not under /v1.
Authentication
Pass your API key using the x-api-key header:
curl -H "x-api-key: YOUR_API_KEY" "https://api.snapaddress.io/v1/postcodes/SW1A2AA"The native /v1 endpoints accept the key in the x-api-key header only. The compatibility endpoints additionally accept a query-parameter key (api-key for getAddress.io, Key for Loqate) to match the APIs they replace.
Keep your key server-side — passing it in the header keeps it out of browser history and access logs.
You can generate API keys from the dashboard. Each key is scoped to your account and can be revoked at any time.
Warning
Endpoints
Which endpoints spend a credit
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.
A charged request that returns no match (404) is not charged: no address data is returned, so it is not a Transaction under Royal Mail's definition, and the credit is returned to your account before the response is sent. The same goes for a page beyond the last page (200 with no addresses). Follow next_page rather than counting pages all the same. Requests rejected before the search runs never spend one: malformed queries (400, or 404 on /find), missing or revoked keys (401), and requests refused for an empty balance (429 / 402). A partial postcode too broad to return complete (422 postcode_too_broad, on /v1/postcodes, /find and Loqate Find) 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. Full detail in Rate Limits & Errors.
Find addresses by postcode
GET /v1/postcodes/{postcode}
Returns all addresses at the given UK postcode. Spends one credit. Up to 100 addresses are returned per request; postcodes holding more are paged with page, and each page is a separate lookup.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
postcode | path | Yes | UK postcode (spaces optional, case insensitive) |
x-api-key | header | Yes | Your API key |
page | query | No | Page number, starting at 1 (default 1) |
limit | query | No | Addresses per page, 1–100 (default 100) |
Example request:
curl -H "x-api-key: YOUR_API_KEY" \
"https://api.snapaddress.io/v1/postcodes/SW1A2AA"Example response:
{
"postcode": "SW1A 2AA",
"addresses": [
{
"line_1": "Prime Minister & First Lord Of The Treasury",
"line_2": "10 Downing Street",
"line_3": "",
"town": "LONDON",
"county": "Greater London",
"postcode": "SW1A 2AA",
"country": "England",
"udprn": "23747771",
"formatted_address": "Prime Minister & First Lord Of The Treasury, 10 Downing Street, LONDON, SW1A 2AA",
"organisation": "Prime Minister & First Lord Of The Treasury",
"department": "",
"sub_building": "",
"building_name": "",
"building_number": "10",
"street": "Downing Street",
"dependent_street": "",
"double_locality": "",
"locality": "",
"po_box": "",
"parent_udprn": null,
"type": "commercial",
"label": "Prime Minister & First Lord Of The Treasury\n10 Downing Street\nLONDON\nSW1A 2AA\nUNITED KINGDOM",
"barcode": "(SW1A2AA1AM)"
}
],
"count": 1,
"page": 1,
"limit": 100,
"total": 1,
"next_page": null
}Autocomplete
GET /v1/autocomplete?q={query}
Search by partial postcode, street, building, or business name (minimum 2 characters). Free — this endpoint does not spend a credit, but it does require a key with a balance above zero. The response shape depends on the query:
- Postcode-shaped queries (e.g.
SW1A,PL1) return suggestions grouped by postcode — each suggestion is one postcode with itsaddress_count. Up to 15 are returned. - Street, building, or business name queries (e.g.
Armada,Iceland) return individual matching addresses, each with anaddress_countof1. Up to 12 are returned.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | query | Yes | Search text — minimum 2 characters. Shorter queries return a 400 error. |
limit | query | No | Maximum suggestions, 1–20 (default 10) |
x-api-key | header | Yes | Your API key |
Tip
Check q.length >= 2 before calling the API. Autocomplete is free, so this costs you nothing either way — it just avoids a pointless round-trip on the first keystroke. Show a hint like "Keep typing for results..." instead.
Example request:
curl -H "x-api-key: YOUR_API_KEY" \
"https://api.snapaddress.io/v1/autocomplete?q=SW1A"Example response:
{
"query": "SW1A",
"suggestions": [
{
"type": "postcode",
"postcode": "SW1A 1RJ",
"summary": "SW1A 1RJ - Arlington Street, LONDON",
"address_count": 57,
"udprn": null
},
{
"type": "postcode",
"postcode": "SW1A 2EL",
"summary": "SW1A 2EL - Whitehall Court, LONDON",
"address_count": 54,
"udprn": null
}
],
"count": 2
}Each suggestion has a type. For a "postcode" suggestion, use its postcode to fetch full addresses via the Find addresses by postcode endpoint above. An "address" suggestion (from a street, building or business-name query) carries a udprn: fetch that one address via Get address by UDPRN below.
Get address by UDPRN
GET /v1/addresses/{udprn}
Retrieve a single address by its Royal Mail UDPRN (Unique Delivery Point Reference Number). Spends one credit. Useful for looking up a specific address you have previously stored.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
udprn | path | Yes | The UDPRN of the address |
x-api-key | header | Yes | Your API key |
Example request:
curl -H "x-api-key: YOUR_API_KEY" \
"https://api.snapaddress.io/v1/addresses/23747771"Example response:
{
"line_1": "Prime Minister & First Lord Of The Treasury",
"line_2": "10 Downing Street",
"line_3": "",
"town": "LONDON",
"county": "Greater London",
"postcode": "SW1A 2AA",
"country": "England",
"udprn": "23747771",
"formatted_address": "Prime Minister & First Lord Of The Treasury, 10 Downing Street, LONDON, SW1A 2AA",
"organisation": "Prime Minister & First Lord Of The Treasury",
"department": "",
"sub_building": "",
"building_name": "",
"building_number": "10",
"street": "Downing Street",
"dependent_street": "",
"double_locality": "",
"locality": "",
"po_box": "",
"parent_udprn": null,
"type": "commercial",
"label": "Prime Minister & First Lord Of The Treasury\n10 Downing Street\nLONDON\nSW1A 2AA\nUNITED KINGDOM",
"barcode": "(SW1A2AA1AM)"
}The address object is the same as each entry in a postcode lookup's addresses. An unknown UDPRN returns 404 (address_not_found), which is not charged.
Check your credit balance
GET /plan
Returns the spendable credit balance for your account, plus the expiry of the soonest-to-expire credit pack. Mounted at the root, not under /v1. Read-only — this endpoint does not consume a credit.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
x-api-key | header | Yes | Your API key |
Example request:
curl -H "x-api-key: YOUR_API_KEY" \
"https://api.snapaddress.io/plan"Example response:
{
"balance": 447,
"soonest_expiry": "2027-06-01T00:00:00+00:00"
}balance is the total of all non-expired credits. soonest_expiry is when the pack spent next (under FIFO) expires, or null if you have no live credits.
Postcode formatting
The API accepts postcodes with or without spaces, in any case. All of these are equivalent:
SW1A 2AAsw1a2aaSW1A2AAsw1a 2aa
The response always returns the postcode in its correctly formatted form.
Content type
All responses are returned as application/json with UTF-8 encoding.
Calling from a browser
Call the API from your server, not from the browser. In production the API only accepts cross-origin browser requests from SnapAddress's own sites, and a key in client-side code can be read by anyone. Have your frontend call a route on your backend, which calls SnapAddress with the key from an environment variable — see Getting Started for an example.
Compatibility endpoints
SnapAddress provides drop-in compatible endpoints for teams migrating from other providers. Change your base URL — keep your existing integration. These endpoints are mounted at the root (https://api.snapaddress.io), not under /v1.
getAddress.io compatibility
These endpoints mirror the getAddress.io request paths and response shapes. Auth uses the api-key query parameter (the x-api-key header also works).
| Endpoint | Description |
|---|---|
GET /autocomplete/{query}?api-key=KEY | Address autocomplete. Free — no credit spent. Returns { suggestions: [{ id, address, url }] } |
GET /find/{postcode}?api-key=KEY | Find addresses by postcode. Spends one credit. Returns { postcode, addresses }, where addresses is an array of comma-separated strings |
GET /find/{postcode}?api-key=KEY&expand=true | Same, but addresses is an array of structured objects (line_1–line_4, locality, town_or_city, county, district, country, building_number, building_name, thoroughfare, residential) |
GET /get/{id}?api-key=KEY | Retrieve a single address by ID (the id is the UDPRN). Spends one credit. |
/find returns up to 100 addresses per page and includes page, limit, total and next_page; request further pages with ?page=2 (each page is a lookup). Latitude and longitude are not returned (the underlying PAF data has no geo component). See the getAddress.io migration guide for a step-by-step walkthrough.
Loqate compatibility
These endpoints mirror the Loqate Capture Interactive API. Auth uses the Key query parameter (the api-key query parameter or x-api-key header also work).
| Endpoint | Description |
|---|---|
GET /Capture/Interactive/Find/v1.1/json3.ws?Key=KEY&Text=query&Countries=GB | Search for addresses. Free — no credit spent. Returns { Items: [{ Id, Type, Text, Highlight, Description }] } |
GET /Capture/Interactive/Retrieve/v1.1/json3.ws?Key=KEY&Id=id | Retrieve a full address by ID. Spends one credit. Returns { Items: [{ Line1, Line2, City, PostalCode, ... }] } |
The Find endpoint supports the Container parameter for drill-down searches. When a result has Type: "Postcode", its Id is the postcode itself — pass that value as Container to expand it into individual addresses. A drill-down returns up to 100 addresses; if more remain, the last item has Type: "Container" — pass its Id back as Container for the next page (free, like every Find). See the Loqate migration guide for the full flow.
On every endpoint — native and compatible — a BFPO address can be looked up by its number (BFPO 16 or BFPO16), and a postcode typed with a letter for a digit (SWIA OAA) is corrected when the search as typed finds nothing. See the October 2026 changelog.
See also
- Response Format — detailed field breakdown
- Rate Limits & Errors — status codes and troubleshooting
- Migrating from getAddress.io — step-by-step guide
- Migrating from Loqate — step-by-step guide