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

# BotShield ID

> A BotShield ID is a human's standing proof-of-human, and it lets returning users pass your gates faster without you ever learning who they are.

A human sets up the BotShield app once, on their own phone, and secures it with a passkey. That is their **BotShield ID**: a standing proof-of-human that belongs to them. The same BotShield ID works at every partner. You do not issue it, store it, or see it. You see results.

## What it changes for your users

The first time a person meets a BotShield gate, they create a passkey — at [app.botshield.ai](https://app.botshield.ai) (public beta, no download) or in the BotShield app — and confirm with their device biometric. After that, they already have a BotShield ID, and every later gate is quicker, on your site and on any other platform's.

| The user | What they do at your gate |
| - | - |
| Has never used BotShield | Scans the QR code, sets up the app, and confirms. |
| Has a BotShield ID, new to your site | Scans the QR code (or taps through on their phone) and confirms. No setup. |
| Has a BotShield ID and you have recognized them before | Gets a push on their phone instead of scanning. On a Recent Presence gate they may pass instantly. |

## Verification modes

You choose a verification mode when you place a gate. It decides how much a BotShield ID can do on its own.

| Mode | What it asks of the human | Use it for |
| - | - | - |
| **Recent Presence** | A recognized returning human whose presence is recent passes instantly, with no prompt. Everyone else confirms on their phone. | High-traffic actions where friction costs you: browsing a sale, joining a waitlist, adding to a cart. |
| **Live** | A new biometric confirmation every time, for every human. | Actions where you need a human at this moment: checkout, account recovery, a payout. |

An Age Gate always uses Live. It always asks for a new confirmation.

BotShield decides whether a human's presence is recent enough. The rule is not exposed and you do not configure it. If you need a guarantee that a human confirmed at this moment, use Live.

On a Recent Presence gate, an instant pass reaches your page as `botshield:success` with `token: null` and `via: "precheck"`. The result state is Verified either way. To confirm an instant pass on your server, call `GET /verification/status` with the `request_id` straight away. It reports `status: "pass"` rather than `"completed"`, and the record reads `"expired"` 60 seconds after the check. If it has already expired, ask the user to verify again. The [Quick start](/quick-start) has the code.

## Recognizing a returning user

BotShield does not know that the visitor on your page is someone it has seen before unless you say which of *your* users they are. You do that with a reference of your own.

<Tabs>
  <Tab title="Widget">
    Set `platform-user-ref` to your own stable ID for the signed-in user.

    ```html theme={null}
    <botshield-verify
      site-key="pk_live_…"
      scope="checkout"
      scan-mode="modal"
      platform-user-ref="mer_user_48213"
    ></botshield-verify>
    ```

    `link-on-verify` defaults to `true`. Set `link-on-verify="false"` to verify without linking.
  </Tab>

  <Tab title="Server API">
    Send `partner_user_ref` to `POST /sdk/create-verification-link`. `link_on_verify` defaults to `true`.

    ```json theme={null}
    {
      "scope": "checkout",
      "partner_user_ref": "mer_user_48213",
      "link_on_verify": true
    }
    ```

    The response includes `pushed_to_devices`. A value above `0` means BotShield recognized the reference and sent a push to the human's phone. See [Verify on your server](/gate/verify-on-your-server).
  </Tab>
</Tabs>

Here is what happens with that reference:

<Steps>
  <Step title="First verification">
    The human confirms on their phone. Because linking is on, BotShield remembers that this reference, at your organization, belongs to that BotShield ID.
  </Step>

  <Step title="Later verifications">
    You send the same reference. BotShield recognizes it and sends a push to the human's phone. The widget's modal reads "Check your phone" and still shows the QR code as a fallback. On a Recent Presence gate, a human whose presence is recent skips the prompt entirely.
  </Step>
</Steps>

Without a reference, every visitor is new to BotShield. They always get the QR code or deep link, and a Recent Presence gate never passes them instantly.

## What stays private

* **Your reference is hashed.** BotShield stores a hash of `platform-user-ref` that is specific to your organization, not the raw value. It is never returned to you or shown to anyone else.
* **You never receive a BotShield identifier on the Gate rail.** No widget event, token claim, status response, or gate webhook carries one. You correlate results with your own `request_id` and your own reference.
* **Nothing links your users across partners.** Another partner using the same human's BotShield ID learns nothing about your site, and you learn nothing about theirs.

<Tip>
  Use an opaque internal ID as the reference. Do not use an email address, phone number, or name. BotShield does not need it, and an opaque ID keeps personal data out of the request.
</Tip>

Agents Ask identifies a linked human differently, with an opaque ID that is unique to each agent. See [The privacy boundary](/concepts/privacy-boundary).

<CardGroup cols={2}>
  <Card title="Place a gate" icon="location-dot" href="/gate/place-a-gate">
    Choose the gate type and verification mode.
  </Card>

  <Card title="Web component" icon="code" href="/gate/web-component">
    `platform-user-ref`, `link-on-verify`, and every other attribute.
  </Card>

  <Card title="Result states" icon="circle-check" href="/concepts/result-states">
    Verified and Unavailable, and how to design for both.
  </Card>

  <Card title="The privacy boundary" icon="user-shield" href="/concepts/privacy-boundary">
    What crosses to you and what never does.
  </Card>
</CardGroup>
