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

# The privacy boundary

> A field-by-field list of what BotShield sends to partners and what it never sends.

BotShield tells you *that* a user is human, never *who* they are. Results cross to you. Identity does not. This page lists, surface by surface, exactly what you receive, so you can describe the integration accurately to your own privacy and security reviewers.

## What you never receive

None of the surfaces on this page sends you any of the following:

* The human's name, email address, or phone number.
* Biometric data of any kind. The biometric check happens on the human's own device. BotShield does not send you a face, a fingerprint, or a template.
* The human's device details or location.
* A score, a confidence value, or a "bot" verdict.
* A date of birth, an age number, or an "underage" result.
* An identifier that lets you match a human with another partner's records.

You receive no personal data from BotShield. The one thing to watch is data you send yourself: whatever you put in `metadata` comes back to you in gate webhooks, so keep personal data out of it.

## BotShield Gate

### Widget events

| Event | You receive |
| - | - |
| `botshield:success` after a confirmation on the phone | `token`, `request_id`, `score`, and `via: "ceremony"`. `token` is the attestation token (a signed JWT) or `null`. It is never a request ID. `score` is always `null`. The shape is the same on desktop and on mobile. |
| `botshield:success` on an instant pass | `token: null`, `event_id`, `request_id`, and `via: "precheck"` |
| `botshield:failure` | `reason`. A configuration failure, such as `origin_not_allowed`, `invalid_site_key`, or `gate_not_found`, also carries `message` and `status_code`. A `blocked` result also carries `event_id`, `request_id`, and `result_state`. |
| `botshield:cancel` | `request_id`. Fires when the person closes the modal before finishing. |
| `botshield:census-status` | `event_id`, `request_id`, `verdict`, `result_state` |
| `botshield:inline-passkey` (Beta) | `status`, `reason`, `request_id` |

No widget event carries an age field, on a Human Gate or an Age Gate.

