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

# Overview

> What the mobile SDK does, what it needs from your backend, and which platforms are available.

The chmod SDK renders the whole verification experience inside your app: document capture,
the liveness check, and an optional result screen. You launch it with a token and it hands
back a typed outcome.

<CardGroup cols={2}>
  <Card title="iOS" icon="apple" href="/sdk/ios/installation">
    Swift Package Manager. SwiftUI and UIKit. iOS 16+.
  </Card>

  <Card title="Android" icon="android" href="/sdk/android/installation">
    Gradle via GitHub Packages. Compose and Views. minSdk 24.
  </Card>

  <Card title="React Native" icon="react" href="/sdk/react-native">
    In progress.
  </Card>

  <Card title="Flutter" icon="code" href="/sdk/flutter">
    In progress.
  </Card>
</CardGroup>

## What the SDK needs

Exactly two things:

<ResponseField name="baseUrl" type="string">
  Your chmod API host, the same one your backend calls.
</ResponseField>

<ResponseField name="sdkToken" type="string">
  A token scoped to one transaction, minted by your backend with [Create transaction](/api-reference/transactions/create-transaction).
</ResponseField>

Optionally, a configuration object controlling how the flow looks and behaves. See
[SDK configuration](/sdk/configuration/overview).

<Warning>
  Your app must never hold your API client id and secret. It receives an `sdk_token` that
  only permits the calls for one transaction, and it should get that token from your own
  backend over your own authenticated endpoint.
</Warning>

## The shape of an integration

On both platforms the sequence is the same, and it is short:

<Steps>
  <Step title="Ask your backend for a token">
    Your app calls an endpoint you own. That endpoint authenticates the user, creates the
    transaction, and returns the `sdk_token`. Do this off the main thread.
  </Step>

  <Step title="Launch the flow">
    Hand the token to the SDK. It takes over the screen and drives the user through
    capture.
  </Step>

  <Step title="Receive the outcome">
    The SDK returns `completed`, `cancelled` or `failed`, always on the main thread.
  </Step>

  <Step title="Let your backend deliver the verdict">
    The decision is produced after capture ends and reaches your backend through the
    webhook. Your app finds out from your backend, not from the SDK.
  </Step>
</Steps>

## Three outcomes, and what they mean

| Outcome | What happened | What to show |
| - | - | - |
| `completed` | The user finished the flow | We are reviewing your document |
| `cancelled` | The user backed out deliberately | Return to where they were, no error |
| `failed` | Something went wrong; a code says what | Depends on the code |

<Warning>
  `completed` does **not** mean approved. It means the capture finished and everything was uploaded. The verdict is produced afterwards, usually within seconds, and delivered to your backend through the [webhook](/results/webhooks).

  An app that shows a success screen at `completed` is lying to the user roughly as often
  as your rejection rate.
</Warning>

Every outcome carries the transaction id, so you can correlate what the app saw with what
your backend later receives.

## Permissions

The SDK asks for what it needs, when it needs it, and converts a refusal into a typed
result rather than a crash.

| Permission | When | Required |
| - | - | - |
| Camera | Before document capture or liveness | Always |
| Location | At the start of the flow | Only when you enable it |

<Warning>
  Do not request the camera permission yourself before launching the flow. Asking early,
  out of context, gets you a denial with nothing on screen to explain why you needed it.
  The SDK asks at the moment the camera appears, which is when the user understands the
  request.
</Warning>

Location is off unless you turn it on, and it only matters if you use the GPS rules in [device policy](/configuration/device-policy).

## What the SDK reports

Alongside the images, the SDK collects signals about the device: model and OS, whether it
is an emulator, whether root or jailbreak was detected, network type and carrier, and
(with permission) GPS coordinates.

Those signals are what [`device_policy`](/configuration/device-policy) acts on, and they all come back in `result_data.metadata` so you can audit any decision.

## Versions

| Platform | Requirements |
| - | - |
| iOS | iOS 16.0+, Swift tools 5.9, SwiftUI or UIKit |
| Android | minSdk 24 (Android 7.0), compileSdk 35+, JDK 17-21, Kotlin 2.0+, Compose or Views |

The copy, the colours and the capture behaviour are configured identically on both
platforms, and the localization keys are shared. See
[SDK configuration](/sdk/configuration/overview).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.