botshield-sdk is the typed TypeScript client for the BotShield API. Use it on your server to confirm BotShield Gate results, and in your agent to ask a human to Confirm or Deny an action. It covers the same operations as the HTTP API and adds types, optional retries, timeouts, and a built-in MCP server. This page describes version 2.0.1.
Install
Requirements
- A runtime with ECMAScript 2020, the Fetch API, and Web Streams: Node.js 18 or 20 LTS, Bun 1 or later, Deno 1.39, or an evergreen browser. The built-in MCP server needs Node.js 20 or later.
- The package ships ESM and CommonJS builds. Its runtime dependencies are
zodand@modelcontextprotocol/sdk. - For TypeScript, use
"target": "es2020"or higher and include"dom"inlibso thefetchtypes resolve.
Create the client
Authentication
The two products authenticate differently. BotShield Gate: per call. Gate methods take a security object as their first argument. This lets one client use an API key forcreateSession and then the grant token for createVerificationLink.
Agents Ask: on the client. Set the agent key once and the
actions methods use it.
security type also lists agentKeyAuth1, and the security types of verifyToken, getStatus and getPartnerConfig list apiKeyAuth1. They are duplicates produced by the code generator. Ignore them.
Namespaces and methods
(census is the SDK’s name for BotShield Gate.)
Every method also accepts a final
options argument for per-call timeoutMs, retries, retryCodes, serverURL, and standard fetch options such as signal.
Not in 2.0.1: the link operations (POST /agent/bind-session, GET /agent/check-binding) and the Age Gate response fields (gate_type, age_threshold, age_verdict, age_source). The SDK drops fields it has no type for, so call the HTTP API directly for those. See Link a human and Age Gate.
The response envelope
The SDK returns the API’s envelope as it is. It does not unwrap it and it does not throw on handler errors.- Request and response fields are camelCase in the SDK (
anchorGrantToken,requestId). The SDK converts them to and from the API’s snake_case. Timestamps arrive asDateobjects. - Read the result from
result.data.data. Forverification.getStatusandcensus.logout, read it fromresult.data. - Check
result.data.errorfirst. A rejected request resolves normally withresult.data.errorset to{ message, statusCode, code? }.
BotShield Gate: confirm a widget result
Most integrations place the web component on the page and confirm the result on the server. Your page sends therequest_id and token from the widget’s success event to your server, and your server runs this check before it unlocks the action.
POST /sdk/verify-token is open and the token has no audience claim, so the comparison of organizationId and requestId is what ties the token to your request. Do both.BotShield Gate: create a request from your server
Use this flow when your server, not the widget, starts the verification, for example in a native app or a server-rendered step. The status can becompleted or pass. Accept both.
partnerUserRef, or the partnerUserId from createSession when you send no reference) has a pending, unexpired request for the same gate. A completed or failed request never blocks a new one. revokeVerification ends exactly those pending requests and reports the number in revokedCount.
expiresAt is the request’s own expiry, five minutes after it was created. It is the same instant verification.getStatus returns as expiresAt, so it is the right deadline for your polling loop.
The gate is looked up in your API key’s environment: a bs_dev_… key reaches the Development gate named checkout, and a bs_production_… key reaches the Production one. Requests you create this way count in the gate’s Overview and in Analytics in the Console, the same as requests the widget starts.
Do not send userEmail. It is deprecated and ignored. webhookUrl is deprecated and has no effect, because webhooks are configured in the Console. See Webhooks overview. In the response, qrCodeUrl is deprecated and does not resolve to an image. Draw your own QR code from webUrl.
Agents Ask: propose an action and wait
timeoutMs above the long-poll window, or pass { timeoutMs: 35_000 } as the options argument on checkActionStatus. Verify resolutionJwt before your agent acts on it. See Proof of Resolution.
Standalone functions
Every method is also exported as a standalone function that takes aBotShieldCore client. Bundlers can tree-shake everything you do not import, which matters in serverless and edge bundles. Standalone functions return a Result instead of throwing.
<namespace><Method>: censusCreateSession, censusCreateVerificationLink, censusVerifyToken, censusRevokeVerification, censusLogout, verificationGetStatus, actionsProposeAction, actionsCheckActionStatus, actionsCancelAction. Each lives in botshield-sdk/funcs/<kebab-case-name>.js.
Errors
There are two kinds of failure, and you need to handle both. Handler errors do not throw. They arrive asresult.data.error with HTTP 200. This covers 401, 403, 404, 409, 422 and the other codes listed in Errors.
HTTP and transport errors throw. Import the classes from botshield-sdk/models/errors:
Retries and timeouts
Retries are off by default. Turn them on for the whole client withretryConfig, or for one call with the retries option. Intervals are in milliseconds.
The example in Errors shows both forms. Two things to know:
- The retry codes do not include 403, so a rate-limited call is not retried. Catch it and wait as described in Rate limits.
- Retries act on HTTP status only. A handler error inside an HTTP 200 response is never retried.
timeoutMs works the same way: set it on the client, or per call in the options argument. A call that times out throws RequestTimeoutError.
Run the SDK as an MCP server
The package includes a Model Context Protocol server that exposes the Agents Ask methods as tools for an MCP-capable agent host. It needs Node.js 20 or later.
Pass
--server-url. Without it the server targets the local development address, the same default as the client. The --agent-key-auth value needs the Bearer prefix. Run npx -y --package botshield-sdk -- mcp start --help for all flags. The default transport is stdio.
BotShield also hosts an MCP server that needs no local process and adds the link tools. See MCP server.
Error codes
result.data.error.code is a string, present when the API sets one. For the operations this SDK calls, the documented codes are ttl_below_floor and ttl_above_ceiling on actions.proposeAction. The error object then also carries minTtlSeconds or maxTtlSeconds.
gate_not_active and gate_not_found are reported by the widget, as the reason of its botshield:failure event. See Web component. The SDK’s gate methods report a missing or inactive gate through message and statusCode, so branch on statusCode.
Coming in SDK 2.1
Version 2.0.1 is the current release. These changes arrive with BotShield 3.0 and are not in 2.0.1. Until 2.1 is published, the SDK drops fields it has no type for, so call the HTTP API directly when you need one of them.Call the API without the SDK
The SDK is a thin layer over plain JSON operations. For other languages, or for the operations and fields the SDK does not cover, call the HTTP API directly. API overview has the base URL, the credentials, and the envelope, and Errors has a small typedfetch helper.
Upgrading
2.0.1
Released 25 September 2026, regenerated from the September API specification.From 1.x
Version 2.0.x is a different generated client from 1.x. The API operations are the same. The calling conventions are not.Next steps
Verify on your server
The full server-side check for a gate result.
Propose an action
Request fields and outcomes for Agents Ask.
Errors
Status codes for every operation.
Keys and environments
Create the keys this page uses.