(`census` is the API's name for BotShield Gate.)

### Attestation token claims

The token from `botshield:success` is an ES256 JWT that lives 120 seconds. `POST /sdk/verify-token` returns these claims:

| Claim | What it is |
| - | - |
| `request_id` | The verification request. Your correlation key. |
| `verified` | `true` |
| `organization_id` | Your organization. |
| `timestamp` | When the human confirmed. |
| `nonce` | A unique value for this token. |
| `issued_at`, `expires_at` | The token's lifetime, in Unix seconds. |

The token has no `sub` claim. It describes the event, not the person. On a met Age Gate the JWT also carries `age_over`. A token for a Human Gate never carries `age_over`.

### Verification status

`GET /verification/status` returns:

| Field | What it is |
| - | - |
| `found`, `status` | Whether the request exists and where it stands. |
| `request_id`, `organization_id`, `scope` | The request, your organization, and the gate key. |
| `created_at`, `expires_at`, `verified_at` | Timestamps. |
| `verification_token`, `signed_token` | The attestation token once the request completes, otherwise `null`. |
| `error_message` | A short description when the request failed. |
| `sdk_type`, `metadata` | Request context. `metadata` holds `scope`, `sdk_type`, `environment`, `return_url`, and `parent_request_id`. |
| `presence_address` | Reserved. `null` for BotShield Gate. |
| `gate_type`, `age_threshold`, `age_verdict`, `age_source` | Age Gate fields. See below. On a Human Gate, `gate_type` is `human` and the other three are `null`. |

### Gate webhooks

| Event | You receive |
| - | - |
| `gate.human_verified` | `type`, `event_id`, `request_id`, `verified_at`, `environment`, `product`, `metadata` |
| `gate.unavailable` | `type`, `event_id`, `request_id`, `environment`, `product`, `metadata`, and either `failed_at` with `reason` and `error_message`, or `expired_at` |

`event_id` is the same value as `request_id`. `environment` is `development` or `production`. `product` is `census` for a request made against a gate. `metadata` holds only the keys you supplied when you created the request. BotShield's own request context is not included, and the key is left out when you supplied nothing. `reason` is one of `user_denied`, `device_lock_required`, `platform_declined`, or `internal_error`: it describes why the confirmation did not happen, not who the person is. Gate webhooks carry no age result, on either gate type.

### Your user reference

If you send `platform-user-ref` (or `partner_user_ref` on the server API), BotShield stores a hash of it that is specific to your organization. It is not returned to you on any of these surfaces, and you never receive a BotShield identifier for the human on the Gate rail. See [BotShield ID](/concepts/botshield-id).

## Age Gate

Age Gate (Beta) is positive-only. It can say that a human is over your threshold. It never says anything else about their age.

Age data belongs to Age Gates only. A Human Gate never returns an age result: its token has no `age_over` claim, and `age_verdict` and `age_source` stay `null` on `GET /verification/status`, whatever the human's phone is able to report.

| You receive | Values |
| - | - |
| `gate_type` | `age` |
| `age_threshold` | The threshold you set on the gate: `13`, `18`, or `21` |
| `age_verdict` | `over_13`, `over_18`, `over_21`, or `unavailable` |
| `age_source` | Which platform age signal the phone used |
| `age_over` (token claim) | Present only when a threshold was met |

`unavailable` means BotShield could not confirm the threshold. It does not mean the human is under it. There is no "under" value, no date of birth, and no age number on any surface. See [Age Gate](/gate/age-gate).

## Agents Ask

Agents Ask needs to address the same human more than once, so it uses an **opaque ID**. The opaque ID starts with `OP_` and is pairwise: it is unique to one human and one agent. Two agents that are linked to the same human hold different opaque IDs, so the IDs cannot be matched to each other or to any Gate result.

### Proof of Resolution claims

A Proof of Resolution is an ES256 JWT that lives 24 hours.

| Claim | What it is |
| - | - |
| `iss` | `https://api.botshield.ai` |
| `sub` | The human's opaque ID for your agent (`OP_…`). |
| `aud` | Your agent's ID. Check it. |
| `jti` | The `request_id` you sent when you proposed the action. |
| `verdict` | `approve` or `denied` |
| `action` | The action as the human saw it: `category`, `description`, and, where present, `trusted_account_id`, `total`, `total_currency`. |
| `iat`, `exp`, `kid` | Issue time, expiry, and signing key ID. |
| `ceremony_id` | Optional. Shared by actions the human resolved in one confirmation. |

See [Proof of Resolution](/agents-ask/proof-of-resolution).

### Agents Ask webhooks

| Event | You receive |
| - | - |
| `agents_ask.card.proposed` | `request_id`, `card_id`, `agent_id`, `agent_name`, `category`, `summary_title`, `ttl_at`, `source` |
| `agents_ask.resolution.confirmed`, `agents_ask.resolution.denied` | `request_id`, `resolution_id`, `outcome`, `proof_token` (the Proof of Resolution), and `metadata` with `card_id`, `ceremony_id`, `agent_id`, `agent_name` |
| `agents_ask.resolution.expired` | `request_id`, `card_id`, `outcome`, `metadata`. An expired action has no Proof of Resolution. |

## Summary

| Surface | Identifies the human to you as | Personal data |
| - | - | - |
| Widget events | Nothing | None |
| Attestation token | Nothing | None |
| `GET /verification/status` | Nothing | None |
| Gate webhooks | Nothing | None |
| Age Gate fields | Nothing | None. A positive-only threshold result. |
| Proof of Resolution and Agents Ask webhooks | A pairwise opaque ID, unique to your agent | None |

<CardGroup cols={2}>
  <Card title="BotShield ID" icon="id-badge" href="/concepts/botshield-id">
    How a returning human is recognized without being identified.
  </Card>

  <Card title="Result states" icon="circle-check" href="/concepts/result-states">
    Verified and Unavailable.
  </Card>

  <Card title="Webhook events" icon="bell" href="/webhooks/events">
    Full payloads for every event.
  </Card>

  <Card title="Proof of Resolution" icon="file-signature" href="/agents-ask/proof-of-resolution">
    Verify the signed result of an agent action.
  </Card>
</CardGroup>
