Security

What verification proves.

A verified result means exactly this: this request was signed by a recognized agent credential.

Last updated 23 September 2026.

The claim

VERIFIED means someone holding the private key for an active, registered key of a non-disabled agent signed this specific challenge inside its validity window. For Web Bot Auth, it means the request was signed by a key published in the named origin's directory.

Authentication, not a pass

Treat a verified agent as a known client. Authorization, safety and intent stay with the integrating website. The widget cannot grant them.

What it does not prove

A reader might assumeThe result actually says
No human was involved.A person can run, script or supervise the agent, or paste the challenge into a signer. The signature proves possession of a key.
The agent is benevolent, accurate or safe.Registration does not review behaviour. There is no AI-detection score.
The operator's name is a verified identity.Agent name and website are self-declared by the account that registered them.
The site should let the agent in.The token names a credential. The site decides what that credential may do. The protocol does not delegate authorization.
Later requests are covered.The token covers one challenge. It is not a session.

The product also does not use trivia, impossible maths, typing or timing tests, cursor analysis, user-agent sniffing, or a model judging whether someone "seems like AI". Those signals are not proof. The click demo on the homepage is labelled as a demo and never talks to the verifier.

Trust boundaries

PartyRelied on forNot relied on for
Widget in the browserShowing the status the server already recorded.Declaring success. The host verifies the token.
Publishable client keyLetting a signed-in operator read their own dashboard rows.Writing challenges, proofs or tokens. Those writes exist only on the verification API. The key is not a service credential.
Integrating websiteAuthorization, and keeping the token on its own backend.Forging a proof. The server rebuilds the signed message from its own challenge record.
Holder of the agent private keyBeing that agent for this challenge.Any claim about intent. Whoever holds the key is the agent.
This verifierChecking the signature, consuming the challenge, issuing the token.Judging whether the requested action is a good idea.

Service credentials and token-signing seeds are not written into these pages.

Controls

  • Cryptographic identity. Agents register an Ed25519 public key. Proofs are signatures over a base that binds the challenge id, nonce, site key, origin, issued and expiry timestamps, action, intent and mode. Only Ed25519 proofs and EdDSA tokens are accepted.
  • One-time challenges. The first valid proof consumes the challenge. A second proof of the same challenge fails. Failed proofs do not consume it, so an honest retry can succeed until the attempt cap.
  • Origin binding. A challenge is created only for https://<domain>, an https subdomain of that domain, or an origin the site has listed (including local development).
  • Scoped tokens. Verification tokens are EdDSA JWTs. The audience is the site key, so a token for one site does not verify as another site's. Public keys are at /.well-known/jwks.json.
  • Revocation. Keys and agents can be revoked or disabled. Later proofs fail with KEY_REVOKED, KEY_PENDING, AGENT_DISABLED or AGENT_REVOKED.
  • Rate limiting and attempt caps. The website throttles by client address (Cloudflare's connecting IP when it is present). The API adds per-network, per-site, per-challenge, per-agent and per-user buckets. Challenge mint, proof checks and key registration are tighter than docs and static files. Health checks stay open for monitoring and still cap floods. A verified agent does not get a higher budget. A challenge is rejected after ten failed proofs.
  • Test mode stays labelled. Keys beginning with site_test_ produce simulated verifications and test tokens. Production verification rejects those tokens unless the caller explicitly allows them.
  • Private keys stay with the agent. The service never receives or stores an agent private key. Registration uploads the public half. A page that asks for the private key is not imnotahuman.ai. Rotate by registering a new key and revoking the old one. A registration token is a short-lived secret; only its hash is stored.

Lifetimes and caps

LimitValue
Challenge lifetime120 seconds by default. A site may ask for 30 to 300 seconds.
Signature clock skew60 seconds around the server clock and the challenge window.
Failed proofs on one challenge10, then that challenge is rejected.
Verification token lifetime10 minutes, and single-use when the site verifies with consume.
Per-minute request limitsPublished in the how verification works docs. The same numbers apply to every site.

Out of scope

  • A stolen private key. Whoever holds it is the agent until the key is revoked.
  • A malicious script on the host page. It can hide the widget or forward a token. Verifying and consuming the token on the site's server limits that to one use.
  • Traffic past the published rate limits. Those limits are not a capacity contract.
  • Reputation, behaviour scoring, or a claim that the caller is or is not an AI model.

The same checks for every site

The hosted service is free. Live keys and test keys run the same signature checks. There is no paid tier, no usage credit, and no upgrade that makes a verified result mean more than the claim above. Hitting a rate limit returns RATE_LIMITED. It does not open a checkout. The service can change or be interrupted. Status shows the live health check and does not promise an uptime figure.

Before you rely on it

  1. Verify the token on your server, or offline against the JWKS while remembering jti values for at least 10 minutes. Do not trust the widget alone.
  2. Consume the token when you act on it. A check without consume can still be presented by whoever holds the token.
  3. Make the authorization decision in your application. Verification only names a key.
  4. List every origin that should create challenges, including local development. HTTPS on your domain and its subdomains is allowed without a list. Other origins are not.
  5. Leave production verification rejecting test tokens. They pass only if you send allow_test.

Reporting a vulnerability

Report vulnerabilities privately through the contact page. Include the affected endpoint, the steps to reproduce, and the impact you expect. Do not include live private keys or session tokens, and do not post exploit details in public. This site has no public issue tracker for vulnerabilities. We acknowledge reports as we can and credit people who want to be credited.

The longer write-ups live in the docs. Company decisions that sit on top of this signal are on For companies. The embed is on Developers. API health is GET https://imnotahuman.ai/api/v1/health, shown on Status.