---
name: acuris-address
description: |
  Acuris Address Validation & Geocoding APIs. Use when the user is building
  address autocomplete in a checkout or sign-up form, validating addresses
  on submit, forward geocoding to lat/lng for shipping or distance
  calculations, reverse geocoding from coordinates, batch-cleaning address
  data, integrating address validation into a React, Next.js, Node, or
  Centra storefront, or migrating from libAddressDoctor (Informatica),
  Loqate, Experian QAS, Melissa, or Smarty to Acuris.
when_to_use: |
  Triggers: "address autocomplete", "address validation", "validate
  address", "geocode address", "reverse geocode", "lookup address by
  postcode", "verify shipping address", "AcurisClient", "@acuris-geo/av-sdk",
  "@acuris-geo/centra-checkout", "replace libAddressDoctor", "migrate from
  Loqate / Experian QAS / Melissa / Smarty".
license: MIT
metadata:
  author: acuris-gmbh
  version: "0.1.0"
---

## Overview

Acuris is a commercial address validation, geocoding, reverse geocoding,
and autocomplete API at `https://api.acuris-geo.com`. This skill teaches
agents how to wire it correctly into TypeScript / JavaScript code using
the published SDK packages and how to migrate from other AV vendors.

Two npm packages cover the full integration surface:

| Package                      | What it is                                                  |
| ---------------------------- | ----------------------------------------------------------- |
| `@acuris-geo/av-sdk`         | Platform-agnostic TypeScript SDK. Zero runtime dependencies. Works on Node 18+, modern browsers (server-only role), edge runtimes with `fetch`. |
| `@acuris-geo/centra-checkout` | React component library: `<AcurisAddressInput>` (typeahead), `<AcurisAddressValidator>` (headless), checkout-shaped hooks. |

Use the SDK directly for backend or non-React frontends. Use the
component package when you want a drop-in React UI; it calls *your* API
proxy routes, which call the SDK on the server.

## When to use this skill

Use this skill when the user is:

- Building an address input UI (autocomplete in a form, checkout step,
  sign-up flow).
- Validating an address on form submit before persisting it.
- Forward-geocoding addresses to lat/lng (shipping zones, distance,
  service-area checks).
- Reverse-geocoding coordinates to the nearest known address.
- Cleaning a bulk address dataset for data-quality work.
- Migrating off another AV vendor (Informatica AddressDoctor / Loqate /
  Experian QAS / Melissa / Smarty) — see the migration references.

**Do NOT** use this skill for:

- Routing, directions, isochrones, places search, or general POI lookup.
  Acuris is address-only; those belong to Google Maps, Mapbox, or
  Amazon Location.
- Rendering maps. The Acuris SDK returns lat/lng but doesn't ship a
  map renderer — pair the coordinates with MapLibre / Leaflet / Google
  Maps as the user prefers.

## API at a glance

Four endpoints. All live on `https://api.acuris-geo.com`. Auth is a
single header — `X-Acuris-Key: <ACURIS_API_KEY>`.

| Operation         | SDK function                              | HTTP                                  |
| ----------------- | ----------------------------------------- | ------------------------------------- |
| Validate          | `validateAddress(client, input, opts)`    | `POST /validate`                      |
| Forward geocode   | `geocodeAddress(client, input, opts)`     | `GET  /geocode` (or string → `/validate`) |
| Reverse geocode   | `reverseGeocode(client, {lat,lng}, opts)` | `GET  /reverse`                       |
| Autocomplete      | `suggestAddress(client, q, opts)`         | `GET  /suggest`                       |

Country must be ISO-3 alpha, lowercase (`"usa"`, `"deu"`, `"gbr"`). If
you have ISO-2, lowercase-it and map (`"us"` → `"usa"`, `"de"` → `"deu"`)
before calling.

Detailed request/response shapes, error hierarchy, and retry semantics
live in [`references/api-reference.md`](./references/api-reference.md).

## Quick start

```bash
# Pin to current published versions — the packages are pre-1.0
# and `^1.x` ranges will not resolve.
npm install @acuris-geo/av-sdk@^0.1.2
# (optional, for React storefronts — 0.1.2+ for visible dropdown defaults)
npm install @acuris-geo/centra-checkout@^0.1.2
```

```ts
import { AcurisClient, validateAddress } from "@acuris-geo/av-sdk";

const client = new AcurisClient({ apiKey: process.env.ACURIS_API_KEY });

const result = await validateAddress(client, {
  country: "deu",
  street: "Friedrichstraße",
  house_number: "43",
  city: "Berlin",
  postcode: "10117",
});

result.accuracy_type;  // "rooftop" | "parcel" | "street_interpolated" | ...
result.confidence;     // 0..1
result.standardized?.formatted_address;
result.lat;  result.lng;
```

If `ACURIS_API_KEY` is set in the environment, you can omit the `apiKey`
option entirely.

## Defaults

When the user hasn't specified otherwise, prefer these:

