# Hand Off a CAPTCHA API Integration to an AI Coding Assistant

> A walkthrough: give Claude Code, Cursor, Copilot or Codex ZeroCaptcha's integration brief and rule files, then check its work against the brief's checklist.

- Source: https://zerocaptcha.io/blog/ai-coding-assistant-captcha-integration
- Published: 2026-10-01
- Author: ZeroCaptcha Engineering

To have an AI coding assistant integrate ZeroCaptcha, give it **one file**: the integration brief at
[/ai/integration.md](https://zerocaptcha.io/ai/integration.md). It is generated when the site is built, from the API's own
OpenAPI contract and tested reference clients, and holds everything the assistant needs:
configuration, every call, polling and callbacks, every error code and what to do about it, the
retry rules, reference clients in Node, Python, Go and bash, and **a checklist** it works through
before it says it is done. Save the rule file for your assistant too (Claude Code, Cursor, AGENTS.md
or Copilot), put your key in the environment rather than the chat, and then check the result against
the same checklist.

This walkthrough takes you from an empty branch to a reviewed integration. The files are listed on
the docs page [Hand off to AI](https://zerocaptcha.io/docs/ai); nothing below needs anything else.

## Step 1: get the files

The site serves six files for assistants, none of which contains a key:

| File | What it is | Where it goes |
| --- | --- | --- |
| `/ai/integration.md` | The integration brief | Give it to the assistant, or keep it in the repository |
| `/ai/zerocaptcha.json` | The brief as JSON, for tools | Wherever your tooling reads it |
| `/ai/claude/SKILL.md` | A Claude Code skill | `.claude/skills/zerocaptcha/SKILL.md` |
| `/ai/cursor/zerocaptcha.mdc` | A Cursor rule | `.cursor/rules/zerocaptcha.mdc` |
| `/ai/AGENTS.md` | A section for `AGENTS.md`, read by Codex, Jules, Gemini CLI and other agents | Paste into your `AGENTS.md` |
| `/ai/copilot-instructions.md` | GitHub Copilot instructions | `.github/copilot-instructions.md` |

The brief starts the assistant; the rule files keep the same rules in front of it whenever it
touches your ZeroCaptcha code later. In the dashboard, **Hand off to AI** on the API keys page
downloads the brief with your account's API address filled in.

Fetching them into a repository, with `ZEROCAPTCHA_SITE` set to this site's address:

```sh
mkdir -p .claude/skills/zerocaptcha .cursor/rules .github
curl -fsSL "$ZEROCAPTCHA_SITE/ai/claude/SKILL.md" -o .claude/skills/zerocaptcha/SKILL.md
curl -fsSL "$ZEROCAPTCHA_SITE/ai/cursor/zerocaptcha.mdc" -o .cursor/rules/zerocaptcha.mdc
curl -fsSL "$ZEROCAPTCHA_SITE/ai/AGENTS.md" >> AGENTS.md
curl -fsSL "$ZEROCAPTCHA_SITE/ai/copilot-instructions.md" >> .github/copilot-instructions.md
```

The last two append, so existing instructions in those files are kept.

## Step 2: put the key where the code will read it

The brief tells the assistant to read the key from `ZEROCAPTCHA_KEY` (or your project's secret
store) and the API's address from `ZEROCAPTCHA_API`, and never to write the key into source, logs,
error messages, URLs or anything sent to a browser. Set both in your shell or `.env` before you
start, and keep `.env` out of version control. Don't paste the key into the chat: anyone who has it
can spend your balance. A key with its own daily spend cap limits what a mistake can cost while you develop.

## Step 3: prompt

A prompt that names the brief, the page and the key's variable is enough:

```text
Read https://your-docs-site/ai/integration.md and integrate ZeroCaptcha into this project to solve
the Cloudflare Turnstile widget on https://staging.example.com/login. Read the API key from the
ZEROCAPTCHA_KEY environment variable. Work through the brief's checklist before you finish.
```

Replace the address with this site's. If your assistant can't fetch URLs, attach the file instead.
Say which page and which widget, and whether the site sets an `action` or `cData`: the assistant
can't guess them, and a token with the wrong action may be refused by the site.

## Step 4: review against the checklist

The brief ends with a checklist, and it is the fastest review you can do. Each line, shortened
from the brief, with what to look for in the diff:

| The brief's checklist says | Look for |
| --- | --- |
| The base URL is read from `ZEROCAPTCHA_API`, and no other host is called | One place that reads the variable |
| The API key is read from `ZEROCAPTCHA_KEY` (or the project's secret store), never written in source, logs, error messages, URLs or anything sent to a browser | No key literal; no key in log lines or exceptions |
| Every create sends an `Idempotency-Key` made once per task and reused only when retrying that same create | The key made outside the retry loop |
| Results are read every 2 seconds, or received by a signed callback, and the wait stops at a deadline | A sleep of 2 seconds and a deadline; no endless loop |
| Both the HTTP status and the body are checked on every reply; a non-JSON reply is an error | Status checked before parsing |
| 429, 5xx and `idempotency_key_in_use` are retried after `Retry-After`, else with exponential backoff from 1 s to 16 s with jitter; nothing else is retried as is | A retry list, not a blanket retry |
| `failed` and `expired` tasks are reported with their `errorCode` and never retried in a loop | No "try again forever" |
| A Turnstile token is used at once: it works once, for 300 seconds | The token submitted right after it arrives, never cached |
| A challenge page's `cf_clearance` cookie is sent with `solution.userAgent`, through the same proxy the task used | User agent and proxy kept with the cookie |
| Callbacks, if used, are checked with the HMAC-SHA256 signature over the raw body, in constant time, refusing timestamps more than 300 seconds away | Verification before JSON parsing |
| Money is handled as the decimal strings the API sends, never as floats | No `float(cost)` |
| Tests run against a stand-in for the API, not the real one: every real task is charged | A mock server or recorded replies in the tests |

The [idempotency keys guide](https://zerocaptcha.io/guides/idempotency-keys-for-captcha-tasks) and
[createTask and getTaskResult](https://zerocaptcha.io/guides/createtask-gettaskresult-explained) explain the two rules
assistants most often get wrong. For signed callbacks, see
[verify a webhook's HMAC-SHA256 signature](https://zerocaptcha.io/guides/verify-webhook-hmac-signature).

## Step 5: run it once for real

When the tests pass against the stand-in, run the integration once against the real API on a page
you are allowed to automate. That one task is charged if it succeeds, as every task is: ZeroCaptcha
has no test mode or test keys. For your own forms' CI, use Cloudflare's testing sitekeys instead,
which cost nothing: see [Cypress and Cloudflare Turnstile](https://zerocaptcha.io/blog/cypress-cloudflare-turnstile).

## Brief or MCP server?

The brief is for an assistant **writing code**. If you want the assistant to **call ZeroCaptcha
itself** while you work, to check a sitekey, read a task or search the docs, connect the
[ZeroCaptcha MCP server](https://zerocaptcha.io/blog/captcha-solver-mcp-server) instead. Many setups use both: the rule
file for the code, the server for questions. The product itself is on the
[Cloudflare Turnstile solver](https://zerocaptcha.io/cloudflare-turnstile-solver) page.

## Sources

- [ZeroCaptcha docs: hand off to AI](https://zerocaptcha.io/docs/ai) and the [integration brief](https://zerocaptcha.io/ai/integration.md)
  (checked 1 October 2026).
- [ZeroCaptcha docs: errors and retries](https://zerocaptcha.io/docs/errors-and-retries) (checked 1 October 2026).
- [AGENTS.md](https://agents.md), the open format for agent instructions (checked 1 October 2026).
- [GitHub Docs: adding repository custom instructions for GitHub Copilot](https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions)
  (checked 1 October 2026).

## Questions

### What file do I give my AI coding assistant to integrate ZeroCaptcha?

The integration brief at /ai/integration.md. It is one self-contained file, generated from the API's OpenAPI contract and tested reference clients, with configuration, every call, polling and callbacks, every error code, retries, reference clients in four languages and a checklist.

### Should I paste my API key into the assistant's chat?

No. The brief tells the assistant to read the key from the ZEROCAPTCHA_KEY environment variable. Set it in your environment or secret store; anyone who has the key can spend your balance.

### How do I know the assistant's integration is right?

Go through the checklist at the end of the brief: the base URL and key come from the environment, every create sends an Idempotency-Key, results are polled every 2 seconds with a deadline, retries follow Retry-After, tokens are used at once, and tests run against a stand-in for the API.
