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

# Troubleshooting and FAQ

> The problems most integrations hit, what causes them, and the questions everyone asks.

Backend and flow-level problems are covered here. For SDK-specific symptoms — crashes,
permissions, build errors — see the troubleshooting sections on
[iOS](/sdk/ios/handling-results#troubleshooting) and
[Android](/sdk/android/handling-results#troubleshooting).

## Authentication

<AccordionGroup>
  <Accordion title="401 on every request">
    The access token is missing, invalid or expired. Confirm you are sending it as a bearer token in the `Authorization` header and that it is under an hour old. When it expires, request a new one and retry.
  </Accordion>

  <Accordion title="The token request itself fails">
    Check the four form fields exactly: `grant_type=client_credentials`, your `client_id`,
    your `client_secret`, and `scope=account-integration-api/account-api-access`. The body
    must be `application/x-www-form-urlencoded`, not JSON.
  </Accordion>
</AccordionGroup>

## Creating transactions

<AccordionGroup>
  <Accordion title="400 with a configuration error">
    The `error` field names the field and the constraint. The usual suspects: a time limit outside 1–1440 minutes, a score outside 0.1–1.0, an age outside 0–200, or a webhook URL that is not `https://`. Nothing is created on a 400. See [Errors](/api-reference/errors).
  </Accordion>

  <Accordion title="The app gets a token but the SDK fails immediately">
    Almost always a base URL mismatch: the token was minted against one host and the SDK is pointed at another, or at the OAuth host instead of the API host. The SDK's base URL is the same API host your backend calls.
  </Accordion>

  <Accordion title="The SDK says the token is expired">
    The token lives as long as the transaction's time limit. If your app fetches a token and holds it before launching the flow, a short limit can expire in between. Mint the token when the user taps the button, not at app start.
  </Accordion>

  <Accordion title="I want to change the rules on a transaction I already created">
    You cannot. Configuration is fixed at creation. Create a new transaction — the old one
    will expire on its own.
  </Accordion>
</AccordionGroup>

## Results

<AccordionGroup>
  <Accordion title="Everything is rejected while I test">
    Check the findings. If you are testing on a simulator or emulator, you are hitting emulator detection, which rejects by default. Set that rule to ignore while you test on emulators — and make sure the configuration your real users get does not inherit that.
  </Accordion>

  <Accordion title="The transaction is stuck in INITIATED">
    It is waiting on the user, not on chmod. Initiated means the SDK opened a session and the person has not finished capture. It will move to expired when the time limit runs out. If users are consistently stuck here, they are abandoning inside the flow — look at the SDK's welcome screen, permission prompts and document guidance.
  </Accordion>

  <Accordion title="UNDETERMINED — what do I do?">
    Read the findings. A configuration code means your rules could not be applied: fix them and create a new transaction. An engine code means a provider failure: retry with a new transaction, and alert if it keeps happening. Never treat undetermined as a rejection of the user.
  </Accordion>

  <Accordion title="APPROVED but with FACE_COMPARISON_SKIPPED_NO_REFERENCE">
    This is the customer's first transaction. There is no enrolled face yet, so the comparison against it cannot run. It is informational, it is expected, and the face captured now becomes the reference for next time. If you see it on a customer who *should* have history, you are probably creating a new customer per verification.
  </Accordion>

  <Accordion title="BIOMETRIC_ONLY approves people it should not">
    On a customer with no enrolled face, a biometric-only verification only proves a live person was present — it cannot prove who. Require a completed document-and-biometric verification before allowing biometric-only for that customer. See [Verification types](/concepts/verification-types#when-there-is-no-enrolled-face).
  </Accordion>

  <Accordion title="Legitimate users fail NAME_MISMATCH">
    Your similarity threshold is too high, or you are matching against a name with a middle name the document omits (or vice versa). Documents print names uppercase and unaccented. `0.85` absorbs that; `1.0` does not. The finding's `details.score` tells you how close each failure was.
  </Accordion>

  <Accordion title="A document that should be accepted returns DOCUMENT_NOT_ELIGIBLE">
    Your accepted-documents list does not include that exact country and type. Check the filter mode too: under `ALLOW`, only listed documents pass. If the code is `DOCUMENT_TYPE_NOT_SUPPORTED` instead, chmod does not support that document at all — see the [supported documents](/configuration/document-policy#supported-documents) table.
  </Accordion>
</AccordionGroup>

## Webhooks

<AccordionGroup>
  <Accordion title="Nothing arrives">
    In order: was the webhook set on the transaction? Is the URL HTTPS and reachable from the public internet (not `localhost`, not behind your VPN)? Is your endpoint returning a success status? See [Webhooks](/results/webhooks#not-receiving-calls).
  </Accordion>

  <Accordion title="Signature verification fails">
    The signed string is exactly the timestamp header value, a colon, and the transaction id from the body. No spaces, no newline, no re-formatting of the timestamp. Make sure you are verifying against the keys published on the same host that sent the webhook.
  </Accordion>

  <Accordion title="The same notification arrives twice">
    Expected. Delivery is at-least-once. Key your handler on the transaction id plus status and make repeats a no-op.
  </Accordion>
</AccordionGroup>

## Frequently asked

<AccordionGroup>
  <Accordion title="Does completed from the SDK mean the user was approved?">
    No. It means the user finished the capture flow. The decision is produced afterwards and reaches your backend by webhook or by fetching the transaction. Show "we're reviewing your document" at completed.
  </Accordion>

  <Accordion title="Can my app call the chmod API directly?">
    No. The app holds only the SDK token, which the SDK uses for its own session calls. Everything else — creating customers and transactions, reading results — is your backend, with credentials that never leave your server.
  </Accordion>

  <Accordion title="Can I reuse a transaction for a second attempt?">
    No. Transactions are single-use and terminal states are final. A retry is a new
    transaction for the same customer. That is cheap, and it keeps every attempt auditable.
  </Accordion>

  <Accordion title="Which countries and documents are supported?">
    Seventeen Latin American countries, with national ID, passport and driver licence in
    each, plus resident and temporary permits for Colombia. The full matrix is in
    [Document policy](/configuration/document-policy#supported-documents).
  </Accordion>

  <Accordion title="Can I verify someone without a document?">
    A biometric-only verification runs a liveness check with no document. On a customer who already completed a document-and-biometric verification, it also confirms they are the same person. On a brand-new customer it proves only that a live human was present.
  </Accordion>

  <Accordion title="How long does analysis take?">
    Normally seconds after the user finishes capture. If a transaction sits in processing for more than a couple of minutes, contact support with the transaction id.
  </Accordion>

  <Accordion title="Where do I report a problem?">
    Your account manager, or the support link in the navigation. Include the transaction id, the exact error message or finding codes, and the time in UTC.
  </Accordion>
</AccordionGroup>


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