> ## 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.

# Quickstart

> One complete verification, from access token to final decision, in five requests.

This walks through one complete verification: authenticate, create a customer, open a
transaction, run the flow on the device, and read the decision.

You need your account's OAuth client credentials and API base URL. Both come from your
chmod account manager.

<Steps>
  <Step title="Get an access token">
    All API calls are authenticated with a bearer token from your account's OAuth
    endpoint. Tokens live for an hour; reuse one until it expires.

    ```bash lines theme={null}
    curl -X POST https://{your-account}.auth.us-east-1.amazoncognito.com/oauth2/token \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=client_credentials" \
      -d "client_id=$CHMOD_CLIENT_ID" \
      -d "client_secret=$CHMOD_CLIENT_SECRET" \
      -d "scope=account-integration-api/account-api-access"
    ```

    ```json Response lines theme={null}
    {
      "access_token": "eyJraWQiOiJ...",
      "expires_in": 3600,
      "token_type": "Bearer"
    }
    ```
  </Step>

  <Step title="Create the customer">
    A customer is the person, and it persists across transactions. Create one the first
    time you verify someone, then reuse the returned `customer_id` forever — that is what
    lets chmod compare a new selfie against the face you already enrolled.

    ```bash lines theme={null}
    curl -X POST https://{your-api-host}/api/account/integration/kyc/customer \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "external_customer_id": "user_84213",
        "email": "ana@example.com",
        "phone_number": "+5491122334455"
      }'
    ```

    ```json Response lines theme={null}
    {
      "external_customer_id": "user_84213",
      "customer_id": "4a63b11c-803d-4126-bf91-d5f8290ff0a5",
      "created_at": "2026-09-10T14:22:00.000Z"
    }
    ```

    Store `customer_id` against your own user record.
  </Step>

  <Step title="Open a transaction">
    This is where you say what should be verified and what counts as acceptable. The
    response carries the `sdk_token` your app needs.

    ```bash lines theme={null}
    curl -X POST https://{your-api-host}/api/account/integration/kyc/transaction \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "customer_id": "4a63b11c-803d-4126-bf91-d5f8290ff0a5",
        "transaction_type": "DOCUMENT_AND_BIOMETRIC",
        "config": { ... }
      }'
    ```

    ```json Response lines theme={null}
    {
      "transaction_id": "34dc4204-2b57-42ae-a3bc-1d114935b98f",
      "sdk_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "token_type": "Bearer",
      "expires_in": 3600
    }
    ```

    Every field in `config` is optional and falls back to a documented default. The full
    configuration is on [Create transaction](/api-reference/transactions/create-transaction).
  </Step>

  <Step title="Run the flow on the device">
    Pass the `sdk_token` to your app and hand it to the SDK. The SDK renders document
    capture, the liveness check and the result screen, then returns.

    <CodeGroup>
      ```swift iOS lines theme={null}
      let token = try await backend.createKycTransaction()

      let request = ChmodKycRequest(
          baseURL:  URL(string: "https://api.chmod.com")!,
          sdkToken: token
      )

      let result = await ChmodKyc.verify(from: self, request: request)
      ```

      ```kotlin Android lines theme={null}
      val token = backend.createKycTransaction()

      verification.launch(
          ChmodKycRequest(
              baseUrl  = "https://api.chmod.com",
              sdkToken = token
          )
      )
      ```
    </CodeGroup>

    Full setup in [iOS installation](/sdk/ios/installation) and
    [Android installation](/sdk/android/installation).
  </Step>

  <Step title="Read the decision">
    When the analysis finishes, chmod calls your webhook. Fetch the transaction to get
    the verdict and the reasons behind it.

    ```bash lines theme={null}
    curl https://{your-api-host}/api/account/integration/kyc/transaction/34dc4204-2b57-42ae-a3bc-1d114935b98f \
      -H "Authorization: Bearer $ACCESS_TOKEN"
    ```

    ```json Response lines theme={null}
    {
      "id": "34dc4204-2b57-42ae-a3bc-1d114935b98f",
      "customer_id": "4a63b11c-803d-4126-bf91-d5f8290ff0a5",
      "status": "FINISHED",
      "result_data": {
        "decision": "APPROVED",
        "issues": [],
        "document": { "status": "PASSED", "data": { "...": "..." } },
        "liveness": { "status": "PASSED", "data": { "...": "..." } }
      }
    }
    ```

    `decision` is `APPROVED`, `REJECTED` or `UNDETERMINED`. When it is `REJECTED`, every
    reason is in `issues[]` with a stable `code` — see [Issue codes](/results/issue-codes).
  </Step>
</Steps>

## Next

<CardGroup cols={2}>
  <Card title="Create transaction" icon="circle-plus" href="/api-reference/transactions/create-transaction">
    Every rule you can enforce, and what each one defaults to.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/results/webhooks">
    Receive decisions as they happen, and verify the signature.
  </Card>

  <Card title="Reading a result" icon="file-lines" href="/results/reading-a-result">
    Every field the transaction returns.
  </Card>

  <Card title="Errors" icon="circle-exclamation" href="/api-reference/errors">
    Status codes and what is safe to retry.
  </Card>
</CardGroup>


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