# Regions

:::note[In one sentence]

An `OctetRegion` is the *area* you ask about (country, city, disc, polygon, bounding box), and its shape determines how the SDK proves containment.

:::

## How shapes map to evidence

Different region shapes are answered in different ways. A *disc* needs a precise location fix. A *city* resolves to a polygon set. Letting callers supply a free-form lat/lon polygon would force the SDK to triangulate and re-quantize every query, which the H3-based proof format does not support. Polygons are therefore accepted only as **H3 cell sets**.

```mermaid
flowchart TD
    R[OctetRegion] --> Named[Named lookups]
    R --> Geometric[Geometric shapes]
    Named --> Country[country isoCode]
    Named --> Sub[subdivision isoCode]
    Named --> City[city name]
    Geometric --> Disc[disc center radius]
    Geometric --> Ellipse[ellipse center axes heading]
    Geometric --> Box[box3D lat lon alt ranges]
    Geometric --> Poly[polygonSet H3 cells]
    Geometric --> Earth[earth maxAltitude]
```

## The shapes

| Factory | Verified via | Typical use |
|---|---|---|
| `earth(maxAltitudeMeters)` | Always `YES`. | Sanity check / fallback. |
| `country(isoCode)` | Resolved on the device and bound into the signed proof. | "Is the user in the US?" |
| `subdivision(isoCode)` | Resolved on the device at the state or province level. | ISO 3166-2 codes: `US-CA`, `FR-75`, `JP-13`. |
| `usState(stateCode)` | Same as `subdivision`. | Sugar for `subdivision("US-XX")`. |
| `city(name)` | SDK resolves the name to an H3 polygon set. The proof is verified against that polygon. | "Is the user in San Francisco?" |
| `disc(center, radiusMeters)` | The proof carries the disc as an ellipse with equal axes. The SDK checks containment from the distance between the centers and the two radii. | "Is the device within 250 m of a saved anchor point?" |
| `ellipse(center, semiMajorM, semiMinorM, headingDeg)` | 2D ground ellipse. Disc is a special case. Only discs are answered today: an ellipse with unequal axes returns `INDETERMINATE` with `NOT_YET_RELEASED`. | GNSS uncertainty ellipses, oriented zones. |
| `box3D(latRange, lonRange, altRange)` | 3D bounding box. | Volumetric containment, building floors. |
| `polygonSet(cells)` | Union of H3 cells. | Custom geofences pre-quantized to H3. |

All factories **validate eagerly**. Invalid lat/lon, malformed ISO codes, non-positive radii, ellipse axes out of order: all trap at construction. An invalid region never reaches a predicate call.

## Why polygons are H3-only

If you have a free-form polygon (a delivery zone, an event venue, a building footprint), you (or your tooling) quantize it to H3 cells ahead of time and pass the cell list. The SDK compares those cell IDs with the cells of the proof's claimed region on the device, so nothing is triangulated at request time. The claimed cells are part of the signed proof.

The comparison treats each cell ID as an exact value. When every claimed cell is in your list, the answer is `YES`. When none of them is, the answer is `NO`. Any other overlap is `INDETERMINATE` with `NO_PROOF_AT_RESOLUTION`. A cell ID also encodes its resolution, but the comparison doesn't relate cells across resolutions: a coarse cell in your list doesn't match the finer cells inside it.

## Construction helpers (Android only)

On Android, two additional surfaces let you build regions dynamically:

- `getRegion(RegionSpec.country("US"))`. Symbolic lookup, useful when the region name comes from configuration or a server response. The `city` / `namedZone` variants currently throw `OctetFutureFlag` and are not available in this release.
- `buildRegion { disc(center = LatLon(37.42, -122.08), radiusMeters = 250.0) }`. A DSL over the static factories for assembling regions from runtime data.

The `RegionSpec` DSL and `getRegion` are Android-only. iOS exposes the static factories.

## Inspecting a region

Two helpers turn a region into a string:

- **`whatisRegion(r)`**. Short, human-readable. For log lines and debug overlays. **Not stable** across SDK versions.
- **`regionToStr(r)`**. Canonical, machine-readable, **stable** wire form. Suitable for log diffs, idempotency keys, eventual `regionFromStr` round-trip.

Both are surfaced uniformly on every API object via `.toStr()`, `.toJson()`, and `.toJsonl()`. See [Serialization](/docs/v2.0/api-reference/serialization/).

## Where to go next

- [OctetRegion API Reference](/docs/v2.0/api-reference/octet-region/) for the exact signatures and validation rules.
- [Verdicts](/docs/v2.0/concepts/verdicts/) for what happens when the cached proof's region is coarser than your query.
