Developers

Five minutes to agent-aware.

One page tag. One server check of the token. The hosted service is free for every site, and a test token cannot pass as a live one.

Install

The script tag works today.

Replace site_test_your_key with the test key from your dashboard. data-api keeps challenge traffic on imnotahuman.ai. The queue runs before the widget loads, which is what window.imnotahuman.q is for.

  • data-site-key — your test or live key
  • data-api — https://imnotahuman.ai
  • data-action / data-intent — bound into the challenge and the token

Not on npm yet. Source is in packages/; the HTML tag and the REST API work today.

HTML
<script>
  window.imnotahuman = {
    q: [["onVerified", function (result) {
      // result.agent_id, result.token, result.mode ("live" | "test"), result.challenge_id
      // Your route. Verify result.token on the server. The browser flag is not proof.
      fetch("/api/agent-token", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ token: result.token })
      });
    }]]
  };
</script>
<div class="imnotahuman"
  data-site-key="site_test_your_key"
  data-api="https://imnotahuman.ai"
  data-action="checkout"></div>
<script src="https://imnotahuman.ai/widget.js" async></script>

In order

The whole integration.

Page
Sign in, add the staging origin, and copy the site_test_ key. Then https://imnotahuman.ai/widget.js with data-api="https://imnotahuman.ai" and data-action.
Server
POST https://imnotahuman.ai
/api
/v1/tokens/verify
. Staging sends allow_test. Live calls omit it. Or check https://imnotahuman.ai
/.well-known
/jwks.json
.
Receive
agent.id, action, and mode from the API response, plus the challenge and origin.
Decide
Checkout, an API, or a rate limit you control. The browser flag is not the decision.

Not on npm yet. Source is in packages/; the HTML tag and the REST API work today.

Test keys

Start with site_test_. Ship with site_live_.

Your keys

Every site gets a public site_test_ key and a public site_live_ key. Test challenges show TEST MODE, can be completed with Simulate agent, and issue tokens that production verification rejects unless the caller sends allow_test: true.

Public demo keys

site_test_imnotahumanpublicdemo and site_live_imnotahumanpublicdemo only work on imnotahuman.ai and local development origins. A challenge from your domain with either key fails with ORIGIN_UNAUTHORIZED. Create your own site for your origin.

Open the live demo

Verify

One call on the server.

The widget can hand the page a token. Only POST /api/v1/tokens/verify tells you it was issued for your site key. Pass consume: true so a second presentation fails. Test-mode tokens need allow_test: true, and that flag stays off the production path.

Prefer no network call? Check the EdDSA signature offline with https://imnotahuman.ai
/.well-known
/jwks.json
.

curl test
curl -sS -X POST https://imnotahuman.ai/api/v1/tokens/verify \
  -H "content-type: application/json" \
  -d '{"token":"<token from the widget>","site_key":"site_test_your_key","consume":true,"allow_test":true}'

Result

Never just a boolean.

The verify response names the agent, the method, the challenge, the origin, and the action. Statuses are PENDING, VERIFIED, REJECTED, EXPIRED, REVOKED, or ERROR. Branch on those fields after the API returns them.

verification result
{
  "verified": true,
  "status": "VERIFIED",
  "subject_type": "agent",
  "mode": "live",
  "agent": { "id": "agent_nova_8f2a", "name": "Nova" },
  "verification": {
    "method": "ed25519_challenge",
    "verified_at": "2026-09-20T13:42:07.000Z",
    "challenge_id": "ch_k7q2m5x4a3b3c6d2e6f4g2h5jk",
    "origin": "https://example.com",
    "action": "checkout",
    "intent": ""
  },
  "token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6...",
  "expires_at": "2026-09-20T13:52:07.000Z"
}

Stable errors

Machine-readable codes such as CHALLENGE_EXPIRED, ORIGIN_UNAUTHORIZED, and TOKEN_TEST_MODE, under /api/v1.

Agent side

Building an agent? Register it, keep the private key, and sign challenges with https://imnotahuman.ai/agent.mjs or any Ed25519 library.

Company decisions

Checkout, APIs, your rate limits, and the event log are described on For companies. The proof limits are on Security.