{
  "openapi": "3.1.0",
  "info": {
    "title": "Addrexy API",
    "version": "1.0.0",
    "summary": "Address autocomplete, address verification, forward geocode and reverse geocode.",
    "description": "**DRAFT: Addrexy is not live yet.** It will run as a tenant of the white-label developer portal at `https://addrexy.com`. In version 1 the portal and documentation are those of the existing white-label tenant `https://intodq2.devapicloud.com`; the API and its documentation are the same. This file describes the white-label API as documented; it does not change it.\n\nFour atomic operations: **autocomplete** (suggest addresses as someone types), **verify** (check one address against postal reference data; coverage varies by country), **forward geocode** (address to latitude and longitude) and **reverse geocode** (latitude and longitude to address). Authentication is HTTP Basic with an API key and secret. Every request needs an `X-Session-Token` (a UUID v4).\n\nVerify returns `matchScore` from 0 to 5. There is no confidence percentage. Use `matchScore` and `matchDetails`; do not compute your own number. Decision rules for software are in `x-agent-decision-rules` below and at https://addrexy.com/agent/build.\n\nAccess: a person gets an API key and secret from the portal (Account, API Keys). Credits are allocated by the portal administrator. See https://addrexy.com/agent/start.",
    "x-status": "draft: not live"
  },
  "externalDocs": {
    "description": "Pages written for AI agents",
    "url": "https://addrexy.com/agent"
  },
  "servers": [
    {
      "url": "https://api.devapicloud.com/v1",
      "description": "White-label API (shared base URL; your key identifies your tenant)"
    }
  ],
  "security": [
    {
      "basicAuth": []
    }
  ],
  "tags": [
    {
      "name": "Autocomplete",
      "description": "Suggest addresses as someone types."
    },
    {
      "name": "Verify",
      "description": "Verify and standardise one address."
    },
    {
      "name": "Geocode",
      "description": "Forward geocode (address to coordinates) and reverse geocode (coordinates to address)."
    }
  ],
  "x-agent-native": {
    "scope": "Atomic address primitives only. No business capability.",
    "confidence_percentage": false,
    "score_field": "result.matchScore",
    "audit_keys": [
      "X-Request-Id response header (always)",
      "requestId (autocomplete body)",
      "result.meta.requestId (verify and geocode bodies)",
      "result.meta.referenceId (your own id)"
    ],
    "access": "A person creates the key and secret in the portal and gives them to the agent. An agent cannot create an account by itself. Credits: allocated by the administrator; cost per call and behaviour at zero credits are not documented.",
    "rate_limits_per_key": {
      "autocomplete_rps": 50,
      "verify_rps": 200,
      "forward_geocode_rps": 200,
      "reverse_geocode_rps": 200,
      "scope": "Per API key, per second, independent for each API"
    },
    "recommended_flow": "autocomplete (as the user types) -> verify (the address chosen) -> forward geocode (the verified address.components) when coordinates are needed. Reverse geocode is separate: coordinates in, address out.",
    "pages": {
      "start": "https://addrexy.com/agent/start",
      "build": "https://addrexy.com/agent/build",
      "operate": "https://addrexy.com/agent/operate"
    }
  },
  "x-agent-decision-rules": {
    "note": "api_documentation applies when a person is present in your application. headless_agent is Addrexy guidance for when no person is available. The API itself returns only matchScore and matchDetails.",
    "verify": [
      {
        "matchScore": 5,
        "api_documentation": "Proceed. Use result.address downstream. No user interaction required.",
        "headless_agent": "Proceed. Store result.address and the request id."
      },
      {
        "matchScore": 4,
        "api_documentation": "Proceed. Minor normalisation. Silent acceptance is acceptable.",
        "headless_agent": "Proceed. Log which components were corrected (componentMatches value 3)."
      },
      {
        "matchScore": 3,
        "api_documentation": "Review. Show the user the corrected address and ask for confirmation.",
        "headless_agent": "Do not treat as verified. Queue for human review. Do not wait for an answer."
      },
      {
        "matchScore": 2,
        "api_documentation": "Flag to the user. Show components that were not found. Allow manual override with confirmation.",
        "headless_agent": "Do not use. Queue for human review with the components whose value is 0."
      },
      {
        "matchScore": 1,
        "api_documentation": "Prompt for re-entry. Do not use for delivery without manual verification.",
        "headless_agent": "Reject. Ask the source for a fuller address."
      },
      {
        "matchScore": 0,
        "api_documentation": "Block submission and prompt for re-entry. Never block silently.",
        "headless_agent": "Reject. Report that no match was found. Do not retry with guessed variations."
      }
    ]
  },
  "paths": {
    "/autocomplete/suggest": {
      "post": {
        "operationId": "suggestAddresses",
        "tags": [
          "Autocomplete"
        ],
        "summary": "Suggest addresses for a partial string",
        "description": "Returns up to 50 ranked suggestions for a partial address. Call it as the user types: debounce at 200 ms, minimum 3 characters, and share one `X-Session-Token` across all keystrokes of one search session. **Autocomplete does not verify.** Call `verifyAddress` on the address the user chooses before you rely on it. Each suggestion already carries structured `addressComponents`, so no second call is needed to fill a form.",
        "parameters": [
          {
            "$ref": "#/components/parameters/XSessionToken"
          },
          {
            "$ref": "#/components/parameters/XRequestId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuggestRequest"
              },
              "examples": {
                "partial": {
                  "summary": "A partial address",
                  "value": {
                    "query": {
                      "addressInput": "20 W 34th",
                      "countryCode": "USA"
                    },
                    "settings": {
                      "candidateLimit": 5,
                      "includeDetails": true,
                      "language": "en_US"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Suggestions, ranked by relevance. An empty array is not an error.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuggestResponse"
                },
                "examples": {
                  "found": {
                    "value": {
                      "requestId": "req_03kz2p8qxy",
                      "result": {
                        "status": "OK",
                        "message": "",
                        "meta": {
                          "language": "en_US",
                          "candidateLimit": 5,
                          "countryCode": "USA",
                          "enrichmentFields": {
                            "requested": [],
                            "granted": []
                          }
                        },
                        "suggestions": [
                          {
                            "displayText": "20 W 34th St, New York, NY 10118, United States",
                            "suggestedAddressLines": [
                              "20 W 34th St",
                              "New York, NY 10118",
                              "United States"
                            ],
                            "postalDeliverable": true,
                            "addressComponents": {
                              "houseNumber": "20",
                              "thoroughfare": "W 34th St",
                              "city": "New York",
                              "district": "New York County",
                              "region": "New York",
                              "neighborhood": "",
                              "postcode": "10118",
                              "postcodeExtension": "",
                              "unit": "",
                              "unitType": "",
                              "countryCode": "USA"
                            },
                            "enrichment": null,
                            "places": null
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/address/verify": {
      "post": {
        "operationId": "verifyAddress",
        "tags": [
          "Verify"
        ],
        "summary": "Verify and standardise one address",
        "description": "Checks one address against postal reference data. Coverage varies by country. Synchronous: one request, one response. Returns `matchScore` 0 to 5, `deliverable`, `addressType`, the standardised `address`, and `matchDetails`. A `matchScore` of 0 is **not** an HTTP error: the call returns 200. Always use `result.address`, not your input; the API may have corrected it. Generate one `X-Session-Token` per verification flow.",
        "parameters": [
          {
            "$ref": "#/components/parameters/XSessionToken"
          },
          {
            "$ref": "#/components/parameters/XRequestId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyRequest"
              },
              "examples": {
                "clean": {
                  "summary": "A free-form address",
                  "value": {
                    "query": {
                      "address": "20 W 34th St, New York NY 10118",
                      "countryCode": "USA"
                    },
                    "settings": {
                      "language": "en_US",
                      "matchLevel": "STANDARD"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A verification result. Branch on `result.matchScore`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyResponse"
                },
                "examples": {
                  "found": {
                    "value": {
                      "result": {
                        "status": "OK",
                        "message": "",
                        "meta": {
                          "requestId": "req_03kz2p8qxy",
                          "referenceId": null,
                          "language": "en_US",
                          "countryCode": "USA"
                        },
                        "matchScore": 4,
                        "deliverable": true,
                        "addressType": "COMMERCIAL",
                        "address": {
                          "formatted": "20 W 34th St, New York, NY 10118",
                          "addressLines": [
                            "20 W 34th St",
                            "New York, NY 10118",
                            "United States"
                          ],
                          "components": {
                            "houseNumber": "20",
                            "thoroughfare": "W 34th St",
                            "placeName": "",
                            "unitType": "",
                            "unit": "",
                            "city": "New York",
                            "suburb": "",
                            "district": "New York County",
                            "postcode": "10118",
                            "postcodeExt": "",
                            "region": "New York",
                            "adminAreaCode": "US-NY",
                            "countryCode": "USA"
                          },
                          "nationalId": null
                        },
                        "matchDetails": {
                          "matchType": "ADDRESS",
                          "componentMatches": {
                            "houseNumber": {
                              "value": 4,
                              "meaning": "Verified without changes"
                            },
                            "thoroughfare": {
                              "value": 4,
                              "meaning": "Verified without changes"
                            },
                            "city": {
                              "value": 4,
                              "meaning": "Verified without changes"
                            },
                            "district": {
                              "value": 6,
                              "meaning": "Appended using reference data"
                            },
                            "postcode": {
                              "value": 4,
                              "meaning": "Verified without changes"
                            },
                            "region": {
                              "value": 3,
                              "meaning": "Verified and corrected"
                            },
                            "countryCode": {
                              "value": 4,
                              "meaning": "Verified without changes"
                            }
                          }
                        },
                        "parsed": null
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/address/geocode": {
      "post": {
        "operationId": "geocodeAddress",
        "tags": [
          "Geocode"
        ],
        "summary": "Forward geocode: address to coordinates",
        "description": "Converts one address (free text, with optional structured parts) into latitude and longitude, with a standardised address and precision metadata. Synchronous. Request field names in `query` are the same as verify. For best results run `verifyAddress` first and pass the verified `address.components` here. Read `candidates[0].matchScore` (0 to 5) **and** `matchDetails.matchType` **and** `coordinates.locationType`: a high score at `POSTAL_CODE` depth is not building-level accuracy. Candidates are ordered by `matchScore`, highest first; an empty `candidates` array means no match and is a `200`, not an error. The documentation gives no sample response.",
        "parameters": [
          {
            "$ref": "#/components/parameters/XSessionToken"
          },
          {
            "$ref": "#/components/parameters/XRequestId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GeocodeRequest"
              },
              "examples": {
                "structured": {
                  "summary": "A free-form address with structured parts",
                  "value": {
                    "query": {
                      "address": "20 W 34th St, New York NY 10118",
                      "houseNumber": "20",
                      "thoroughfare": "W 34th St",
                      "city": "New York",
                      "region": "NY",
                      "countryCode": "USA"
                    },
                    "settings": {
                      "language": "en_US",
                      "matchLevel": "STANDARD"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Zero or more geocoded candidates. Branch on `candidates[0].matchScore`, `matchPrecision`, `matchDetails.matchType` and `coordinates.locationType`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeocodeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/address/reverse-geocode": {
      "post": {
        "operationId": "reverseGeocode",
        "tags": [
          "Geocode"
        ],
        "summary": "Reverse geocode: coordinates to address",
        "description": "Converts a latitude and longitude (WGS 84) into the nearest standardised postal address within `settings.searchRadius` (default 150 metres). Synchronous. Check `coordinates.distanceMeters` to see how far the matched address is from your point and decide your own acceptance threshold. `query.countryCode` is optional; supplying it helps near borders. An empty `candidates` array is a `200`, not an error. The documentation gives no sample response.",
        "parameters": [
          {
            "$ref": "#/components/parameters/XSessionToken"
          },
          {
            "$ref": "#/components/parameters/XRequestId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReverseGeocodeRequest"
              },
              "examples": {
                "point": {
                  "summary": "A point near the Empire State Building",
                  "value": {
                    "query": {
                      "latitude": 40.7484,
                      "longitude": -73.9857,
                      "countryCode": "USA"
                    },
                    "settings": {
                      "searchRadius": {
                        "value": 150,
                        "unit": "METER"
                      },
                      "maxCandidates": 1,
                      "language": "en_US"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Zero or more address candidates. Check `coordinates.distanceMeters` against your own tolerance.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReverseGeocodeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "basicAuth": {
        "type": "http",
        "scheme": "basic",
        "description": "HTTP Basic. Username is the API key, password is the API secret: `Authorization: Basic base64(ApiKey:ApiSecret)`. Keep both server-side. Never put them in browser code, a mobile bundle, or source control."
      }
    },
    "parameters": {
      "XSessionToken": {
        "name": "X-Session-Token",
        "in": "header",
        "required": true,
        "description": "A UUID v4 that groups related calls for billing and audit. Autocomplete: create it when the address field gets focus and reuse it for the whole search session. Verify: create one per verification flow. A missing or malformed value returns `MISSING_SESSION_TOKEN`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "XRequestId": {
        "name": "X-Request-Id",
        "in": "header",
        "required": false,
        "description": "Optional correlation id you supply (alphanumeric, hyphens, underscores, up to 38 characters). It is echoed on the response. Generated if omitted. Record it and quote it in any support request.",
        "schema": {
          "type": "string",
          "maxLength": 38,
          "pattern": "^[A-Za-z0-9_-]+$"
        }
      }
    },
    "headers": {
      "XRequestId": {
        "description": "Correlation id for this request, on every response including errors.",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "schemas": {
      "CountryCode": {
        "type": "string",
        "minLength": 3,
        "maxLength": 3,
        "pattern": "^[A-Za-z]{3}$",
        "description": "ISO 3166-1 alpha-3, case-insensitive. Must be covered by your subscription.",
        "examples": [
          "USA"
        ]
      },
      "SuggestRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "object",
            "required": [
              "addressInput",
              "countryCode"
            ],
            "properties": {
              "addressInput": {
                "type": "string",
                "minLength": 3,
                "maxLength": 200,
                "description": "The partial address as typed. A plain string, not an array."
              },
              "countryCode": {
                "$ref": "#/components/schemas/CountryCode"
              }
            }
          },
          "settings": {
            "type": "object",
            "properties": {
              "candidateLimit": {
                "type": "integer",
                "minimum": 1,
                "maximum": 50,
                "default": 5
              },
              "language": {
                "type": "string",
                "description": "A locale code in the format the API examples use, such as en_US or fr_FR. Defaults to the country locale."
              },
              "includeDetails": {
                "type": "boolean",
                "default": false,
                "description": "true returns addressComponents and suggestedAddressLines. Use true for form filling."
              },
              "originCoordinates": {
                "type": "array",
                "minItems": 2,
                "maxItems": 2,
                "items": {
                  "type": "number"
                },
                "description": "[longitude, latitude]. Ranks nearby results first."
              },
              "searchRadius": {
                "type": "object",
                "required": [
                  "value",
                  "unit"
                ],
                "description": "Requires originCoordinates.",
                "properties": {
                  "value": {
                    "type": "number"
                  },
                  "unit": {
                    "type": "string",
                    "enum": [
                      "METER",
                      "KILOMETER",
                      "MILE"
                    ]
                  }
                }
              },
              "searchType": {
                "type": "string",
                "enum": [
                  "ADDRESS",
                  "PLACES"
                ],
                "description": "ADDRESS (default) or named places such as landmarks."
              },
              "searchScope": {
                "type": "object",
                "description": "Filter or bias by city and postcode.",
                "required": [
                  "type",
                  "fields"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "filter",
                      "bias"
                    ],
                    "description": "exclude is only valid with filter."
                  },
                  "fields": {
                    "type": "object",
                    "properties": {
                      "include": {
                        "type": "object"
                      },
                      "exclude": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "AddressComponents": {
        "type": "object",
        "description": "Empty string, not null, for components that do not apply.",
        "properties": {
          "houseNumber": {
            "type": "string"
          },
          "thoroughfare": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "district": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "neighborhood": {
            "type": "string"
          },
          "postcode": {
            "type": "string"
          },
          "postcodeExtension": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "unitType": {
            "type": "string"
          },
          "countryCode": {
            "type": "string"
          }
        }
      },
      "Suggestion": {
        "type": "object",
        "required": [
          "displayText"
        ],
        "properties": {
          "displayText": {
            "type": "string",
            "description": "Full address string, localised."
          },
          "suggestedAddressLines": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "null unless includeDetails is true."
          },
          "postalDeliverable": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "true confirmed, false not confirmed, null unknown for this address or country."
          },
          "addressComponents": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AddressComponents"
              },
              {
                "type": "null"
              }
            ],
            "description": "null unless includeDetails is true."
          },
          "enrichment": {
            "type": [
              "object",
              "null"
            ],
            "description": "Future scope. Always null today."
          },
          "places": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "description": "Populated only for searchType PLACES."
          }
        }
      },
      "SuggestResponse": {
        "type": "object",
        "required": [
          "requestId",
          "result"
        ],
        "properties": {
          "requestId": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "required": [
              "status",
              "message",
              "suggestions"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "OK",
                  "ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "meta": {
                "type": "object",
                "description": "Echo of the settings applied.",
                "additionalProperties": true
              },
              "suggestions": {
                "type": "array",
                "maxItems": 50,
                "items": {
                  "$ref": "#/components/schemas/Suggestion"
                }
              }
            }
          }
        }
      },
      "VerifyRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "object",
            "required": [
              "address",
              "countryCode"
            ],
            "description": "Supply structured fields as well as address when you have them; they take precedence over the same token parsed from address.",
            "properties": {
              "referenceId": {
                "type": "string",
                "maxLength": 100,
                "description": "Your own id for this record. Echoed in result.meta.referenceId."
              },
              "address": {
                "type": "string",
                "maxLength": 500,
                "description": "Full address as one unparsed string."
              },
              "countryCode": {
                "$ref": "#/components/schemas/CountryCode"
              },
              "houseNumber": {
                "type": "string",
                "maxLength": 20
              },
              "thoroughfare": {
                "type": "string",
                "maxLength": 150
              },
              "placeName": {
                "type": "string",
                "maxLength": 100
              },
              "unitType": {
                "type": "string",
                "maxLength": 10
              },
              "unit": {
                "type": "string",
                "maxLength": 20
              },
              "suburb": {
                "type": "string",
                "maxLength": 100
              },
              "city": {
                "type": "string",
                "maxLength": 100
              },
              "district": {
                "type": "string",
                "maxLength": 100
              },
              "postcode": {
                "type": "string",
                "maxLength": 20
              },
              "region": {
                "type": "string",
                "maxLength": 100
              }
            }
          },
          "settings": {
            "type": "object",
            "properties": {
              "language": {
                "type": "string"
              },
              "matchLevel": {
                "type": "string",
                "enum": [
                  "EXACT",
                  "STANDARD",
                  "RELAXED"
                ],
                "default": "STANDARD",
                "description": "EXACT: tight, fewest candidates. RELAXED: loose, more multiple matches, slower."
              },
              "includeComponentDetail": {
                "type": "boolean",
                "default": true,
                "description": "false returns matchType only. Set false in high-volume flows that branch on matchScore alone."
              },
              "returnParsedInput": {
                "type": "boolean",
                "default": false,
                "description": "Diagnostics only. Do not use in production responses."
              }
            }
          }
        }
      },
      "ComponentMatch": {
        "type": "object",
        "required": [
          "value",
          "meaning"
        ],
        "properties": {
          "value": {
            "type": "integer",
            "enum": [
              0,
              3,
              4,
              6
            ],
            "description": "0 not found or empty; 3 verified and corrected; 4 verified without changes; 6 appended from reference data."
          },
          "meaning": {
            "type": "string",
            "enum": [
              "Not found or empty",
              "Verified and corrected",
              "Verified without changes",
              "Appended using reference data"
            ]
          }
        }
      },
      "VerifyResponse": {
        "type": "object",
        "required": [
          "result"
        ],
        "properties": {
          "result": {
            "type": "object",
            "required": [
              "status",
              "message",
              "meta",
              "matchScore",
              "deliverable",
              "address",
              "matchDetails"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "OK",
                  "ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "meta": {
                "type": "object",
                "required": [
                  "requestId"
                ],
                "properties": {
                  "requestId": {
                    "type": "string"
                  },
                  "referenceId": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "language": {
                    "type": "string"
                  },
                  "countryCode": {
                    "type": "string"
                  }
                },
                "additionalProperties": true
              },
              "matchScore": {
                "type": "integer",
                "minimum": 0,
                "maximum": 5,
                "description": "5 high confidence ... 0 no match. See x-agent-decision-rules. This is the signal to branch on."
              },
              "deliverable": {
                "type": "boolean",
                "description": "true: confirmed postal delivery point. false: cannot be confirmed deliverable."
              },
              "addressType": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "RESIDENTIAL",
                  "COMMERCIAL",
                  "INDUSTRIAL",
                  "PO_BOX",
                  "UNKNOWN",
                  null
                ],
                "description": "Present when a match is found. null where classification data is unavailable."
              },
              "address": {
                "type": "object",
                "required": [
                  "formatted",
                  "addressLines",
                  "components"
                ],
                "properties": {
                  "formatted": {
                    "type": "string"
                  },
                  "addressLines": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "components": {
                    "type": "object",
                    "description": "Empty string, never null, for components that do not apply.",
                    "properties": {
                      "houseNumber": {
                        "type": "string"
                      },
                      "thoroughfare": {
                        "type": "string"
                      },
                      "placeName": {
                        "type": "string"
                      },
                      "unitType": {
                        "type": "string"
                      },
                      "unit": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "suburb": {
                        "type": "string"
                      },
                      "district": {
                        "type": "string"
                      },
                      "postcode": {
                        "type": "string"
                      },
                      "postcodeExt": {
                        "type": "string"
                      },
                      "region": {
                        "type": "string"
                      },
                      "adminAreaCode": {
                        "type": "string",
                        "description": "ISO 3166-2 subdivision code, for example US-NY."
                      },
                      "countryCode": {
                        "type": "string"
                      }
                    }
                  },
                  "nationalId": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Future scope. Always null today."
                  }
                }
              },
              "matchDetails": {
                "type": "object",
                "required": [
                  "matchType"
                ],
                "properties": {
                  "matchType": {
                    "type": "string",
                    "enum": [
                      "ADDRESS",
                      "STREET",
                      "LOCALITY",
                      "POSTAL_CODE"
                    ],
                    "description": "How deep the match went: ADDRESS door level, STREET, LOCALITY city level, POSTAL_CODE area only."
                  },
                  "componentMatches": {
                    "type": "object",
                    "additionalProperties": {
                      "$ref": "#/components/schemas/ComponentMatch"
                    },
                    "description": "Per-component status. Empty when includeComponentDetail is false."
                  }
                }
              },
              "parsed": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "null unless returnParsedInput is true.",
                "items": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "GeocodeRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "object",
            "required": [
              "address",
              "countryCode"
            ],
            "description": "Same fields as verify. Structured parts you also supply take precedence over the same part parsed from address.",
            "properties": {
              "referenceId": {
                "type": "string",
                "maxLength": 100,
                "description": "Your own id. Echoed in result.meta.referenceId."
              },
              "address": {
                "type": "string",
                "maxLength": 500,
                "description": "Full address as one unparsed string."
              },
              "countryCode": {
                "$ref": "#/components/schemas/CountryCode"
              },
              "houseNumber": {
                "type": "string",
                "maxLength": 20
              },
              "thoroughfare": {
                "type": "string",
                "maxLength": 150
              },
              "placeName": {
                "type": "string",
                "maxLength": 100
              },
              "unitType": {
                "type": "string",
                "maxLength": 10
              },
              "unit": {
                "type": "string",
                "maxLength": 20
              },
              "suburb": {
                "type": "string",
                "maxLength": 100
              },
              "city": {
                "type": "string",
                "maxLength": 100
              },
              "district": {
                "type": "string",
                "maxLength": 100
              },
              "postcode": {
                "type": "string",
                "maxLength": 20
              },
              "region": {
                "type": "string",
                "maxLength": 100
              }
            }
          },
          "settings": {
            "type": "object",
            "properties": {
              "language": {
                "type": "string"
              },
              "matchLevel": {
                "type": "string",
                "enum": [
                  "EXACT",
                  "STANDARD",
                  "RELAXED"
                ],
                "default": "STANDARD",
                "description": "EXACT: fewest candidates. RELAXED: more candidates, useful for ambiguous input."
              },
              "searchType": {
                "type": "string",
                "enum": [
                  "ADDRESS",
                  "POSTAL",
                  "GEOGRAPHIC"
                ],
                "default": "ADDRESS",
                "description": "Target depth. ADDRESS: a delivery point. POSTAL: a postcode centroid. GEOGRAPHIC: a city or region centroid."
              },
              "maxCandidates": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10,
                "default": 1
              },
              "geohashPrecision": {
                "type": "integer",
                "minimum": 1,
                "maximum": 12,
                "default": 9,
                "description": "Length of coordinates.geohash. 5 is about 4.9 km2; 9 is about 0.6 m2."
              },
              "h3Resolution": {
                "type": "integer",
                "minimum": 0,
                "maximum": 15,
                "default": 9,
                "description": "Resolution of coordinates.h3Index. 6 is about 36 km2; 9 is about 0.1 km2."
              }
            }
          }
        }
      },
      "GeocodeCoordinates": {
        "type": "object",
        "description": "WGS 84 (EPSG:4326) only.",
        "required": [
          "latitude",
          "longitude"
        ],
        "properties": {
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "geohash": {
            "type": "string",
            "maxLength": 12
          },
          "h3Index": {
            "type": "string",
            "maxLength": 15
          },
          "locationType": {
            "type": "string",
            "enum": [
              "ADDRESS_POINT",
              "INTERSECTION",
              "ADDRESS_INTERPOLATED",
              "NEAR_BY_ADDRESS",
              "STREET",
              "POSTAL",
              "POSTAL_CENTROID",
              "TOWN_CENTROID",
              "CITY",
              "COUNTRY",
              "NO_LOCATION",
              "POI"
            ],
            "description": "How precise the point is. ADDRESS_POINT is the most precise; POSTAL_CENTROID, TOWN_CENTROID, CITY and COUNTRY are centroids, not an address."
          },
          "locationDescription": {
            "type": "string",
            "enum": [
              "POSTAL_BUILDING",
              "BUILDING",
              "FRONT_DOOR",
              "DRIVEWAY",
              "PARCEL",
              "POINT_OF_INTEREST",
              "STREET_BLOCK",
              "POSTAL_CODE"
            ],
            "description": "Where the point sits in relation to the address."
          }
        }
      },
      "GeocodeCandidate": {
        "type": "object",
        "required": [
          "matchScore",
          "address",
          "coordinates"
        ],
        "properties": {
          "matchScore": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5,
            "description": "Same 0 to 5 scale as verify."
          },
          "matchPrecision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Finer score. Bands: score 5 is 85 to 100, 4 is 65 to 84, 3 is 45 to 64, 2 is 25 to 44, 1 is 1 to 24, 0 is 0."
          },
          "address": {
            "type": "object",
            "required": [
              "formatted",
              "addressLines",
              "components"
            ],
            "properties": {
              "formatted": {
                "type": "string"
              },
              "addressLines": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "components": {
                "type": "object",
                "description": "Same fields as the verify address components. Empty string, never null.",
                "properties": {
                  "houseNumber": {
                    "type": "string"
                  },
                  "thoroughfare": {
                    "type": "string"
                  },
                  "placeName": {
                    "type": "string"
                  },
                  "unitType": {
                    "type": "string"
                  },
                  "unit": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "suburb": {
                    "type": "string"
                  },
                  "district": {
                    "type": "string"
                  },
                  "postcode": {
                    "type": "string"
                  },
                  "postcodeExt": {
                    "type": "string"
                  },
                  "region": {
                    "type": "string"
                  },
                  "adminAreaCode": {
                    "type": "string"
                  },
                  "countryCode": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "coordinates": {
            "$ref": "#/components/schemas/GeocodeCoordinates"
          },
          "matchDetails": {
            "type": "object",
            "required": [
              "matchType"
            ],
            "properties": {
              "matchType": {
                "type": "string",
                "enum": [
                  "ADDRESS",
                  "STREET",
                  "LOCALITY",
                  "POSTAL_CODE"
                ]
              },
              "componentMatches": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/ComponentMatch"
                }
              }
            }
          }
        }
      },
      "GeocodeResponse": {
        "type": "object",
        "required": [
          "result"
        ],
        "properties": {
          "result": {
            "type": "object",
            "required": [
              "status",
              "candidates"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "OK",
                  "ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "requestId": {
                    "type": "string"
                  },
                  "referenceId": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "language": {
                    "type": "string"
                  },
                  "countryCode": {
                    "type": "string"
                  }
                },
                "additionalProperties": true
              },
              "candidates": {
                "type": "array",
                "maxItems": 10,
                "description": "Ordered by matchScore, highest first. Empty when there is no match.",
                "items": {
                  "$ref": "#/components/schemas/GeocodeCandidate"
                }
              }
            }
          }
        }
      },
      "ReverseGeocodeRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "object",
            "required": [
              "latitude",
              "longitude"
            ],
            "properties": {
              "referenceId": {
                "type": "string",
                "maxLength": 100,
                "description": "Your own id. Echoed in result.meta.referenceId."
              },
              "latitude": {
                "type": "number",
                "minimum": -90,
                "maximum": 90,
                "description": "Decimal degrees, WGS 84."
              },
              "longitude": {
                "type": "number",
                "minimum": -180,
                "maximum": 180,
                "description": "Decimal degrees, WGS 84."
              },
              "countryCode": {
                "type": "string",
                "minLength": 3,
                "maxLength": 3,
                "pattern": "^[A-Za-z]{3}$",
                "description": "Optional. Constrains the search to that country and helps near borders. When omitted, the country is resolved from the coordinates."
              }
            }
          },
          "settings": {
            "type": "object",
            "properties": {
              "searchRadius": {
                "type": "object",
                "required": [
                  "value",
                  "unit"
                ],
                "description": "Default 150 METER.",
                "properties": {
                  "value": {
                    "type": "number"
                  },
                  "unit": {
                    "type": "string",
                    "enum": [
                      "METER",
                      "KILOMETER",
                      "FOOT",
                      "MILE"
                    ]
                  }
                }
              },
              "maxCandidates": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5,
                "default": 1
              },
              "language": {
                "type": "string"
              }
            }
          }
        }
      },
      "ReverseGeocodeCandidate": {
        "type": "object",
        "required": [
          "address",
          "coordinates"
        ],
        "description": "The documentation says the response uses the same envelope and matchDetails as forward geocode but does not list matchScore for reverse geocode, so only address and coordinates are treated as always present.",
        "properties": {
          "matchScore": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5
          },
          "matchPrecision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "address": {
            "type": "object",
            "required": [
              "formatted",
              "addressLines",
              "components"
            ],
            "properties": {
              "formatted": {
                "type": "string"
              },
              "addressLines": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "components": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Same fields as the verify address components."
              }
            }
          },
          "coordinates": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GeocodeCoordinates"
              },
              {
                "type": "object",
                "properties": {
                  "designation": {
                    "type": "string",
                    "enum": [
                      "ROOFTOP",
                      "CENTROID",
                      "RANGE_INTERPOLATED",
                      "GEOMETRIC_CENTER",
                      "APPROXIMATE"
                    ],
                    "description": "Placement of the matched point relative to the address footprint."
                  },
                  "distanceMeters": {
                    "type": "number",
                    "description": "Metres between your submitted point and the matched address point."
                  }
                }
              }
            ]
          },
          "matchDetails": {
            "type": "object",
            "properties": {
              "matchType": {
                "type": "string"
              },
              "componentMatches": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/ComponentMatch"
                }
              }
            }
          }
        }
      },
      "ReverseGeocodeResponse": {
        "type": "object",
        "required": [
          "result"
        ],
        "properties": {
          "result": {
            "type": "object",
            "required": [
              "status",
              "candidates"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "OK",
                  "ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "meta": {
                "type": "object",
                "additionalProperties": true
              },
              "candidates": {
                "type": "array",
                "maxItems": 5,
                "items": {
                  "$ref": "#/components/schemas/ReverseGeocodeCandidate"
                }
              }
            }
          }
        }
      },
      "ErrorCode": {
        "type": "string",
        "enum": [
          "INVALID_REQUEST",
          "INVALID_COORDINATES",
          "MISSING_REQUIRED_FIELD",
          "INVALID_PARAMETER",
          "INVALID_COUNTRY",
          "UNSUPPORTED_COUNTRY",
          "MISSING_SESSION_TOKEN",
          "MISSING_CREDENTIALS",
          "INVALID_CREDENTIALS",
          "FORBIDDEN",
          "SUBSCRIPTION_INACTIVE",
          "UNSUPPORTED_MEDIA_TYPE",
          "RATE_LIMIT_EXCEEDED",
          "INTERNAL_ERROR",
          "SERVICE_UNAVAILABLE"
        ]
      },
      "Error": {
        "type": "object",
        "description": "Every error, from every endpoint, has this envelope. The request id is in the X-Request-Id response header, not the body.",
        "required": [
          "result"
        ],
        "properties": {
          "result": {
            "type": "object",
            "required": [
              "status",
              "message",
              "errorCode"
            ],
            "properties": {
              "status": {
                "type": "string",
                "const": "ERROR"
              },
              "message": {
                "type": "string",
                "description": "For logs. Do not show it raw to end users."
              },
              "errorCode": {
                "$ref": "#/components/schemas/ErrorCode"
              },
              "docsUrl": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request is wrong. Fix it; do not retry unchanged. Codes: INVALID_REQUEST, INVALID_COORDINATES (reverse geocode), MISSING_REQUIRED_FIELD, INVALID_PARAMETER, INVALID_COUNTRY, UNSUPPORTED_COUNTRY, MISSING_SESSION_TOKEN.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missing": {
                "value": {
                  "result": {
                    "status": "ERROR",
                    "message": "query.countryCode is required.",
                    "errorCode": "MISSING_REQUIRED_FIELD",
                    "docsUrl": "https://addrexy.com/errors/MISSING_REQUIRED_FIELD"
                  }
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid credentials. Codes: MISSING_CREDENTIALS, INVALID_CREDENTIALS. Do not retry.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "invalid": {
                "value": {
                  "result": {
                    "status": "ERROR",
                    "message": "The API key and secret are not recognised.",
                    "errorCode": "INVALID_CREDENTIALS",
                    "docsUrl": "https://addrexy.com/errors/INVALID_CREDENTIALS"
                  }
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Credentials are valid but not allowed. Codes: FORBIDDEN (key lacks the scope for this API), SUBSCRIPTION_INACTIVE (the subscription is expired or suspended). Stop and tell your human.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Content-Type is missing or not application/json. A charset suffix is accepted.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit reached for the key. Wait `Retry-After` seconds, then retry once. Do not retry immediately.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected server failure. Retry with exponential backoff (1 s, 2 s, 4 s). After 3 failures stop and report, quoting X-Request-Id.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Maintenance or incident. Wait `Retry-After` seconds before retrying.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
