Get your agents verified
Sites that run Posterna label every request from an AI agent or crawler. A request that proves who sent it is labeled verified. One that only claims a name in its User-Agent is labeled unverifiable or, when the proof is wrong, claimed but failed. Sites decide in their own policy what each label gets.
This page is for teams that run agents or crawlers and want their requests to be verified.
How a site verifies your agent
Posterna checks a request in one of two ways, using the open Posterna directory of operators:
- A signature. Your agent signs each request with Web Bot Auth, an HTTP Message Signatures (RFC 9421) profile. This works from any network and is the method we recommend.
- Your addresses. Your agent sends from IP ranges you publish as a JSON file, or from hosts whose reverse DNS names end in a suffix you document.
Sign your requests
- Make an Ed25519 key pair. Keep the private key on your signing servers only.
- Publish a key directory at
https://<your-domain>/.well-known/http-message-signatures-directory: a JSON Web Key Set with media typeapplication/http-message-signatures-directory+json, eachkidset to the key's RFC 7638 thumbprint. Sign the response itself as the protocol draft describes (taghttp-message-signatures-directory, covering"@authority";reqandcontent-digest). - Sign every request. Send a
Signature-Agentheader naming your origin, for exampleSignature-Agent: "https://bot.example", and a signature that:- covers
@authorityandsignature-agent, - uses
tag="web-bot-auth",alg="ed25519"andkeyidset to the key's thumbprint, - has
createdandexpiresno more than an hour apart (5 minutes is a good choice), - carries a fresh
nonce(64 random bytes, base64).
- covers
- Keep a stable User-Agent token and document it, along with the robots.txt token you honor.
Cloudflare's open-source web-bot-auth and http-message-sig libraries handle the signing in steps 2 and 3.
Test against /v1/echo
Sign a request to https://posterna.com/v1/echo exactly as your agent signs requests to sites. The answer shows what Posterna saw: the verdict, the operator and agent it matched, the components your signature covers, and the reason for any failure. Nothing about the request is stored.
import { generateNonce, sign } from "web-bot-auth";
import { signerFromJWK } from "web-bot-auth/crypto";
const signer = await signerFromJWK(privateJwk); // your Ed25519 private key as a JWK
const request = new Request("https://posterna.com/v1/echo", {
headers: {
"User-Agent": "ExampleBot/1.0 (+https://bot.example/about)",
"Signature-Agent": '"https://bot.example"',
},
});
const now = new Date();
const { signature, signatureInput } = await sign(request, {
signer,
created: now,
expires: new Date(now.getTime() + 60_000),
nonce: generateNonce(),
});
request.headers.set("Signature", signature);
request.headers.set("Signature-Input", signatureInput);
console.log(await (await fetch(request)).json());A verified request answers like this:
{
"verdict": "verified_by_signature",
"reason": null,
"operator": "bot-example",
"agent": "ExampleBot",
"method": "signature",
"authority": "posterna.com",
"signatures": [
{
"label": "sig1",
"components": ["@authority", "signature-agent"],
"parameters": { "created": 1793068583, "expires": 1793068643, "keyid": "...", "alg": "ed25519", "tag": "web-bot-auth", "nonce": "..." }
}
]
}Until your key directory is in the Posterna directory, the verdict says your agent is not one Posterna knows. The signatures part still shows whether the signature is well formed. Echo allows 60 requests a minute from one address.
Get listed
The Posterna directory is built from operators' own public documentation and reviewed by a person before each release. To be added, or to correct your entry, tell us about your agents below. We review every request by hand. Nothing fetches the key directory URL you enter until that review is done.
The current state of every operator is on the signer status board.