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

# Customers and transactions

> The two objects everything else hangs off, and why reusing a customer matters so much.

chmod has two first-class objects. A **customer** is a person. A **transaction** is one
attempt to verify that person. Everything else — configuration, tokens, results, webhooks —
belongs to one or the other.

```mermaid theme={null}
flowchart LR
    C[Customer] -->|1..n| T1[Transaction]
    C -->|1..n| T2[Transaction]
    T1 --> R1[Result]
    T2 --> R2[Result]
    C -.-> F[Enrolled face]
    C -.-> H[Document history]
```

## Customers

A customer is created once and identified by a `customer_id` you store against your own user record. When you create one you give chmod your own identifier for the person, and optionally an email and a phone number.

### What chmod accumulates per customer

The customer record grows with each successful verification, and that growth is where a
large part of chmod's value sits:

* **An enrolled face.** The liveness capture from the first successful biometric
  transaction becomes the reference face. Every later transaction compares the new selfie
  against it. This is the check that catches one person opening several accounts under
  different names.
* **Document history.** Document numbers, dates of birth and names extracted in earlier
  transactions. A later document that disagrees — a different date of birth, a different
  number for the same document type — is flagged, with a pointer to the transaction it
  conflicts with.

Neither exists on a customer's first transaction. That is expected, and chmod says so with an informational finding rather than a rejection.

<Warning>
  Creating a fresh customer for every verification throws all of this away. Every
  transaction becomes a first transaction, and the identity checks never run. Store
  `customer_id` once and reuse it for as long as that person exists in your system.
</Warning>

### Customer status

chmod maintains a status on every customer, and it participates in every analysis:

| Status | Effect |
| - | - |
| Active | Normal. |
| Suspicious | A warning is added to every verification. The decision is unchanged. |
| Blocked | Every verification is rejected. |

## Transactions

A transaction is one verification attempt.

| Property | Meaning |
| - | - |
| Transaction id | Identifies this attempt. Appears on the webhook and in the SDK result. |
| Type | Which checks run — see [Verification types](/concepts/verification-types). |
| Configuration | The rules for **this** attempt. Two transactions for one customer can differ. |
| SDK token | Lets your app run the flow for this one transaction, and nothing else. |
| Status | Where the attempt is in its lifecycle. |
| Result | The decision and everything behind it, once analysis has finished. |

### Configuration is per transaction

There is no account-level configuration. Every transaction carries its own rules, so a strict onboarding check and a light step-up check can run from the same integration without touching any shared setting. Once a transaction is created its rules are fixed — to change them, create a new transaction.

### Lifecycle

| Status | Meaning |
| - | - |
| Created | Opened by your backend. Nothing has happened on the device yet. |
| Initiated | The SDK started a session. |
| Completed | The user finished capture. |
| Processing | Analysis is running. |
| Finished | Analysis finished. The decision is available. |
| Failed | Analysis could not run. The decision is undetermined. |
| Expired | The time limit elapsed before the user finished. |

Finished, failed and expired are terminal. A transaction is never reopened or re-run; a retry is a new transaction for the same customer. See [How verification works](/how-it-works) for the full sequence.

## What to store on your side

| Store | Why |
| - | - |
| The customer id, against your user | Reuse across transactions. The single most important row. |
| The transaction id, against the attempt | Correlate webhooks, SDK results and support tickets. |
| The decision and the finding codes | Your own audit trail and analytics. |
| When the verdict was reached | Reporting and reconciliation. |

You do not need to store the full result — it can be fetched again by id — and there are good reasons not to: it contains document images and personal data. Store what you act on, and fetch the rest when you need it.


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