WattleAddr API
Add Australian address autocomplete, verification and geocoding to any application. Base URL https://api.wattleaddr.com.au/v1. JSON only. Australian addresses only.
Quickstart
Grab a secret key from the console, then make your first call. This works as-is once you paste your key in:
curl -s -H "Authorization: Bearer waddr_sk_live_…" \
"https://api.wattleaddr.com.au/v1/addresses/autocomplete?q=1+martin+pl"
# 2. retrieve the one they picked (this is the billable lookup)
curl -s -H "Authorization: Bearer waddr_sk_live_…" \
"https://api.wattleaddr.com.au/v1/addresses/GANSW706124693"
Or drop in the browser widget
One script tag, no build step, no dependencies. Use a publishable key (waddr_pk_…) locked to your domains in the console. It handles session tokens for you, so all the keystrokes behind one address count as a single billable lookup.
<script src="https://api.wattleaddr.com.au/v1/widget.js"></script>
<script>
const wa = new WattleAddr('waddr_pk_live_…');
wa.attach('#address', {
onSelect: (a) => console.log(a.formatted, a.components, a.geo)
});
</script>
| Option | Default | What it does |
|---|---|---|
onSelect | required | Called with the full record once someone picks an address. |
onError | console warning | Called instead of logging, if you want to handle failures yourself. |
theme | light | light, dark, or auto to follow the visitor’s system setting. |
limit | 6 | How many suggestions to show. |
state | all | Restrict to one state, for example NSW. |
Or install the SDK from npm
Official, typed, MIT-licensed packages. Use @wattleaddr/react for React, or the zero-dependency @wattleaddr/js for vanilla JavaScript or server-side Node.
npm install @wattleaddr/react
# Vanilla JS / Node: headless client + the same drop-in widget
npm install @wattleaddr/js
The React component drops into any form. Use a publishable key:
<AddressAutocomplete
apiKey="waddr_pk_live_…"
onSelect={(a) => console.log(a.formatted, a.components.postcode)}
/>
Or call it headlessly with the client — it runs in the browser and in Node 18+. On the server, set keyTransport: 'header' to send a secret key as a Bearer token instead of in the URL:
const client = new WattleAddrClient('waddr_sk_live_…', { keyTransport: 'header' });
const session = createSession();
const { suggestions } = await client.autocomplete('1 mart', { session });
const addr = await client.retrieve(suggestions[0].id, { session }); // the billable call
Building with a coding agent
If you use Claude Code, Cursor, Copilot or similar, give it our agent skill. It covers the things an assistant otherwise gets wrong — session tokens and what they cost, which key belongs in the browser, PO Boxes being absent from G-NAF by design, reading a verify verdict, and how to store the address components. It is a single markdown file with no telemetry.
curl -o WATTLEADDR.md https://wattleaddr.com.au/skills/wattleaddr/SKILL.md
# Claude Code: drop it in as a skill
mkdir -p .claude/skills/wattleaddr && curl -o .claude/skills/wattleaddr/SKILL.md \
https://wattleaddr.com.au/skills/wattleaddr/SKILL.md
It also ships inside @wattleaddr/js, at node_modules/@wattleaddr/js/skills/wattleaddr/SKILL.md, so an agent working in a project that already depends on the SDK can find it without downloading anything.
Authentication
Two key types, both created in the console. Never expose a secret key in the browser.
| Key | Prefix | Where | Secured by |
|---|---|---|---|
| Secret | waddr_sk_live_… | Server-side | Authorization: Bearer + optional IP allowlist |
| Publishable | waddr_pk_live_… | Browser | Allowed referrer domains + rate limits |
That is how your application authenticates. How your team signs in to the console is separate: on Enterprise plans you can point it at your own identity provider over OpenID Connect, and require it. See single sign-on setup.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /v1/addresses/autocomplete | Type-ahead suggestions for a partial query |
GET | /v1/addresses/{id} | Full structured record for a chosen suggestion (billable) |
POST | /v1/addresses/verify | Match free-text to the best canonical address, with a per-field verdict (billable on a match) |
GET | /v1/status | Service health & current G-NAF release |
Example: autocomplete
-H "Authorization: Bearer waddr_sk_live_…"
"suggestions": [
{ "id": "GANSW706124693", "formatted": "1 Martin Place, Sydney NSW 2000" }
]
}
Example: verify, and what a verdict means
verify takes free text you already hold and returns the best canonical match plus an assessment of how well it answers what you sent. Branch on verdict.
-H "Authorization: Bearer waddr_sk_live_…" \
-H "Content-Type: application/json" \
-d '{"address": "100 collins st melbourne", "session": "abc"}'
"matched": true,
"match": { /* the full canonical record */ },
"verdict": "corrected",
"match_score": 75,
"match_level": "premise",
"elements": { "street_number": "verified", …, "postcode": "missing" },
"changed_elements": []
}
verdict | Meaning | Handling |
|---|---|---|
verified | Every element you supplied agrees, and no other candidate fits | Accept |
corrected | Agrees as far as it goes — you abbreviated or left something out | Accept the canonical form, or re-prompt for the missing elements |
ambiguous | An element was contradicted, input was discarded, or a runner-up fits equally well | Review — never auto-accept |
unverified | Nothing matched, or the match scored too low to rely on | Reject and flag |
elements gives every field its own status — verified, changed or missing — so a checkout can re-prompt for the one field that is wrong instead of the whole address. match_level says how precisely we identified it (subpremise → premise → thoroughfare → locality) and is independent of the verdict. We publish no accept/reject score threshold: the right line depends on what a wrong address costs you, and a single number cannot say “we matched a building on a street whose suburb you contradicted”. The older top-level confidence field is deprecated — it is still returned, but it was a constant on any match before August 2026, so branch on verdict instead. This tells you an address exists in G-NAF and where it is — not that mail can be delivered to it.
PO Boxes & postal addresses
G-NAF is a register of physical addresses, so it contains no PO Boxes, GPO Boxes, Locked Bags or Private Bags. Rather than returning a confusing empty list, a query for one returns 200 with an empty suggestions array and a notice, so your form can prompt for a street address or accept the PO Box in a separate field. verify returns the same notice with matched: false and billed: false — a query the dataset cannot answer is never charged.
"code": "postal_address_unsupported",
"kind": "PO Box",
"message": "PO Box addresses aren’t in the G-NAF dataset…"
} }
Rate limits & billing
Billing is session-based, the same model as Google Places: send a session token with each autocomplete keystroke and the final retrieve, and the whole session counts as one billable lookup — however many keystrokes it took. Autocomplete on its own is never billed. Retrieve or verify with no session token always bills, so always send one.
Every response carries X-WattleAddr-Quota-Limit and X-WattleAddr-Quota-Remaining. Exhausting a plan’s monthly quota returns 402 quota_exceeded; a per-key burst limit returns 429 rate_limited with a Retry-After header. Error and notice codes are stable and safe to switch on — the full list is in the reference.
Data & privacy
Every request is served from Australian infrastructure — no query or matched address is processed, cached or routed offshore, and your end-users’ input never touches a third-party ad platform such as Google Places.
Autocomplete queries and the addresses they match are recorded in a per-workspace search log for usage, debugging and support. In the console you choose what it keeps:
| Mode | What it stores |
|---|---|
full (default) | Query and matched-address text, in full, until retention purges it. |
hashed | Each query as a salted keyed hash; matched-address text is dropped. This is pseudonymisation — we hold the key, so it is not anonymisation. |
none | No query or matched-address text at all — only counts, timing and billing. |
Retention is configurable (7–365 days, by plan) and old query text is purged automatically; you can also apply a privacy mode to logs already stored, in one click. See the FAQ and Privacy Policy for detail.
Attribution
WattleAddr is built on the open Geocoded National Address File. The G-NAF licence requires attribution. Display this wherever you surface address data:
licensed under the Open G-NAF End User Licence Agreement.
Explore every endpoint and try calls live in the interactive reference. Questions? hello@wattleaddr.com.au