@wherabouts/sdk
v0.4.3
Published
Official TypeScript SDK for the Wherabouts location API — Australian geocoding, geofencing zones, device tracking, and webhooks over authoritative G-NAF/ABS data.
Downloads
615
Maintainers
Readme
@wherabouts/sdk
Official TypeScript SDK for the Wherabouts location API — Australian geocoding, geofencing zones, device tracking, and webhooks over authoritative G‑NAF / ABS data.
- Dependency-free and runtime-agnostic (Node, edge, browser) — built on
fetch. - Fully typed, resource-namespaced surface (
client.zones.create(...)). - Resilient by default: automatic retries with backoff, per-request timeouts,
AbortSignalsupport, and idempotent writes.
Interactive API Explorer → (Paste the URL into Swagger UI or Hoppscotch to explore all endpoints interactively.)
Install
npm install @wherabouts/sdk
# or: pnpm add @wherabouts/sdk · yarn add @wherabouts/sdkRequires Node.js 18+ (or any runtime with a global fetch).
Quickstart (60 seconds)
import { createWheraboutsClient } from "@wherabouts/sdk";
const client = createWheraboutsClient({
apiKey: process.env.WHERABOUTS_API_KEY!,
});
// Classify a coordinate into official ABS/ASGS regions
const regions = await client.regions.classify({
lat: -37.8136,
lng: 144.9631,
});
// Autocomplete an address
const { results } = await client.addresses.autocomplete({ q: "123 collins st" });
// Create a geofence zone
const zone = await client.zones.create({
name: "Melbourne CBD depot",
geometry: {
type: "Polygon",
coordinates: [
[
[144.95, -37.82],
[144.97, -37.82],
[144.97, -37.8],
[144.95, -37.8],
[144.95, -37.82],
],
],
},
});Resources
| Namespace | Methods |
|---|---|
| client.addresses | autocomplete, getById, nearby, reverse |
| client.geocode | forward, batch.submit, batch.poll, batch.results |
| client.zones | create, list, get, update, delete, contains, addresses |
| client.devices | pushLocation, zones |
| client.webhooks | create, list, delete, reactivate |
| client.regions | classify |
Configuration
const client = createWheraboutsClient({
apiKey: "wh_...", // required
baseUrl: "https://api.wherabouts.com", // optional override
maxRetries: 2, // optional, default 2
timeoutMs: 30_000, // optional, default 30s
fetch: customFetch, // optional fetch implementation
headers: { "x-app": "..." } // optional default headers
});| Option | Default | Description |
|---|---|---|
| apiKey | — | Your Wherabouts API key (wh_...). Required. |
| baseUrl | https://api.wherabouts.com | API origin override. |
| maxRetries | 2 | Automatic retries for transient failures (429/5xx/network/timeout). |
| timeoutMs | 30000 | Per-request timeout. |
| fetch | globalThis.fetch | Custom fetch implementation. |
| headers | — | Default headers added to every request. |
Per-request options
Every method accepts an optional trailing options argument to override the client
defaults for a single call:
await client.addresses.autocomplete(
{ q: "123 collins st" },
{ timeoutMs: 5000, signal: AbortSignal.timeout(5000) }
);
// Writes auto-attach an Idempotency-Key; supply your own to dedupe explicitly:
await client.zones.create(zoneBody, { idempotencyKey: "order-42" });Resilience
- Retries transient failures (HTTP
408/425/429/500/502/503/504, network errors, and timeouts) up tomaxRetries, using exponential backoff with full jitter (200 ms base, 5 s cap). ARetry-Afterresponse header is honoured when present. - Idempotent writes:
POST/PUTcalls automatically send anIdempotency-Keyheader so retries are safe. Passoptions.idempotencyKeyto control it. - Timeouts & cancellation: each request times out after
timeoutMs; passoptions.signalto cancel a call yourself.
Error handling
Failed requests reject with a WheraboutsApiError:
import { WheraboutsApiError } from "@wherabouts/sdk";
try {
await client.zones.get(999);
} catch (err) {
if (err instanceof WheraboutsApiError) {
err.status; // HTTP status (e.g. 404)
err.code; // machine code (e.g. "not_found")
err.message; // human-readable message
err.requestId; // correlation id for support, if provided
err.docUrl; // link to error docs, if provided
err.fields; // field-level validation detail, if provided
}
}Rate Limits
| Plan | Requests / minute | Requests / month | |------------|-------------------|-----------------| | Free | 60 | 10,000 | | Starter | 300 | 100,000 | | Pro | 1,000 | 1,000,000 | | Enterprise | Custom | Custom |
When you exceed the rate limit, the API returns 429 Too Many Requests with error code rate_limited. The Retry-After response header contains the number of seconds to wait.
import { WheraboutsApiError } from "@wherabouts/sdk";
try {
const result = await client.geocode.forward({ q: "Sydney Opera House" });
} catch (e) {
if (e instanceof WheraboutsApiError && e.code === "rate_limited") {
const retryAfter = e.response?.headers.get("retry-after");
console.log(`Rate limited. Retry after ${retryAfter}s`);
}
}Migrating from Google Places API
| Google Places | Wherabouts equivalent |
|--------------------------------------------------|-----------------------------------------------------|
| PlacesService.findPlaceFromQuery() | client.geocode.forward({ q }) |
| AutocompleteService.getPlacePredictions() | client.addresses.autocomplete({ q }) |
| Geocoder.geocode({ location }) | client.addresses.reverse({ lat, lng }) |
| places.nearbySearch() | client.addresses.nearby({ lat, lng, radius }) |
Key differences:
- Authoritative data: Wherabouts uses G-NAF — Australia's official address register maintained by PSMA Australia. Addresses match what Australia Post, ABS, and government systems use.
- Structured components: Every address includes
streetNumber,streetName,streetType,locality,state,postcodeas first-class fields — no parsing needed. - No session tokens: Autocomplete billing is per-call. No session token complexity.
- Unique identifiers: Each address has a
gnafPid(G-NAF Persistent Identifier) andidfor stable cross-system referencing.
License
UNLICENSED — © Wherabouts. Contact the maintainers for usage terms.
