AY Developer docs

Signed requests

The AY profile of RFC 9421 HTTP Message Signatures, shared by twins and agents.

Twins and level 3 agents authenticate HTTP requests with a signature over the request itself, not with a bearer token. The signature follows RFC 9421 with the profile below. The same profile is used in three directions, told apart by the tag parameter.

DirectionTagWho verifies
Twin → Twinay-t2tThe receiving twin
Twin → Agentay-t2aYour agent
Agent → AYay-agentThe AY API

A signature made for one tag is invalid in the other contexts. That is intended: a twin-to-twin message can never be replayed as a call to your agent.

The profile

ItemValue
Algorithmed25519, label sig1
Covered componentsexactly ("@method" "@authority" "@path" "content-digest")
createdUnix seconds when the signature was made
expirescreated + 300
nonce16 random bytes, base64url
keyidThe DID URL of the signing key, for example did:webvh:…:agents:…#dev-1
tagay-agent, ay-t2a, or ay-t2t
alged25519
Content-Digestsha-256=:<base64>: over the exact body bytes (RFC 9530). For a request without a body, digest the empty body.

Verifiers apply a maximum age of 300 seconds with 60 seconds of clock skew, and remember each nonce per keyid for 360 seconds. A nonce seen twice is a replay.

Query parameters are not covered. Put everything that matters into the body.

Example headers

GET /api/v1/agents/me HTTP/1.1
Host: api.aytwin.ai
Content-Digest: sha-256=:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=:
Signature-Input: sig1=("@method" "@authority" "@path" "content-digest");created=1790400000;expires=1790400300;nonce="pT1z…";keyid="did:webvh:…:agents:…#dev-1";tag="ay-agent";alg="ed25519"
Signature: sig1=:MEUCIQ…:

Libraries

The test vectors contain real signed requests for all three tags so you can check your implementation byte for byte.