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

# Get transaction

> Read the current status of a transaction and, once it has finished, the decision.

```http theme={null}
GET /api/account/integration/kyc/transaction/{transaction_id}
```

Returns the transaction: where it is in its lifecycle and, once analysis has finished,
the decision with every reason behind it.

## Request

<ParamField header="Authorization" type="string" required>
  `Bearer {access_token}` — see [Authentication](/api-reference/authentication).
</ParamField>

<ParamField path="transaction_id" type="string (UUID)" required>
  The id returned by [Create transaction](/api-reference/transactions/create-transaction).
</ParamField>

## Response

<ResponseField name="id" type="string (UUID)">
  The transaction id.
</ResponseField>

<ResponseField name="customer_id" type="string (UUID)">
  The customer this transaction belongs to.
</ResponseField>

<ResponseField name="status" type="string">
  `CREATED`, `INITIATED`, `COMPLETED`, `PROCESSING`, `FINISHED`, `FAILED` or `EXPIRED`.
  See [How verification works](/how-it-works).
</ResponseField>

<ResponseField name="created_at" type="string (ISO-8601)">
  When your backend opened the transaction.
</ResponseField>

<ResponseField name="initiated_at" type="string (ISO-8601) | null">
  When the SDK started the session on the device.
</ResponseField>

<ResponseField name="completed_at" type="string (ISO-8601) | null">
  When the user finished capture.
</ResponseField>

<ResponseField name="processing_at" type="string (ISO-8601) | null">
  When analysis started.
</ResponseField>

<ResponseField name="finished_at" type="string (ISO-8601) | null">
  When analysis ended.
</ResponseField>

<ResponseField name="result_data" type="object | null">
  The analysis result. `null` until the transaction reaches `FINISHED` or `FAILED`.
  Full structure in [Reading a result](/results/reading-a-result).
</ResponseField>

## Example

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

  ```typescript Node.js lines theme={null}
  const res = await fetch(
    `${CHMOD_API_URL}/api/account/integration/kyc/transaction/${transactionId}`,
    { headers: { Authorization: `Bearer ${accessToken}` } },
  );

  const transaction = await res.json();

  if (transaction.status === "FINISHED") {
    handleDecision(transaction.result_data.decision, transaction.result_data.issues);
  }
  ```

  ```python Python lines theme={null}
  res = requests.get(
      f"{CHMOD_API_URL}/api/account/integration/kyc/transaction/{transaction_id}",
      headers={"Authorization": f"Bearer {access_token}"},
  )
  transaction = res.json()
  ```
</CodeGroup>

```json Response — approved lines theme={null}
{
  "id": "34dc4204-2b57-42ae-a3bc-1d114935b98f",
  "customer_id": "4a63b11c-803d-4126-bf91-d5f8290ff0a5",
  "created_at": "2026-09-10T14:22:00.000Z",
  "initiated_at": "2026-09-10T14:23:12.450Z",
  "completed_at": "2026-09-10T14:25:30.110Z",
  "processing_at": "2026-09-10T14:25:30.980Z",
  "finished_at": "2026-09-10T14:25:44.220Z",
  "status": "FINISHED",
  "result_data": {
    "decision": "APPROVED",
    "issues": [],
    "document": { "status": "PASSED", "data": { "...": "..." } },
    "liveness": { "status": "PASSED", "data": { "...": "..." } },
    "face_comparison": { "status": "PASSED", "data": { "...": "..." } }
  }
}
```

```json Response — rejected lines theme={null}
{
  "id": "34dc4204-2b57-42ae-a3bc-1d114935b98f",
  "customer_id": "4a63b11c-803d-4126-bf91-d5f8290ff0a5",
  "status": "FINISHED",
  "result_data": {
    "decision": "REJECTED",
    "issues": [
      {
        "type": "REJECT",
        "code": "EXPIRED_DOCUMENT",
        "message": "The document has expired.",
        "details": { "evaluated_at": "2026-09-10" }
      },
      {
        "type": "REJECT",
        "code": "SURNAME_MISMATCH",
        "message": "The surnames on the document do not match the expected value.",
        "details": { "score": 0.41, "threshold": 0.85 }
      }
    ],
    "document": { "status": "REJECTED", "data": { "...": "..." } },
    "liveness": { "status": "PASSED", "data": { "...": "..." } }
  }
}
```

```json Response — still in progress lines theme={null}
{
  "id": "34dc4204-2b57-42ae-a3bc-1d114935b98f",
  "customer_id": "4a63b11c-803d-4126-bf91-d5f8290ff0a5",
  "created_at": "2026-09-10T14:22:00.000Z",
  "initiated_at": "2026-09-10T14:23:12.450Z",
  "status": "INITIATED",
  "result_data": null
}
```

## Polling

Prefer [webhooks](/results/webhooks): they arrive as soon as the decision exists, and
polling a transaction that is still `INITIATED` tells you nothing you did not already know.

When you do poll — as a reconciliation job, or as a fallback when a webhook did not
arrive — back off rather than hammering:

```typescript lines theme={null}
async function waitForDecision(transactionId: string, timeoutMs = 120_000) {
  const deadline = Date.now() + timeoutMs;
  let delay = 2_000;

  while (Date.now() < deadline) {
    const tx = await getTransaction(transactionId);

    // FINISHED and FAILED are terminal; EXPIRED means the user never came back.
    if (["FINISHED", "FAILED", "EXPIRED"].includes(tx.status)) return tx;

    await sleep(delay);
    delay = Math.min(delay * 2, 15_000);
  }

  throw new Error(`Transaction ${transactionId} did not settle in time`);
}
```

<Info>
  Analysis normally settles within seconds of the user finishing. A transaction sitting in
  `INITIATED` is waiting on the user, not on chmod — it will move to `EXPIRED` once
  `transaction_ttl_minutes` elapses.
</Info>

## Next

<CardGroup cols={2}>
  <Card title="Reading a result" icon="file-lines" href="/results/reading-a-result">
    Every field inside `result_data`.
  </Card>

  <Card title="Issue codes" icon="triangle-exclamation" href="/results/issue-codes">
    What each rejection reason means.
  </Card>
</CardGroup>


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