GovData Docs

Error Reference

All API errors follow a consistent format with a machine-readable code and human-readable message.

Error format

Every error response uses this structure:

{
  "error": {
    "code": "error_code",
    "message": "A human-readable description of what went wrong.",
    "documentation_url": "https://docs.govdata.dev/errors"
  }
}
Field Description
code Machine-readable error code (use this for programmatic handling)
message Human-readable description (may change, don't parse this)
documentation_url Link to relevant documentation

Error codes

400 Bad Request

Code Description
bad_request Malformed request body or missing required parameters
invalid_region Invalid region slug. Valid values: england_wales_ni, scotland
invalid_year Year parameter is not a valid 4-digit number

401 Unauthorized

Code Description
unauthorized Missing, malformed, or invalid API key. Check your Authorization header.

403 Forbidden

Code Description
forbidden Your API key does not have permission to access this resource.

404 Not Found

Code Description
not_found The requested resource doesn't exist. Check the URL and resource identifier.
invalid_tax_year Tax year not found. Format: YYYY-YY (e.g., 2025-26)
no_active_tax_year No active tax year configured (returned from /current endpoint)

422 Unprocessable Entity

Code Description
invalid_type Invalid NI calculation type. Valid values: employed, self_employed

429 Too Many Requests

Code Description
rate_limit_exceeded Per-minute rate limit exceeded. See Rate Limits.
insufficient_credits Insufficient credits. Purchase a credit pack or enable auto top-up on your billing page.

500 Internal Server Error

An unexpected error occurred on our end. If this persists, please contact support.

Handling errors

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
  http.request(req)
}

case res.code
when "200"
  JSON.parse(res.body)["data"]
when "401"
  raise "Invalid API key"
when "429"
  sleep(res["Retry-After"].to_i)
  retry
else
  error = JSON.parse(res.body)["error"]
  raise "#{error["code"]}: #{error["message"]}"
end