Agent Email & KYA
Agent Email & KYA — REST API Reference
Base URL: https://api.agnic.ai
Auth: X-Agnic-Token: <key> or Authorization: Bearer agnic_at_...
Agent Email
GET /api/agent/email
Returns alias info, or { hasEmail: false } if not provisioned.
Response
{
"hasEmail": true,
"emailAddress": "[email protected]",
"displayName": "My Agent",
"walletAddress": "0xabc...def",
"agentId": 396,
"isActive": true,
"createdAt": "2025-01-15T10:30:00Z"
}POST /api/agent/email
Creates the alias. Idempotent — re-posting with a new displayName updates it in place. Requires an active KYA agent.
Body
{ "displayName": "My Agent" }displayName is optional. Response shape same as GET.
Errors: 400 if no active agent.
GET /api/agent/email/inbox
Returns inbound and outbound messages, newest first.
Query params: limit (default 20, max 100), offset (default 0)
Response
{
"emailAddress": "[email protected]",
"messages": [{
"id": "aem_1775222237594_v4gwcj",
"direction": "inbound",
"from": "[email protected]",
"to": "[email protected]",
"subject": "Re: hello",
"bodyText": "Approved.",
"bodyHtml": null,
"isRead": false,
"threadId": null,
"createdAt": "2025-01-15T11:00:00Z"
}],
"limit": 20,
"offset": 0
}Note: bodyHtml is populated on inbound messages. threadId is unreliable (Resend-dependent) — use id for threading.
POST /api/agent/email/send
Sends from the agent's address. Plain text only (HTML not supported on send today).
Body
{ "to": "[email protected]", "subject": "Hello", "body": "Plain text only." }Response
{
"sent": true,
"messageId": "re_abc123",
"from": "[email protected]",
"to": "[email protected]",
"subject": "Hello"
}Errors: 400 missing fields · 404 no alias · 502 Resend error · 503 not configured
POST /api/agent/email/reply
Replies to an inbox message. Sets In-Reply-To/References headers automatically. Marks the original as read.
Body
{ "messageId": "aem_1775222237594_v4gwcj", "body": "Thank you." }messageId is the id field from the inbox, not the Resend ID.
Response: same shape as send.
KYA (Know Your Agent)
KYA registration happens automatically on first API key creation or OAuth token exchange — there is no manual provisioning endpoint exposed over REST.
GET /api/agent/identity
Returns the active agent's ERC-8004 identity. agentId is the on-chain KYA registration ID.
Response
{
"hasAgent": true,
"agentId": 396,
"chainId": "8453",
"walletAddress": "0xabc...def",
"trustScore": 85,
"status": "active",
"email": "[email protected]",
"delegation": {
"id": "del_abc123",
"sdJwt": "eyJ..."
}
}Returns { "hasAgent": false } if onboarding hasn't completed.
GET /api/agent/credential
Returns the agent's SD-JWT trust credential (used by merchants for identity verification).
Response
{
"hasCredential": true,
"trustCredential": "eyJ...",
"delegationCredential": "eyJ...",
"expiresAt": "2025-02-15T00:00:00Z"
}Returns { "hasCredential": false } if the agent isn't registered or credential fetch fails.
Scopes
| Scope | Covers |
|---|---|
payments:sign | X402 payment signing |
balance:read | GET /api/balance |
transactions:read | GET /api/transactions |
email:read | All /api/agent/email/* endpoints |
agent:read | /api/agent/identity, /api/agent/credential; also gates agent_id in /oauth/userinfo |
Note: scopes are declared but not currently enforced at the route level — any valid token can call any endpoint. Request the relevant scopes for forward-compatibility.
Stable user key
sub from GET /oauth/userinfo is the canonical human-account identifier (Privy DID, did:privy:...). agentId is agent-scoped. Use sub as your foreign key.