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

# Place a gate

> Create a site key, place a gate in the BotShield Console, activate it, and copy the embed snippet.

You place and manage gates in the [BotShield Console](https://console.botshield.ai). Placing a gate creates a **Draft**. The gate starts answering verifications when you **Activate** it. This page walks through the whole path, from the first key to a live gate.

<Note>
  Check the **Development | Production** toggle in the page header before you start. Keys and gates belong to one environment, and a gate's environment is fixed when you place it. Start in **Development**: it is not billed and has no business requirements.
</Note>

## Create a site key

The widget authenticates with a **site key**. It is public, so it is locked to the origins you list.

<Steps>
  <Step title="Open Site Keys">
    Go to **Settings → Developer Tools** and select the **Site Keys** tab. Select **New Site Key**.
  </Step>

  <Step title="Name the key and pick an environment">
    Enter a **Name**, for example "Production checkout". Under **Environment**, choose **test** for Development gates or **live** for Production gates. A test key starts with `pk_test_` and a live key starts with `pk_live_`.
  </Step>

  <Step title="Add allowed origins">
    Under **Allowed Origins**, add each origin that will host the widget, for example `https://www.meridianairlines.com`. Origins are matched exactly. Use `https://*.meridianairlines.com` to allow every subdomain.
  </Step>

  <Step title="Create">
    Select **Create Site Key**. The key appears in the list with its origins. You can edit the origins or revoke the key later from the same list.
  </Step>
</Steps>

<Warning>
  A **live** site key must have at least one allowed origin. The Console rejects a live key that is created or saved with an empty list. A **test** key can have an empty list, and a key with no allowed origins accepts requests from any origin. Test keys also accept `localhost` and `127.0.0.1` without listing them.
</Warning>

If you plan to [verify on your server](/gate/verify-on-your-server) or run the server-to-server flow, also create an API key on the **API Keys** tab. The same tab shows your **Organization ID** with a **Copy** button. It is the value in the `organization_id` claim of every verification token, so keep it in your server configuration. See [Keys and environments](/console/keys-and-environments).

## Place the gate

<Steps>
  <Step title="Open BotShield Gate">
    Select **BotShield Gate** in the sidebar. The **Deployments** tab lists your gates for the environment selected in the header. Select **Place a gate**.
  </Step>

  <Step title="Fill in the modal">
    The modal reads "Name it and pick a verification mode. You'll configure the rest and activate on the next screen."

    | Field | What to enter |
    | - | - |
    | **Gate name** | A label for your team. Placeholder: "e.g. Gate at Checkout". |
    | **Key** | The identifier you pass as `scope`. It fills in from the name until you edit it. Letters, numbers, `_`, `.` and `-` are kept; anything else becomes `_`. The helper line shows how it will be used: `scope="checkout"` in the SDK, case-sensitive, with the environment. |
    | **Gate type** | **Human**: "Is a real human here?" or **Age**: "Is this human over 13, 18 or 21?" |
    | **Verify over** (Age only) | **13+**, **18+** or **21+**. The default is 21+. The caption reads "Positive-only: Over 21 Verified or Unavailable. Never a date of birth." |
    | **Verification mode** | **Recent Presence**: "Returning humans pass instantly — within their earned TTL" or **Live**: "New biometric every time". An Age Gate is locked to Live: "Age Gate always runs a live check — the age signal is read on the phone during the passkey ceremony." |
  </Step>

  <Step title="Confirm with your passkey (Production only)">
    In Production the modal shows a **Passkey** badge: "Placing a gate is sealed with your passkey — only a proven human places a gate." Select **Place gate** and confirm with your Console passkey when prompted. In Development there is no passkey step.
  </Step>

  <Step title="Check the key">
    The gate opens in a detail panel as a **Draft**. Its key is shown under the name. If the key you asked for was already taken, BotShield adds a suffix such as `-2`, so copy the key from this panel, not from memory.
  </Step>
</Steps>

You can rename the gate, switch the verification mode, and change an Age Gate's threshold later from the gate's **Configuration** card. The gate type and the environment do not change after placement.

A key is unique within one environment. You can place a gate with the same key in Development and in Production. They are two independent gates with their own settings, and BotShield uses the one in the environment of the credential that calls it: `pk_test_` and `bs_dev_` keys reach Development gates, `pk_live_` and `bs_production_` keys reach Production gates.

## Draft, Active, Archived

| State | How you get there | What happens at runtime |
| - | - | - |
| **Draft** | **Place a gate** | The gate does not answer. The widget shows "Unavailable" and fires `botshield:failure` with reason `gate_not_active`. `create-verification-link` returns a `400` error saying the scope is not defined or not active. |
| **Active** | **Activate** on a Draft | The gate answers verifications. Production verifications are metered; Development verifications are not billed. |
| **Archived** | **Deactivate** in the gate panel, or **Close deployment** in the list menu | The gate stops answering, exactly like a Draft. Its logs stay available. |

<Warning>
  Archiving is permanent. An archived gate cannot be activated again; activation returns a `409` error. To bring a placement back, place a new gate and check the key it was given.
</Warning>

To activate, open the Draft and select **Activate** in the header, or **Activate →** in the **Next steps** list. To archive an active gate, select **Deactivate**, then **Confirm** when the panel asks "Stop answering verifications?".

## Production requirements

A Development gate activates with no checks. A Production gate activates only when all three of these are true, checked in this order:

1. **Your business is verified.** Select **Verify Business** on the BotShield Gate page and use a company email address on your company's domain. Verification is automatic. Personal email domains such as Gmail or Outlook are declined.
2. **You have an active plan.** Choose one on the **Plan** tab.
3. **You confirmed with your Console passkey in the last 5 minutes.** Add a passkey under **Settings → Profile → Passkeys** if you do not have one. The Console prompts you when a fresh confirmation is needed.

If a requirement is missing, **Activate** fails with one of these codes and the Console shows the message:

| Code | Message | Fix |
| - | - | - |
| `org_not_verified` | Business verification required before activating a production deployment. | Complete **Verify Business**. |
| `no_active_plan` | An active plan is required before activating a production deployment. | Choose a plan on the **Plan** tab. |
| `passkey_required` | A console passkey is required for production. Add one under Settings → Profile → Passkeys, then try again. | Add a Console passkey. |
| `passkey_stepup_required` | Confirm with your console passkey to continue — the confirmation must be recent. | Confirm with your passkey, then select **Activate** again. |

Placing a Production gate can also return the two passkey codes.

## The embed snippet

The gate's **Integration** card shows the site key for the gate's environment, a link to its allowed origins, and a snippet with a **Copy** button. The snippet is ready to paste: it carries the site key, the gate key as `scope`, and `scan-mode="modal"`, which names the widget's QR code and mobile hand-off flow.

```html theme={null}
<!-- Load BotShield SDK -->
<script src="https://cdn.botshield.ai/sdk.js"></script>

<!-- Render the verification widget -->
<botshield-verify
  site-key="pk_live_…"
  scope="checkout"
  scan-mode="modal"
  onsuccess="onBotShieldSuccess"
  onfailure="onBotShieldFailure"
></botshield-verify>

<script>
  function onBotShieldSuccess({ token, request_id }) {
    // Send the token (or the request_id when token is null) to your backend
    // and validate it there before you trust it.
  }
  function onBotShieldFailure({ reason }) {
    console.error('BotShield verification failed:', reason);
  }
</script>
```

If the card shows `pk_live_…` or `pk_test_…` as a placeholder, you have no site key in that environment yet. [Create one](#create-a-site-key) first. See [Web component](/gate/web-component) for every attribute and event.

## The gate detail panel

Select a gate in the **Deployments** list to open its panel. A Draft shows only **Overview**. Active and Archived gates show three tabs.

<Tabs>
  <Tab title="Overview">
    * A date range (**Last 7 days**, **Last 30 days**, **Last 90 days**) and **Export CSV** for the summary.
    * Metric tiles: **Total attestations**, **Human Verified**, **BotShield ID Active** (verifications that passed on Recent Presence without a phone step) and **Human Unavailable**. An Age Gate shows **Over N Verified** and **Age Unavailable** as well.
    * **Configuration**: gate type, age threshold (Age Gate) and verification mode. Changes save automatically.
    * **Health**: last attestation, last webhook sent, error rate, BotShield ID adoption and Unavailable rate.
    * **Integration**: site key, allowed origins and the embed snippet.
    * **Next steps**: place, activate, then test in the Sandbox.
  </Tab>

  <Tab title="Verification Logs">
    One row per verification, 25 per page, with the columns **Request ID**, **Status**, **Duration** and **Created**. Filter by **All**, **Verified**, **Failed**, **Blocked**, **Pending**, **Expired** or **Prechecks**. On an Age Gate, each row also carries an age label: **Over N Verified** or **Age Unavailable**.

    **Export CSV** downloads the rows on screen with the columns Request ID, Status, Age, Age Threshold, Age Source, Duration, Created and Error. Use the **Request ID** to match a row to the `request_id` your code received.
  </Tab>

  <Tab title="Activity Logs">
    The configuration history for this gate: who placed it, activated it, changed its mode or archived it. Columns are **Time Stamp**, **Team Member**, **Event**, **Details** and **Audit ID**. Search the list, or select **Export CSV**.
  </Tab>
</Tabs>

## Next steps

<CardGroup cols={2}>
  <Card title="Web component" icon="code" href="/gate/web-component">
    Put the widget on your page.
  </Card>

  <Card title="Verify on your server" icon="server" href="/gate/verify-on-your-server">
    Check the result before you trust it.
  </Card>

  <Card title="Testing" icon="flask" href="/gate/testing">
    Try the gate in the Console Sandbox.
  </Card>

  <Card title="Keys and environments" icon="key" href="/console/keys-and-environments">
    Site keys, API keys and how the two environments differ.
  </Card>
</CardGroup>