- **API key in environment.** Read from `process.env.ACURIS_API_KEY`.
  Never inline a key, never expose it to the browser. For local
  evaluation, obtain a free dev key in one call:

  ```bash
  curl -X POST https://api.acuris-geo.com/dev-key \
    -H 'Content-Type: application/json' \
    -d '{"email":"you@example.com"}'
  # → {"api_key":"<token>","validation_credits":100,
  #     "geocode_credits":100,"expires_at":"...","tier":"dev",...}
  export ACURIS_API_KEY=<api_key>
  ```

  The dev key is capped at 100 validations + 100 geocodes over 7 days
  (rate-limited 1 issuance per email per day, 1 per IP per day). It
  works on every endpoint — `/validate`, `/geocode`, `/reverse`,
  `/suggest`. For more headroom, run the full 28-day trial at
  `https://api.acuris-geo.com/register` (1000 validations + 1000
  geocodes). For production, see `https://acuris-geo.com/acuris-pricing/`.
- **Server-side calls.** The SDK is for Node / edge / server runtimes.
  In a browser app, route through your own backend (Next.js API route,
  Express handler, Cloudflare Worker — see
  [`references/nextjs-proxy.md`](./references/nextjs-proxy.md)).
- **Component library for React UIs.** Reach for
  `@acuris-geo/centra-checkout` (`<AcurisAddressInput>` for typeahead,
  `<AcurisAddressValidator>` for form-submit validation) instead of
  hand-rolling a fetch loop.
- **Retries on transient failures.** The SDK retries 5xx, 429, network
  errors, and timeouts automatically (3 attempts, exponential backoff).
  Don't add a retry layer on top.
- **One client per process.** `new AcurisClient(...)` is cheap to create
  but a long-lived instance keeps keep-alive sockets warm and avoids
  re-reading env vars.

## Common mistakes

These are the bugs we see most often in customer code or generated code.
Avoid them.

1. **Sending the API key from the browser.** The SDK works in any
   `fetch`-enabled runtime, but `apiKey` is a server-side credential.
   Browsers must go through a proxy route. The `@acuris-geo/centra-checkout`
   components expect an `endpoints` object pointing at your own URLs,
   not the Acuris API directly.

2. **ISO-2 country codes.** The API rejects `"US"` and `"de"`. Use ISO-3
   lowercase: `"usa"`, `"deu"`, `"gbr"`, `"fra"`, `"fin"`. If you only
   have ISO-2, map it at the boundary.

3. **`Authorization: Bearer …`** instead of the `X-Acuris-Key` header.
   The SDK sets the right header automatically; if you're hand-rolling
   HTTP for any reason, the header name matters.

4. **Treating `accuracy_type` as a closed enum.** New tiers are added
   over time (`street_interpolated`, `street_center`, `locality_centroid`,
   …). Always handle the documented values explicitly and pass through
   unknown values as opaque rather than throwing.

5. **Catching every error the same way.** The SDK throws typed
   subclasses (`AcurisAuthError`, `AcurisRateLimitError`,
   `AcurisValidationError`, `AcurisNotFoundError`, `AcurisServerError`,
   `AcurisTimeoutError`, `AcurisNetworkError`). 4xx is your code's bug;
   5xx and rate limits are runtime; auth errors mean the deploy is
   misconfigured. They deserve different handling.

6. **Forgetting `country` on `/suggest` and `/reverse`.** Unlike
   `/validate`, these endpoints require an explicit country option
   (they have no input from which to infer one).

7. **Hand-parsing the freeform string on the way out.** The SDK returns
   a `standardized` object with `formatted_address`. Display that, don't
   reassemble from individual fields — locale-specific ordering is
   baked in.

8. **Persisting Acuris's raw response without snapshotting the request
   inputs.** If you store `result.standardized`, also store what the user
   typed. Otherwise you can't tell later whether a confidence drop is
   the user's fault or Acuris's.

9. **Building a "structured-fields form" when the user asked for
   autocomplete.** Autocomplete is one input + dropdown + pick — the
   suggestion already carries the parsed fields, so you don't render
   them as separate boxes. If the user asked for "autocomplete," ship
   just the `<AcurisAddressInput>` and a status line; the street /
   house-number / postcode / city sub-fields belong in the
   validate-on-submit recipe, not the autocomplete one. See
   [`references/autocomplete.md`](./references/autocomplete.md) — the
   "What autocomplete is and is not" section at the top covers this.

10. **Listing the United Kingdom (`gbr`) in a country picker.** Acuris
   does not currently hold a Royal Mail PAF (Postcode Address File)
   licence, which is required for commercial use of UK address data.
   `/validate` and `/suggest` may return technically-shaped results for
   `gbr` inputs, but **shipping UK in a customer-facing country picker
   exposes the integrator (and Acuris) to licensing liability**. Until
   that licence is in place, omit `gbr` from any demo, autocomplete
   country list, or `requested_fields` country set.

