{"openapi":"3.1.0","info":{"title":"Eleidon API","version":"0.1.0","description":"Eleidon is a cryptographic identity verification layer for AI agents. It lets agents prove authorship of messages using Ed25519 digital signatures, verified inboxes, and a public registry.\n\n## How it works\n\n1. **Generate a keypair** — An Ed25519 keypair (public + private key) is created client-side using the SDK, CLI, or MCP server\n2. **Register an agent** — The public key and a claimed inbox (email) are registered with the API\n3. **Verify the inbox** — A challenge code is sent to the claimed email; submitting it proves ownership\n4. **Sign messages** — The canonical message is hashed and signed with the private key, then recorded on the API\n5. **Verify messages** — Anyone can verify a signature against the public registry (no auth required)\n\n## Authentication\n\nMost endpoints require an API key passed via the `Authorization` header:\n\n```\nAuthorization: Bearer eld_your_api_key_here\n```\n\nThe verify endpoint is **public** — no authentication required.\n\n## Canonical Message Format\n\nMessages are canonicalized before hashing to ensure cross-platform consistency:\n\n```\nELEIDON-CANONICAL-MESSAGE-V1\nFROM:sender@example.com\nTO:recipient1@example.com,recipient2@example.com\nSUBJECT:Hello World\nTIMESTAMP:2026-01-15T10:30:00Z\nBODY-HASH:<sha256 hex of body>\n```\n\nRules:\n- `FROM` is lowercased and trimmed\n- `TO` addresses are lowercased, trimmed, and sorted alphabetically\n- `SUBJECT` is trimmed with whitespace collapsed to single spaces\n- `TIMESTAMP` is ISO 8601 UTC\n- `BODY-HASH` is the SHA-256 hex digest of the raw body text\n\nThe final message hash is the SHA-256 hex digest of this entire canonical string.\n\n## SDKs and Tools\n\n- **TypeScript SDK**: `@eleidon/sdk` — full client with crypto utilities\n- **Python SDK**: `eleidon` — pip-installable client with PyNaCl crypto\n- **MCP Server**: `@eleidon/mcp` — Model Context Protocol server for AI agents\n- **CLI**: `@eleidon/cli` — command-line tool for key management and signing\n"},"servers":[{"url":"https://api.eleidon.com","description":"Production"},{"url":"http://localhost:3001","description":"Local development"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key (e.g. eld_abc123...)"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"Error message"}},"required":["error"]},"Agent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Agent UUID"},"public_key":{"type":"string","description":"Ed25519 public key (64-char hex)"},"claimed_inbox":{"type":"string","format":"email","description":"Claimed email address"},"inbox_verified":{"type":"boolean","description":"Whether the inbox has been verified"},"display_name":{"type":"string","nullable":true,"description":"Optional display name"},"metadata":{"type":"object","nullable":true,"description":"Optional metadata"},"registered_at":{"type":"string","format":"date-time"}}},"VerificationResult":{"type":"object","properties":{"result":{"type":"string","enum":["verified","fraudulent","unknown"],"description":"`verified` = valid signature from registered agent, `fraudulent` = signature mismatch or sender mismatch, `unknown` = no agent found"},"confidence":{"type":"number","minimum":0,"maximum":1,"description":"1.0 for verified agents with confirmed inbox, 0.7 for unverified inbox"},"reason":{"type":"string","description":"Human-readable explanation (present on fraudulent/unknown)"},"agent":{"$ref":"#/components/schemas/Agent"},"signature":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"signed_at":{"type":"string","format":"date-time"}}}},"required":["result","confidence"]}}},"paths":{"/health":{"get":{"operationId":"healthCheck","summary":"Health check","tags":["System"],"security":[],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"eleidon-api"},"version":{"type":"string","example":"0.1.0"}}}}}}}}},"/v1/agents/register":{"post":{"operationId":"registerAgent","summary":"Register an agent","description":"Register a new agent identity by providing an Ed25519 public key and a claimed inbox email. A verification challenge is sent to the email address.","tags":["Agents"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["public_key","claimed_inbox"],"properties":{"public_key":{"type":"string","description":"Ed25519 public key as 64-character hex string","example":"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"},"claimed_inbox":{"type":"string","format":"email","description":"Email address the agent claims to send from","example":"agent@company.com"},"display_name":{"type":"string","description":"Optional human-readable name","example":"Customer Support Bot"},"metadata":{"type":"object","description":"Optional key-value metadata","example":{"model":"claude-opus-4-6","version":"2.1"}}}}}}},"responses":{"201":{"description":"Agent registered, verification email sent","content":{"application/json":{"schema":{"type":"object","properties":{"agent_id":{"type":"string","format":"uuid"},"claimed_inbox":{"type":"string","format":"email"},"inbox_verified":{"type":"boolean","example":false},"challenge_sent":{"type":"boolean","example":true},"created_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Agent already registered or inbox claimed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/verify-inbox":{"post":{"operationId":"verifyInbox","summary":"Verify inbox ownership","description":"Submit the challenge code received via email to verify ownership of the claimed inbox.","tags":["Agents"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agent_id","challenge_code"],"properties":{"agent_id":{"type":"string","format":"uuid","description":"Agent ID from registration"},"challenge_code":{"type":"string","description":"6-character code from the verification email","example":"AB3K7M"}}}}}},"responses":{"200":{"description":"Inbox verified successfully","content":{"application/json":{"schema":{"type":"object","properties":{"agent_id":{"type":"string","format":"uuid"},"claimed_inbox":{"type":"string","format":"email"},"inbox_verified":{"type":"boolean","example":true},"verified_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No pending challenge","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Challenge expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/{id}":{"get":{"operationId":"getAgent","summary":"Look up an agent by ID","tags":["Agents"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Agent details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Agent"}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents":{"get":{"operationId":"lookupAgentByInbox","summary":"Look up an agent by inbox","description":"Find the verified agent registered for a given email address.","tags":["Agents"],"parameters":[{"name":"inbox","in":"query","required":true,"schema":{"type":"string","format":"email"},"description":"Email address to look up"}],"responses":{"200":{"description":"Agent details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Agent"}}}},"400":{"description":"Missing inbox parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No verified agent for this inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sign":{"post":{"operationId":"signMessage","summary":"Record a signed message","description":"Submit a message hash and its Ed25519 signature for recording. The API verifies the signature matches the agent's public key before storing it. Returns an `eleidon_header` string to attach to the outgoing message.","tags":["Signing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agent_id","message_hash","signature"],"properties":{"agent_id":{"type":"string","format":"uuid"},"message_hash":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"SHA-256 hash of the canonical message (64-char hex)"},"signature":{"type":"string","pattern":"^[0-9a-f]{128}$","description":"Ed25519 signature of the message hash (128-char hex)"},"headers":{"type":"object","description":"Optional message envelope headers","properties":{"from":{"type":"string","format":"email"},"to":{"type":"array","items":{"type":"string","format":"email"}},"subject_hash":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}}},"responses":{"200":{"description":"Signature recorded","content":{"application/json":{"schema":{"type":"object","properties":{"signature_id":{"type":"string","format":"uuid"},"eleidon_header":{"type":"string","description":"Header to attach to the message: `v1:<agent_id>:<signature_id>:<signature_hex>`","example":"v1:550e8400-e29b-41d4-a716-446655440000:660e8400-e29b-41d4-a716-446655440001:abcd1234..."},"signed_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid input or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Agent inbox not verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/verify":{"post":{"operationId":"verifyMessage","summary":"Verify a message signature","description":"Verify the authenticity of a message by checking its Eleidon header against the public registry. **No authentication required.**","tags":["Verification"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sender","message_hash","eleidon_header"],"properties":{"sender":{"type":"string","format":"email","description":"Claimed sender email address"},"message_hash":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"SHA-256 hash of the canonical message"},"eleidon_header":{"type":"string","description":"The `X-Eleidon-Signature` header from the message","example":"v1:550e8400-e29b-41d4-a716-446655440000:660e8400-e29b-41d4-a716-446655440001:abcd1234..."}}}}}},"responses":{"200":{"description":"Verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationResult"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"tags":[{"name":"System","description":"Health and status endpoints"},{"name":"Agents","description":"Agent registration, verification, and lookup"},{"name":"Signing","description":"Message signing and signature recording"},{"name":"Verification","description":"Message signature verification (public, no auth required)"}]}