> ## Documentation Index
> Fetch the complete documentation index at: https://docs.postcode.gov.ng/llms.txt
> Use this file to discover all available pages before exploring further.

# Postcode Widget

> Drop-in widget that lets your users pick their postcode from bookmarks or search.

The Postcode Widget is an embeddable flow your app opens when it needs a postcode
from a user. It identifies the user by **NIN or email** (typed by the user or
pre-filled by your app), shows their **bookmarked postcodes**, offers a full
**search/discover** experience, and hands the final selection back to your app.

## How it works

1. Your app opens the widget with your **publishable key** (`nipost_pk_…`) and,
   optionally, a pre-filled identifier.
2. The widget starts a short-lived session (`POST /v1/widget/session`) and shows
   the user's saved postcodes, if any.
3. The user picks a bookmark or searches for a postcode.
4. The widget closes and delivers a [`PostcodeSelection`](/widget/overview#the-selection-payload)
   to your app.

## SDKs

| Platform                     | Package                   | Status    |
| ---------------------------- | ------------------------- | --------- |
| Web                          | `@nipost/postcode-widget` | Available |
| Flutter                      | `nipost_postcode_widget`  | Available |
| Android / iOS / React Native | —                         | Planned   |

## The selection payload

Every SDK delivers the same JSON shape (version 1):

```json theme={null}
{
  "version": 1,
  "postcode": "FC02A09DB09",
  "formatted": "FC-02-A09-DB-09",
  "level": 5,
  "segments": { "state": "FC", "lga": "02", "district": "A09", "area": "DB", "unit": "09" },
  "names": { "state": "Federal Capital Territory", "lga": "…", "district": "…", "area": "…" },
  "latitude": 9.0563,
  "longitude": 7.4985,
  "source": "bookmark",
  "label": "Home"
}
```

`segments`/`names` fields below the selection's `level` are `null`.
`latitude`/`longitude` are present only when your key's lookup level permits
point geometry. `source` is `"bookmark"` or `"search"`; `label` is set for
bookmarks only.

## Privacy model

The widget intentionally skips OTP verification for a friction-free flow, so
treat identifiers with care:

* Bookmark reads return **only** `{postcode, label}` — no names, no contact
  details, no account data.
* Session responses are identical whether or not the identifier matched an
  account, so the API cannot be used to probe which NINs or emails exist.
* Sessions are rate-limited per key and per IP, metered in credits, and audited
  with a **hashed** identifier (the raw NIN or email is never logged).
* Publishable keys are origin-bound in browsers and instantly revocable.
