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

# KYC SDK (hosted)

> Redirect users to Zapyd's hosted verification and get the result by webhook.

The KYC SDK is Zapyd's hosted verification flow. You create a link and redirect the user to it. Zapyd collects the documents, verifies them and sends you the result. You never handle identity documents.

<CardGroup cols={2}>
  <Card title="See the flow" icon="mobile-screen" href="/guides/customers/kyc-demo-india">
    An interactive demo of every screen an Indian user sees.
  </Card>

  <Card title="Already verify users?" icon="share-nodes" href="/guides/customers/kyc-sharing">
    Use KYC sharing to submit data you collected.
  </Card>
</CardGroup>

## Flow

```mermaid theme={null}
sequenceDiagram
    participant App as Your backend
    participant Z as Zapyd
    participant U as User
    App->>Z: POST /customer/create
    App->>Z: POST /kyc/generate-link
    Z-->>App: url
    App->>U: Redirect to url
    U->>Z: Documents, PAN, selfie
    Z-->>U: Redirect to your redirect_url
    Z-->>App: CUSTOMER webhook (VERIFIED or FAILED)
```

## 1. Generate the link

Create the customer first, then call [`POST /kyc/generate-link`](/api-reference-exchange/endpoint/kyc/generate-link).

<CodeGroup>
  ```json Request theme={null}
  {
    "customer_id": "075986f3-282b-4555-bfcd-fad973e32596",
    "redirect_url": "https://yourapp.com/kyc/return"
  }
  ```

  ```json Response theme={null}
  {
    "status": true,
    "message": "Success",
    "data": {
      "url": "https://app.zapyd.com/kyc?kyc_id=977c8923-3818-4880-bfbf-65436635ea91"
    }
  }
  ```
</CodeGroup>

## 2. Send the user to the link

Open `url` in the browser, a new tab or a webview. When the user finishes, Zapyd sends them to your `redirect_url`. It's optional: without it, Zapyd uses the redirect URL set for your organization.

<Warning>
  Arriving at `redirect_url` doesn't mean the user passed KYC. Always wait for the `CUSTOMER` webhook, or read the customer's `status`.
</Warning>

If you embed the flow in a webview or an iframe, allow camera access. The selfie step needs it.

## 3. What the user does (India)

Indian users need **Aadhaar or a passport**, and a **PAN**. The flow runs three checks in order.

<Steps>
  <Step title="PAN">
    The user enters their name, date of birth and PAN. Zapyd checks that the PAN is valid, belongs to an individual, matches the name and date of birth, and is linked to an Aadhaar.
  </Step>

  <Step title="Identity document">
    **Aadhaar:** the user authenticates with an OTP through DigiLocker, so there's nothing to upload. **Passport:** the user uploads the front and back pages. Zapyd runs forgery detection and OCR, then matches the name and date of birth with the PAN.
  </Step>

  <Step title="Liveness and face match">
    The user takes a live selfie. Zapyd confirms it isn't a photo of a photo, then matches the face with the document.
  </Step>
</Steps>

When all three checks pass, the customer becomes `VERIFIED`.

## 4. Get the result

Most results arrive within minutes. Manual review can take up to 2 hours. Zapyd sends a `CUSTOMER` webhook:

```json theme={null}
{
  "type": "CUSTOMER",
  "event": "VERIFIED",
  "id": "075986f3-282b-4555-bfcd-fad973e32596",
  "timestamp": "2026-09-30T10:00:00Z",
  "metadata": {}
}
```

If you can't receive webhooks, poll [`GET /customer/{customer_id}`](/api-reference-exchange/endpoint/customer/\{customer_id}) no more than once a minute.

## 5. Handle a failure

On `FAILED`, read `metadata.failure_reason`, tell the user what went wrong, and generate a new link. Each customer has three attempts.

| Situation | What to do |
| - | - |
| User closed the flow early | Generate a new link and send them back |
| `FAILED`, attempts remaining | Explain the reason, then generate a new link |
| Three failures | The customer is blocked. Contact support with the `customer_id` |

## Test it in sandbox

You don't need to run the hosted flow in sandbox. Set the result with [Mock KYC Status](/api-reference-exchange/endpoint/kyc/mock-kyc-status), then check your webhook handler.