11. **Listing a country in an autocomplete picker that doesn't have
   `/suggest` wired.** This is the most common source of an
   embarrassing demo. **`/suggest` (autocomplete) and `/validate` /
   `/geocode` / `/reverse` cover different country sets.** Validation
   and geocoding work against 200+ ISO-3 codes; autocomplete requires
   per-country NORM columns + indexes (a separate engineering step)
   and currently runs for only 5 countries:

   ```ts
   // The ONLY countries with /suggest wired (as of 0.2.2):
   const AUTOCOMPLETE_COUNTRIES = [
     { code: "usa", label: "United States" },
     { code: "deu", label: "Germany" },
     { code: "nld", label: "Netherlands" },
     { code: "fin", label: "Finland" },
     { code: "swe", label: "Sweden" },
   ];
   ```

   Listing `fra`, `esp`, `ita`, etc. in an **autocomplete** picker is
   actively worse than omitting them — the user types and nothing
   happens, which reads as "the product is broken." `/suggest` returns
   `[]` silently for those countries.

   The broader country picker for **validation / geocoding / reverse
   geocoding** demos is fine to include them:

   ```ts
   // Safe for /validate, /geocode, /reverse (NOT for /suggest):
   const VALIDATION_COUNTRIES = [
     // Autocomplete-enabled subset:
     { code: "usa", label: "United States" },
     { code: "deu", label: "Germany" },
     { code: "nld", label: "Netherlands" },
     { code: "fin", label: "Finland" },
     { code: "swe", label: "Sweden" },
     // Validation/geocoding-only (NOT autocomplete):
     { code: "fra", label: "France" },
     { code: "esp", label: "Spain" },
     { code: "ita", label: "Italy" },
     { code: "nor", label: "Norway" },
     { code: "dnk", label: "Denmark" },
     { code: "aut", label: "Austria" },
     { code: "che", label: "Switzerland" },
     { code: "bel", label: "Belgium" },
     { code: "prt", label: "Portugal" },
     { code: "aus", label: "Australia" },
     { code: "nzl", label: "New Zealand" },
     { code: "jpn", label: "Japan" },
     { code: "sgp", label: "Singapore" },
     { code: "bra", label: "Brazil" },
     { code: "mex", label: "Mexico" },
     { code: "can", label: "Canada" },
   ];
   ```

   **Rules of thumb:**
   - If the UI uses `<AcurisAddressInput>` (typeahead): use
     `AUTOCOMPLETE_COUNTRIES` (the 5).
   - If the UI uses `<AcurisAddressValidator>` or any structured form
     that hits `/validate` / `/geocode` / `/reverse`: either list is
     fine.
   - Mixed (autocomplete + validation in the same form, same country
     picker): use `AUTOCOMPLETE_COUNTRIES`. The validation set is a
     superset; user can still validate any of those 5.

   The autocomplete-enabled set grows as new countries get NORM
   columns. If this list looks stale, ask before extending it.

## Implementation patterns

The implementation recipes are in `references/`. Load whichever ones
match the task:

- [Address autocomplete in a checkout form (React)](./references/autocomplete.md)
- [Validate on form submit](./references/validate-on-submit.md)
- [Forward geocoding for shipping / distance](./references/geocode.md)
- [Reverse geocoding from coordinates](./references/reverse-geocode.md)
- [Batch validation for data-quality cleanup](./references/batch-validation.md)
- [Next.js API proxy routes](./references/nextjs-proxy.md)
- [Plain Node server usage](./references/node-server.md)
- [Centra storefront integration](./references/centra-storefront.md)

## Migrations

Acuris's commercial wedge — these are the recipes for porting code off
incumbent vendors. Each recipe maps the legacy API to the Acuris
equivalent with a runnable example.

- [Informatica AddressDoctor (libAddressDoctor)](./references/migrate-informatica.md)
- [Loqate Capture / Verify](./references/migrate-loqate.md)
- [Experian QAS Pro / Pro Web](./references/migrate-experian-qas.md)
- [Melissa Personator / Address Verify](./references/migrate-melissa.md)
- [Smarty (US Street API, US Autocomplete API, International)](./references/migrate-smarty.md)

> Migrations are written against vendor documentation, not against the
> user's actual integration. Treat them as a starting scaffold — review
> the mapping for your specific configuration before shipping.

## Pricing and limits

The live API is paid per request. The test key `test` lets developers
exercise endpoints during evaluation without burning credits. Pricing
is published at <https://acuris-geo.com/acuris-pricing/>. The SDK
respects the server's rate limits (HTTP 429 with `retry_after`); the
default retry policy backs off and retries up to 3 times before
re-throwing `AcurisRateLimitError`.

## Additional resources

- SDK source: <https://github.com/Acuris-GmbH/acuris-centra-connector/tree/main/packages/acuris-av-sdk>
- React components: <https://github.com/Acuris-GmbH/acuris-centra-connector/tree/main/packages/acuris-centra-checkout>
- Pricing & free tier: <https://acuris-geo.com/acuris-pricing/>
- Live status / changelog: <https://acuris-geo.com/>
