# Proof of Location

:::note[In one sentence]

A *proof of location* is a signed, time-stamped record that a device was inside a region at a given time, and anyone holding it can verify the signatures offline.

:::

For example, before your backend lets a user trade, it can require a proof that the phone is in the US. Your app asks the SDK, and a `YES` or `NO` comes back with a proof attached:

<Tabs groupId="platform">
  <TabItem value="swift" label="Swift (iOS)">

```swift
let v = await sdk.loc.isWithin(region: .country(isoCode: "US"))
if v.result == .yes {
    ship(v.proof!.proofBytes)
}
```

  </TabItem>
  <TabItem value="kotlin" label="Kotlin (Android)">

```kotlin
val v = sdk.loc.isWithin(OctetRegion.country("US"))
if (v.result == OctetVerdict.Result.YES) {
    ship(v.proof!!.proofBytes)
}
```

  </TabItem>
</Tabs>

`ship` stands for your own code that sends the proof bytes to your backend. Your backend saves them to a file and checks them with the open-source verifier, with no call to Octet:

```bash
octet-verify proof.bin
```

Exit code `0` means the proof is authentic. See [Verifier Quick Start](/docs/v3.0/getting-started/verifier-quickstart/).

## Why a claim needs a proof

A claim like "the device was in the US at 3 pm Tuesday" can come from the OS, the GPS chip, a browser API, or a mock-location app. All of them are easy to forge. The claim is only worth acting on if a third party (your backend, an auditor, a regulator) can check it without trusting whoever made it.

The Octet SDK produces those proofs. Every `YES` or `NO` it returns carries one. An `INDETERMINATE` carries none. You can:

- Forward a proof to your backend and verify it offline with the open-source verifier.
- Hand it to a compliance auditor to re-check months later.
- Store it as a durable record of where the device was at that time.

## How it works

The SDK combines several independent on-device signals (GNSS, cellular network identity, motion sensors) with platform attestation (Apple App Attest on iOS, hardware key attestation on Android) to produce a verdict and a cryptographic proof. The SDK creates the signing key in the device's hardware where it can (the Secure Enclave on iOS, StrongBox or the Trusted Execution Environment on Android). Each proof records where its key lives as the device-key security tier: `HARDWARE_STRONGBOX`, `HARDWARE_TEE`, or `SOFTWARE`. On a device without hardware-backed key storage, the SDK falls back to a software key and still signs proofs, so a verifier decides which tiers to accept. The proof is a signed protobuf that names:

- The **claimed region** (for example country `US`, or a disc of radius 250 m).
- The **time of the fix** and the validity interval the proof covers.
- The **assurance tier** (`spoofingVerdict`: `VERIFIED` or `PLAUSIBLE`) and the device-integrity status.
- An **attestation chain** from platform hardware (App Attest on iOS, key attestation on Android), which the SDK checks when it builds the proof.

You call `isWithin(region)` and get back a `Verdict`. On `YES` or `NO` the verdict carries a proof. If the SDK cannot get a trustworthy fix (rooted device, a mock-location app, or no usable GPS signal), it issues no proof and returns `INDETERMINATE` with a reason code.

```mermaid
flowchart LR
    A[Your app] -->|isWithin region| B[OctetSDK]
    B --> C{Can the SDK<br/>answer?}
    C -->|Yes| D[Verdict YES or NO<br/>+ signed proof]
    C -->|No| E[Verdict INDETERMINATE<br/>+ reason code]
    D -->|forward| F[Your backend]
    F -->|verify offline| G[octet-verify]
```

## What the SDK does not do

- **Judge the user.** It reports whether it can issue a proof and, when it cannot, a reason code. An adversarial reason (`SPOOFING_DETECTED`, `MOCK_LOCATION_DETECTED`, `TAMPERING`, `ATTESTATION_FAILED`) describes the location fix, not the person. What to do about the user is your policy.
- **Guarantee a `YES`.** On an emulator, indoors with no cellular, on a rooted device, or with a mock-location app running, the result is `INDETERMINATE`.
- **Predict the future.** A proof states where the device was at time T, not where it will be later. See [Time Semantics](/docs/v3.0/concepts/time-semantics/).

## Where to go next

- [Device Attestation](/docs/v3.0/concepts/device-attestation/). How App Attest and key attestation tie a proof to genuine hardware.
- [Verdicts](/docs/v3.0/concepts/verdicts/). The `YES` / `NO` / `INDETERMINATE` values and how to read the reason code.
- [Regions](/docs/v3.0/concepts/regions/). What kinds of areas you can ask about.
- [Time Semantics](/docs/v3.0/concepts/time-semantics/). How `atTime` and proof validity intervals interact.
