import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Session Lifecycle

:::note[In short]

`Octet.start(...)` brings the SDK up and returns a handle. `OctetSdk.close()` (new in 2.0) tears it down and stops all background work. Between the two, the SDK runs a proof pipeline and, on Android, a location foreground service.

:::

## Starting

[`Octet.start(...)`](/docs/api-reference/octet-start/) bootstraps the license, brings up the proof pipeline, and returns an `OctetSdk` handle. Hold that handle for as long as you need proofs. Calling `start` a second time in one process is not supported; reuse the handle you already have.

## Running

While the handle is live, the SDK keeps a location and sensor session running so a predicate can produce a proof on demand. On **Android** this session runs inside a **location foreground service**, which Android requires for location work while the app is off-screen. The service posts a notification titled **"Location active"** on a channel named **"Location"**. The notification is Android's mandatory, non-suppressible requirement for a location foreground service, so it cannot be hidden while the service runs.

## Closing

`OctetSdk.close()` releases every resource the handle holds and stops all background work: the location and sensor session, the Android foreground service (which removes its notification), and the periodic license heartbeat.

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

```swift
let sdk = try await Octet.start(config: config)
let verdict = await sdk.loc.isWithin(region: .country(isoCode: "US"))
// ... prove during the flow ...
await sdk.close()   // async on iOS
```

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

```kotlin
val sdk = Octet.start(context, config)
val verdict = sdk.loc.isWithin(OctetRegion.country("US"))
// ... prove during the flow ...
sdk.close()   // synchronous on Android
```

  </TabItem>
</Tabs>

`close()` is `async` on iOS and synchronous on Android, matching the `start` split. After `close()` the handle is spent: a predicate call on a closed handle returns `INDETERMINATE` (never a crash, never a stale `YES`). Call `Octet.start` again for a new session.

## When to close

Close the handle when the flow that needs proofs ends. An app that proves on a foreground consent screen should `close()` when that screen closes, so location collection matches an "only while in use" claim. Leaving the handle open keeps the Android foreground service (and its high-power location work) running.

## Where to go next

- [`OctetSdk`](/docs/api-reference/octet-sdk/): the handle, `loc`, `flags`, and `close()`.
- [`Octet.start(...)`](/docs/api-reference/octet-start/): how the session is brought up.
