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

# Keys and environments

> Work in Development and Production, create and manage site keys, API keys, and agent keys, and meet the requirements for going live.

The [BotShield Console](https://console.botshield.ai) is where you create the credentials your integration uses and where you move from testing to live traffic. This guide covers the two environments, the three kinds of key, which key belongs in which part of your system, and what the Console asks for before it lets you work in Production.

## Development and Production

Every gate, agent, and key belongs to one of two environments.

| | Development | Production |
| - | - | - |
| Purpose | Build and test. | Live traffic. |
| Site key prefix | `pk_test_…` (labelled `test`) | `pk_live_…` (labelled `live`) |
| API key prefix | `bs_dev_…` | `bs_production_…` |
| Billing | Not billed. | Counts toward your plan. |
| Rate limits | Low, sized for testing. | Higher. See [Rate limits](/api-reference/rate-limits). |
| Requirements | None. Available as soon as you sign up. | Verified business, active plan, and a console passkey. See [Production requirements](#production-requirements). |

Both environments use the same API base URL, `https://api.botshield.ai/operations`, and the same widget script. The key you send selects the environment, and a key works only with gates and agents from its own environment.

A gate is looked up in the environment of the key that calls it. Test and development keys (`pk_test_…`, `bs_dev_…`) reach Development gates. Live and production keys (`pk_live_…`, `bs_production_…`) reach Production gates. The same gate key (`scope`) can exist in both environments. The two are separate gates, each with its own gate type, verification mode, and status, and a key only ever reaches the one in its own environment. When that environment has no Active gate with the gate key, the call fails: the widget reports `botshield:failure` with reason `gate_not_found`, and `POST /sdk/create-verification-link` answers `statusCode` 400 with "not defined or not active".

### The environment toggle

The **Development | Production** toggle sits in the page header of the **BotShield Gate** and **Agents Ask** pages. It controls which gates and agents you see, and the environment of anything you create from that page. Your choice carries across pages and is remembered in your browser. It starts on Production.

<Warning>
  A gate's environment is fixed when you place it, and an agent's when you register it. You cannot move one between environments. Place the gate again in Production when you are ready, using the same key (`scope`) if you want your markup to stay the same.
</Warning>

Two areas are not filtered by the toggle. **Settings → Developer Tools** lists the keys for both environments together, each with an environment badge. **Analytics** covers all environments.

## Site keys

A site key is the **public** credential the BotShield widget uses in the browser. It goes in your HTML as the `site-key` attribute, so anyone can read it. What protects it is the list of **allowed origins**: BotShield accepts a request with a site key only when the browser's `Origin` matches that list.

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

  <Step title="Name it and pick the environment">
    Enter a name, for example "Meridian checkout", and choose `test` or `live`. Names must be unique within an environment.
  </Step>

  <Step title="Add allowed origins">
    Add every origin that will load the widget, then create the key. An origin is scheme plus host, with a port if you use one, and no path: `https://www.meridianairlines.example`.
  </Step>

  <Step title="Copy the public key">
    The key appears in the list as `pk_test_…` or `pk_live_…` and stays visible there, so you can come back for it.
  </Step>
</Steps>

### Allowed origins

| You enter | It matches |
| - | - |
| `https://www.meridianairlines.example` | That exact origin. |
| `https://*.meridianairlines.example` | Every subdomain, such as `https://book.meridianairlines.example`, and also `https://meridianairlines.example` itself. |

* Matching ignores case and a trailing slash.
* `test` keys also accept `http://localhost` and `http://127.0.0.1` on any port, so local development works without an entry.
* `live` keys accept only the origins you list, and must have at least one. The Console refuses to create a `live` key with an empty list, and refuses an edit that would remove its last origin.
* `test` keys may have an empty list. A `test` key with no origins is accepted from any origin, so give it origins too once it is used anywhere other than your own machine.
* A request with no `Origin` or `Referer` header is rejected when the key has origins, so a site key does not work from a server or from curl unless you send an `Origin` header.

<Warning>
  An origin list is what stops someone who copies your site key from using it on their own site. Keep the list on a `live` key tight, and prefer exact origins to wildcards.
</Warning>

### Edit origins or revoke

Use the pencil icon on a key to add or remove origins, then **Save origins**. Changes apply to new requests. A `live` key keeps at least one origin, so add the new origin before you remove the old one. Use the trash icon to revoke a key. A revoked site key stops working at once, and the widget on any page that still uses it fails. There is no rotate action for site keys. To replace one, create a new key, deploy it, then revoke the old key.

## API keys

An API key is the **secret** credential your server uses to call the API. It is never checked against an origin, so anyone who holds it can call the API as you.

<Steps>
  <Step title="Open API Keys">
    Go to **Settings → Developer Tools → API Keys**.
  </Step>

  <Step title="Create a key for one environment">
    Select **New Development Key** or **New Production Key**. You can hold several keys per environment, for example one per service.
  </Step>

  <Step title="Copy it now">
    The full key (`bs_dev_…` or `bs_production_…`) is shown once, in the green panel. Copy it into your secret manager. After you leave the page, the Console shows only a masked version.
  </Step>
</Steps>

Each key in the list shows its environment, a masked value, when it was created, and when it was last used.

| Action | What happens |
| - | - |
| **Rotate** | Issues a new secret for the same key and shows it once. The key keeps its settings, including Admin API access. The old secret stops working immediately, so have your release ready to take the new value. For a rotation with no downtime, create a second key, deploy it, then revoke the first. |
| **Revoke** | Disables the key permanently. Any service still using it gets `statusCode` 401. |
| **Admin API access** | Lets the key also read your organization's catalog of gates, agents, and site keys. It is read-only and is meant for platform integrations that sync that catalog, such as the [Salesforce package](/integrations/salesforce/install-and-setup). Leave it off for keys that only run verifications. |

### Organization ID

The API Keys tab also shows your **Organization ID** (`org_…`) with a **Copy** button. It is the value BotShield writes into the `organization_id` claim of every attestation token, and the `organization_id` that `GET /verification/status` returns. Store it next to your API key and compare it on your server before you trust a token or a status. See [Verify on your server](/gate/verify-on-your-server). The same value comes back from `POST /sdk/create-session` as `organization.id`. One Organization ID covers both environments.

## Agent keys

An agent key (`bs_agent_<Name>__<secret>`) is the secret credential for one Agents Ask agent in one environment. You receive it once, when you register the agent under **Agents Ask → Trusted Agents → Register Agent**.

| Action | What happens |
| - | - |
| **Rotate key** | Issues a new key for the same agent and shows it once. The Console asks you to confirm first, and for a Production agent it also asks for your console passkey. The old key stops working immediately, so have your agent's deployment ready to take the new value. The agent keeps its name, its Agent ID, its categories, and its linked humans. |
| **Revoke** | Disables the agent permanently. Calls with its key get `statusCode` 401. |

See [Register an agent](/agents-ask/register-an-agent) for the full walkthrough.

## Which key goes where

| Where the code runs | Credential | Used for |
| - | - | - |
| Browser (your page) | Site key `pk_…` | The `site-key` attribute of the BotShield widget. |
| Your server | API key `bs_dev_…` or `bs_production_…` | `POST /sdk/create-session`, `POST /sdk/revoke-verification`, `POST /sdk/logout`. |
| Your server | Grant token `bss_…` | `POST /sdk/create-verification-link`. You do not create this in the Console. `create-session` returns it, and it lives five minutes and works once. |
| Your server | No credential | `POST /sdk/verify-token` and `GET /verification/status`. |
| Your agent's server | Agent key `bs_agent_…` | Every Agents Ask operation. |
| Your webhook endpoint | Signing secret `whsec_…` | Verifying webhook deliveries. Copy it from **Settings → Developer Tools → Webhooks**. See [Webhooks overview](/webhooks/overview). |

Send API keys, grant tokens, and agent keys as `Authorization: Bearer <credential>`.

## Production requirements

Development is open from the moment you sign up. Production asks for three things.

<Steps>
  <Step title="Verify your business">
    The Console prompts you to verify your business with your company email. The check is automatic and takes a moment. It compares your email domain with your company website, so use a work address. Free email domains are not accepted.
  </Step>

  <Step title="Choose a plan">
    Pick a plan for the product you are taking live under **Settings → Billing → Plans**, or from the **Plan** tab on the BotShield Gate page.
  </Step>

  <Step title="Add a console passkey">
    Under **Settings → Profile → Passkeys**, select **Add passkey**. This passkey belongs to your Console login and is separate from the one in your BotShield app. Removing it does not affect your BotShield app.
  </Step>
</Steps>

### Passkey confirmation

The Console asks you to confirm with your console passkey when you do any of these in Production:

* Place a gate
* Activate a gate
* Register an agent
* Rotate an agent's key

A confirmation is good for **five minutes**. After that, the next Production action asks again. If you remove your last passkey, these actions lock until you add one.

Activating a Production gate checks all three requirements, in this order: verified business, active plan, passkey. If one is missing, the Console tells you which and the gate stays a Draft.

## Team access

Invite teammates under **Settings → Team**. Every Console member is an **admin** today: invitations are sent with the admin role, and admins can do everything on this page. There are no limited or read-only roles yet, so invite only people who should be able to create and revoke keys.

Each admin confirms Production actions with their own console passkey. A passkey is personal and is not shared across the team.

## Analytics

The **Analytics** page reports on both products across all environments.

| Section | Tiles |
| - | - |
| BotShield Gate | Verifications, Human verified, Unavailable, Verified rate |
| Age Gate | Shown when you have Age Gate verifications. |
| Agents Ask | Resolutions, Confirmed, Denied, Confirm rate |

Verifications your server creates with an API key count in the same places as verifications the widget starts: the gate's **Overview** metrics and the **Analytics** page.

Open a gate from the BotShield Gate page for its own **Overview**, **Verification Logs** (Request ID, Status, Duration, Created), and **Activity Logs**. The log view exports to CSV. Use the Request ID to match a row to the `request_id` in your own records. Logs contain no personal data about the human.

## Handle keys safely

* Keep API keys and agent keys in a secret manager or environment variables. Never commit them, and never send them to the browser or a mobile app.
* Use Development keys on laptops and in CI. Give Production keys only to production services.
* Create one API key per service, so you can revoke one without touching the rest.
* Rotate or revoke a key as soon as someone who had it leaves, or when it may have appeared in a log, a ticket, or a chat.
* Do not log `Authorization` headers. If you turn on the SDK's debug logger, keep it out of production.
* Treat a site key as public, and keep its allowed origins tight. Prefer exact origins to wildcards.
* Check **Last used** on the API Keys tab from time to time and revoke keys nobody uses.

## Next steps

<CardGroup cols={2}>
  <Card title="Place a gate" icon="shield-check" href="/gate/place-a-gate">
    Create a gate and get its key for the `scope` attribute.
  </Card>

  <Card title="Register an agent" icon="robot" href="/agents-ask/register-an-agent">
    Get an agent key for Agents Ask.
  </Card>

  <Card title="Webhooks overview" icon="webhook" href="/webhooks/overview">
    Add an endpoint and copy its signing secret.
  </Card>

  <Card title="API overview" icon="code" href="/api-reference/overview">
    Use your keys against the API.
  </Card>
</CardGroup>
