Replacing getAddress.io? Free drop-in replacement →
·

Error Handling

Every error response follows a consistent JSON format. Use HTTP status codes to handle errors programmatically.

Error format

All error responses return JSON with a consistent structure:

Error Response
{
  "error": {
    "code": "not_found",
    "message": "No property found with UPRN 999999999999"
  }
}
Field Type Description
error object Error detail object (always present on non-2xx responses)
error.code string Machine-readable error code (lowercase_snake_case). Safe to switch on in code.
error.message string Human-readable description. May change — don't match on this programmatically.

HTTP status codes

200

OK

Request succeeded. Response body contains the requested data.

400

Bad Request

Missing or invalid parameters. Check the message field for specifics.

{"error": {"code": "bad_request", "message": "Missing required parameter: postcode"}}
401

Unauthorized

Missing or invalid API key. Make sure you're using the Authorization: Api-Key header.

{"error": {"code": "authentication_required", "message": "Valid API key required"}}
403

Forbidden

API key is valid but doesn't have permission for this resource. May indicate a revoked key or tier restriction.

404

Not Found

The requested resource doesn't exist. For property endpoints, this means no data for that UPRN.

{"error": {"code": "not_found", "message": "No property found with UPRN 999999999999"}}
429

Rate Limit Exceeded

You've exceeded your plan's monthly request limit or per-second rate limit. Check the X-RateLimit-* headers.

{"error": {"code": "rate_limit_exceeded", "message": "Monthly request limit reached. Upgrade at homedata.co.uk/pricing"}}

Upgrade your plan for higher limits

500

Internal Server Error

Something went wrong on our side. These are rare and we're alerted automatically. If persistent, please contact us.

504

Gateway Timeout

Request took too long to process. Retry with exponential backoff. If frequent, the endpoint may be under heavy load.

Error codes

All error codes use lowercase_snake_case. Switch on error.code to handle errors programmatically.

Code Status Description
authentication_required 401 Missing or invalid API key
forbidden 403 API key is valid but revoked or lacks permission
endpoint_not_allowed 403 Your plan doesn't include this endpoint. Upgrade for access.
not_found 404 No data for the requested resource (UPRN, postcode, URN, etc.)
invalid_params 422 Missing or invalid query parameters
invalid_uprn 422 UPRN format is invalid (must be 8–12 digits)
invalid_postcode 422 Postcode doesn't match UK format
missing_postcode 422 Required postcode parameter not provided
rate_limit_exceeded 429 Monthly request quota or per-second rate limit reached
service_unavailable 503 Data source temporarily unavailable. Retry with backoff.

Handling errors in code

# Python — switch on error.code
response = requests.get(url, headers=headers)

if not response.ok:
    err = response.json().get("error", {})
    code = err.get("code")

    if code == "authentication_required":
        raise AuthError(err["message"])
    elif code == "rate_limit_exceeded":
        time.sleep(60)  # back off
    elif code == "not_found":
        return None
    else:
        raise ApiError(f"{code}: {err.get('message')}")

Rate limiting

Every authenticated response includes rate limit headers:

Header Description
X-RateLimit-Limit Your plan's monthly request allowance
X-RateLimit-Remaining Requests remaining in current billing period
X-RateLimit-Reset Unix timestamp when your limit resets (start of next billing period)

Best practice: handle 429 gracefully

# Python — retry with backoff
import time

def api_call(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)
        if response.status_code == 429:
            wait = 2 ** attempt  # 1s, 2s, 4s
            time.sleep(wait)
            continue
        return response.json()
    raise Exception("Rate limit exceeded after retries")