Skip to main content
An agent you run yourself has no Alyte token. It authenticates by signing each request with its own key, RFC 9421 style — the same mechanism Visa’s Trusted Agent Protocol uses. Alyte looks the key up in the merchant’s agent registry, checks the signature, freshness, replay and domain binding, and admits the request as that agent. Nothing in the request is trusted until the signature verifies. Use the conformance tool to sign and send a sandbox request. A valid signature admits your identity; the endpoint still validates the payload and any required purchase authority.

Before you sign: three things must be true

Without 1 the signature cannot be verified (unknown key). Without 2 you are admitted but hold no spending authority, so anything on the money path is refused. Without 3 the signature is bound to the wrong domain and is refused.
Key enrolment today goes through the merchant’s Visa agent registry, so the merchant must have connected one in their console. If your merchant has not, ask your Alyte contact — a registration path that does not require Visa is on the roadmap.

What to sign

Send two headers, Signature-Input and Signature, plus Content-Digest when there is a body.
Covered components, in this order: Parameters: The signature base is built per RFC 9421 §2.5: one "<component>": <value> line per covered component, then "@signature-params": <everything after sig1=>, joined with \n. Sign that string:
  • ed25519 — pure EdDSA over the bytes, no prehash. Signature is the raw 64 bytes.
  • ecdsa-p256-sha256 — SHA-256, signature in raw r||s form (64 bytes), not DER.
  • rsa-pss-sha256 — SHA-256, PSS padding, salt length = 32.
Base64 the signature bytes into Signature as sig1=:<base64>:.
Alyte compares the signed Content-Digest with SHA-256 of the exact received body bytes. For a request with a body, supply one canonical sha-256=:<base64>: value and include content-digest in the covered components. A missing, unsigned, malformed or mismatched digest fails verification. Multiple digest values and other algorithms are not accepted by this profile.Hash and send the same bytes. Reformatting JSON, changing whitespace or changing UTF-8 encoding after signing invalidates the request, even when its parsed JSON would be equivalent. The conformance tool hashes and sends the same body file. Body-size limits still apply.

Prove it with the conformance tool

The tool signs exactly the way Alyte verifies — it builds the signature base with the server’s own code — so it is the reference implementation. It ships in the Alyte repository as scripts/tap-sign-request.mjs. 1 · Make a key. The private half stays with you; the public half is what the merchant enrols.
2 · Sign and send a request.
Without --send it prints the three headers for you to attach in your own client. With --send it performs the request and prints the status and body. Exit 0 means admitted and answered 2xx; 2 means Alyte refused, and the output says why.

Diagnosing a refusal

Signature authentication refusals use 401 with the standard error envelope. Branch on code; the message identifies some checks, while cryptographic and body-digest failures share the generic verification failure. Payload validation, body-size limits and purchase checks can return other statuses. Admitted but refused on a purchase? That is the mandate, not the signature — see the agent buy path and Errors. A buyer has to bring your agent and grant it a cap before it can spend.

What the signature does and does not prove

A valid signature proves who sent the request: a registered agent operator, bound to this merchant, right now, once. It carries no spending authority. Every cap, scope, expiry and inventory limit is enforced server-side from the buyer’s mandate, on every call, regardless of what the agent asserts. A compromised agent can still exercise its existing authority within those limits; revoke its key and buyer grants when that authority should end.