Agnic

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

ScopeCovers
payments:signX402 payment signing
balance:readGET /api/balance
transactions:readGET /api/transactions
email:readAll /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.