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

> Put a gate in front of any action and get back one answer: a real human is here, or the check is unavailable.

BotShield Gate checks for a real human at the moment it matters: a sign-up, a checkout, a post, an age-restricted page. The user confirms with their device biometric (a passkey) in the BotShield app, and you receive a result. BotShield tells you *that* the user is human, never *who* they are. You receive no personal data.

## Two gate types

<CardGroup cols={2}>
  <Card title="Human Gate" icon="user-check">
    **"Is a real human here?"** The result is **Verified** or **Unavailable**.
  </Card>

  <Card title="Age Gate (Beta)" icon="calendar-check">
    **"Is this human over 13, 18 or 21?"** The result is **Over N Verified** or **Unavailable**. It never returns a date of birth, an age, or an "underage" answer. See [Age Gate](/gate/age-gate).
  </Card>
</CardGroup>

Both types use the same integration. There are only two result states, and your code should branch on exactly those two. See [Result states](/concepts/result-states).

<Tip>
  **See it before you build it.** The [BotShield Demos](https://demo.botshield.ai) run both gate types on production keys: **Ticketz** puts a Human Gate on a checkout (with the inline passkey beta), and **Vapez** puts an Age Gate on a storefront door. Open one on your laptop and confirm on your phone.
</Tip>

| Display name | Wire value | What to do |
| - | - | - |
| **Verified** | `human_verified` | Let the action continue. |
| **Unavailable** | `unavailable` | Do not continue on this proof. Offer a retry or your fallback path. |

**Unavailable** is not an accusation. It means BotShield could not confirm a human this time: the request expired, the user declined, or the check could not run.

## What a gate is

A **gate** is one placement of BotShield Gate in your product. You place gates in the [BotShield Console](https://console.botshield.ai), and each gate has:

| Property | What it is |
| - | - |
| **Gate name** | A label for your team, for example "Gate at Checkout". |
| **Key** | A short, case-sensitive identifier such as `checkout`. You pass it as `scope` in the widget and the API. (`scope` is the API's name for the gate key.) |
| **Gate type** | **Human** or **Age**. An Age Gate also has a threshold: 13, 18 or 21. |
| **Verification mode** | **Recent Presence** or **Live**. See below. |
| **Environment** | **Development** or **Production**. It is fixed when you place the gate. |

### Verification mode

| Mode | Behavior | Use it for |
| - | - | - |
| **Recent Presence** | A returning human you have identified with your own user reference passes instantly, with no phone step, while their earlier proof is still current. Everyone else runs the live check. | Frequent, lower-stakes actions: sign-in, posting, browsing a queue. |
| **Live** | Every request runs a new biometric confirmation on the user's phone. | High-stakes actions: checkout on a limited release, payouts, account recovery. |

An Age Gate always runs **Live**, because the age signal is read on the phone during the confirmation.

<Note>
  Recent Presence only applies when you tell BotShield which of *your* users is asking, with `platform-user-ref` on the widget or `partner_user_ref` in the API. BotShield stores that reference only as a one-way hash. Without it, every request runs the live check.
</Note>

## Where to use a gate

Use a gate anywhere you would put a CAPTCHA, and anywhere a CAPTCHA has stopped being enough:

* **Sign-up and sign-in**, to stop scripted account creation.
* **Checkout**, for limited drops, tickets and high-demand inventory.
* **Posting, voting and reviews**, to keep automated content out.
* **Age-restricted access**, with an Age Gate.
* **Sensitive account changes**, such as payout details or recovery.

A gate covers one action. Place separate gates for separate actions so you can choose the mode, read the logs and archive each one independently.

## Two ways to integrate

<CardGroup cols={2}>
  <Card title="Web component" icon="code" href="/gate/web-component">
    Add a script tag and a `<botshield-verify>` element to your page. The widget draws the **Verify Human** button, shows the QR code or opens the app, and hands your page the result. Then you [verify it on your server](/gate/verify-on-your-server).
  </Card>

  <Card title="Server-to-server" icon="server" href="/gate/verify-on-your-server">
    Your server creates the verification request with your API key, you show the link in your own UI, and you learn the result by webhook or by polling. Use this for native apps, custom UI and back-office flows.
  </Card>
</CardGroup>

| | Web component | Server-to-server |
| - | - | - |
| Credential | Site key (`pk_test_…` / `pk_live_…`), public and origin-locked | API key (`bs_dev_…` / `bs_production_…`), secret, server only |
| UI | BotShield's button and QR modal | Yours |
| Recent Presence fast path | Built in | Not available; every request runs the live check |
| Result | DOM event on your page, then a server-side check | Webhook or `GET /verification/status` |

## How the widget flow works

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant P as Your page
    participant W as BotShield widget
    participant A as BotShield API
    participant Ph as User's phone (BotShield app)
    participant S as Your server
    U->>W: Clicks the widget
    W->>A: Pre-check (site key, gate key, your user reference)
    alt Recent Presence gate and this user verified recently
        A-->>W: human_verified
        W-->>P: botshield:success (token null, via precheck)
    else Live gate, Age Gate, or no recent presence
        A-->>W: Confirmation required
        W->>U: Shows a QR code (desktop) or opens the app (mobile)
        U->>Ph: Confirms with device biometric
        Ph->>A: Completes the request
        A-->>W: Completed, with a signed token
        W-->>P: botshield:success (token, via ceremony)
    end
    P->>S: Sends the token or request_id with the action
    S->>A: Verifies the token or reads the request status
    A-->>S: Result
```

The event on your page is a convenience for your UI. The decision belongs on your server: always check the result server-side before you let the action through.

## Next steps

<CardGroup cols={2}>
  <Card title="Place a gate" icon="location-dot" href="/gate/place-a-gate">
    Create a site key, place a gate and activate it in the Console.
  </Card>

  <Card title="Web component" icon="code" href="/gate/web-component">
    The full `<botshield-verify>` reference.
  </Card>

  <Card title="Verify on your server" icon="server" href="/gate/verify-on-your-server">
    Check tokens, or run the whole flow server-to-server.
  </Card>

  <Card title="Testing" icon="flask" href="/gate/testing">
    Development keys, the Console Sandbox and a launch checklist.
  </Card>

  <Card title="Live demos" icon="play" href="https://demo.botshield.ai">
    Ticketz (Human Gate at checkout) and Vapez (Age Gate at the door), running on production.
  </Card>
</CardGroup>
