Agent identity & provenance
Give your agents a signed identity so recipients can verify the mail genuinely came from them.
Give an automated sender its own verifiable identity. An agent passport is a
portable agt_… identity that signs the email your agents send, so anyone
receiving that mail can confirm it genuinely came from your agent — not a spoofer.
This is an optional layer. You don't need a passport to send or receive email;
reach for it when you want recipients (or downstream agents) to be able to
prove who sent a message. Reads use agents:read; creating and binding use
agents:write. Verifying is public — no scope or API key.
Create a passport
You get back the passport, including a portable agentId:
Use the portable agentId (agt_…) — stable for the life of the passport — in
anything you publish or share.
Creating a passport isn't idempotent: each call mints a new agentId, so create
once and store the id rather than retrying.
List and read
Read a passport by its id or its portable agt_… id. Listing returns an
agents array, newest first — there's no pagination or limit, so one call
returns every passport in your organization.
A passport supports create, read, bind, and delete — there's no edit. Deleting a
passport clears its attribution from your keys, inboxes, and sent mail without
touching the messages themselves. Those messages keep their provenance headers,
but verifying one afterward returns unknown_agent, since the passport it named
is gone.
Bind a key or inbox
A passport on its own is only an identity. Binding connects it to the resources an agent actually sends through — an API key and/or an inbox — so every email those resources produce is signed with the agent's provenance and attributed to it in your send-health view.
Pass at least one of apiKeyId / inboxId — both must be resources you own.
Reference the passport by its id or its portable agt_… id.
The response echoes what was bound:
Bind both at once by passing apiKeyId and inboxId together.
You can only bind your own resources to your own passport — there's no way to attach someone else's key or inbox.
After binding, mail from that key or inbox carries the agent's
X-Dairo-Provenance signature, and cross-account agent-to-agent hop receipts
record the bound agentId. From then on, the agent's reputation and any
per-agent send limit gate what it can send.
How provenance works
When a send goes out from a bound key or inbox, Dairo signs a stable summary of
the message (the from, to, subject, and timestamp) and stamps two headers
onto the outgoing mail:
X-Dairo-Provenance— the signature token.X-Dairo-Verify— a verify URL anyone can click.
Signing is best-effort and never blocks a send. A recipient re-derives the same summary from the message they received and checks the signature against the public key Dairo publishes in its JWKS — so they can confirm authenticity without trusting you, or even calling Dairo.
Verify a signed message
Provenance is only useful if anyone can check it. Two public endpoints let them: a verify endpoint that returns a plain yes/no for a given message, and a JWKS that publishes the public signing keys so anyone can check a signature on their own. Neither needs a scope or an API key.
Get a verdict
The simplest path: hand Dairo a message id and get back a verdict, with no crypto
on your side. The endpoint always returns 200 with a verdict — a "no" is a
result, not an error.
A verdict carries verified, the matched agent (when known), the keyId, the
issuer (dairo.app), and a checkedAt timestamp:
A "no" returns the same shape with "verified": false and a reason such as
missing_parameters, message_not_found, unknown_kid, or bad_signature.
Because verify never errors, branch on the verified field — not on the HTTP
status. A 200 with "verified": false is the expected "no" answer.
Verify a signature yourself
To check a signature without relying on Dairo's lookup — say, from the headers on
a message you received — pass the signature (agent + kid + sig) together
with the signed fields (from, to, subject, ts):
Check it offline with the public keys
GET /v1/agents/jwks serves the public signing keys as a standard JSON Web Key
Set, so you can verify a signature entirely on your own — no call back to Dairo.
It serves active and retired keys, so a kid that signed an old message stays
verifiable forever.
Find the key whose kid matches the message's signature, then verify the signed
fields against it with any standard EdDSA library.