{"openapi":"3.1.0","info":{"title":"Ridian Agent Mailbox HTTP API","version":"0.3.0"},"servers":[{"url":"/"}],"components":{"schemas":{"MailboxWebhookPayload":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"event":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["message.received","message.attachments_settled"]},"mailbox_id":{"type":"string"},"message_id":{"type":"string"},"created_at":{"type":"string"}},"required":["id","type","mailbox_id","message_id","created_at"],"additionalProperties":false},"cursor":{"type":"string"}},"required":["event","cursor"],"additionalProperties":false}},"responses":{"400":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"401":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"403":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"404":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"405":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"409":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"413":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"415":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"429":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"503":{"description":"See error.code, message and next_step. For 429, respect Retry-After.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"next_step":{"type":"string"}},"required":["code","message","next_step"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}},"securitySchemes":{"mailbox":{"type":"http","scheme":"bearer","description":"Mailbox-scoped ridian_mailbox_<64 hex> credential. Receive/read, event access and its webhook management only, even after claim."},"setup":{"type":"http","scheme":"bearer","description":"Generate and persist ridian_setup_<64 cryptographically random hex> before the first request. Hand-written or patterned values are refused with weak_setup_credential. Reuse it to recover the same mailbox after interruption. Keep it secret."}}},"paths":{"/v1/mailboxes":{"post":{"operationId":"createOrRecoverMailbox","security":[{"setup":[]}],"description":"Create or recover one private receive-only mailbox. Same setup credential returns the same mailbox and credentials. No account or calendar required. No automatic mailbox expiry. Revocation is not undone by retry.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"mailbox":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"},"ownership":{"type":"string","enum":["unclaimed","claimed"]},"capabilities":{"type":"object","properties":{"receive":{"type":"boolean","const":true},"read":{"type":"boolean","const":true},"send":{"type":"boolean","const":false},"calendar":{"type":"boolean","const":false},"events":{"type":"boolean","const":true}},"required":["receive","read","send","calendar","events"],"additionalProperties":false},"limits":{"anyOf":[{"type":"object","properties":{"messages":{"type":"number"},"attachments":{"type":"number"},"storage_bytes":{"type":"number"}},"required":["messages","attachments","storage_bytes"],"additionalProperties":false},{"type":"null"}]}},"required":["id","address","ownership","capabilities","limits"],"additionalProperties":false},"access_token":{"type":"string"},"claim_secret":{"type":"string"},"claim_url":{"type":"string"},"token_type":{"type":"string","const":"Bearer"}},"required":["mailbox","access_token","claim_secret","claim_url","token_type"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current":{"get":{"operationId":"getCurrentMailbox","security":[{"mailbox":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"},"ownership":{"type":"string","enum":["unclaimed","claimed"]},"capabilities":{"type":"object","properties":{"receive":{"type":"boolean","const":true},"read":{"type":"boolean","const":true},"send":{"type":"boolean","const":false},"calendar":{"type":"boolean","const":false},"events":{"type":"boolean","const":true}},"required":["receive","read","send","calendar","events"],"additionalProperties":false},"limits":{"anyOf":[{"type":"object","properties":{"messages":{"type":"number"},"attachments":{"type":"number"},"storage_bytes":{"type":"number"}},"required":["messages","attachments","storage_bytes"],"additionalProperties":false},{"type":"null"}]}},"required":["id","address","ownership","capabilities","limits"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/messages":{"get":{"operationId":"listMailboxMessages","security":[{"mailbox":[]}],"description":"Incoming messages, newest first. Cursor is opaque and mailbox-bound. Empty pages can have a next_cursor after deleted messages; continue until null. Reading does not mark mail as read.","parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"in":"query","name":"cursor","schema":{"type":"string","maxLength":4096}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"received_at":{"type":"string"},"attachment_count":{"type":"number"}},"required":["id","from","subject","received_at","attachment_count"],"additionalProperties":false}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/messages/{message_id}":{"get":{"operationId":"getMailboxMessage","security":[{"mailbox":[]}],"parameters":[{"in":"path","name":"message_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"received_at":{"type":"string"},"attachment_count":{"type":"number"},"text":{"type":"string"},"html":{"type":["string","null"]},"to":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"reply_to":{"type":["string","null"]},"recipients_complete":{"type":"boolean"},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"content_type":{"type":"string"},"size":{"type":"number"},"status":{"type":"string","enum":["pending","processing","ready","failed"]},"download_path":{"type":["string","null"]}},"required":["id","filename","content_type","size","status","download_path"],"additionalProperties":false}}},"required":["id","from","subject","received_at","attachment_count","text","html","to","cc","reply_to","recipients_complete","attachments"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/attachments/{attachment_id}":{"get":{"operationId":"downloadMailboxAttachment","security":[{"mailbox":[]}],"description":"Authenticated binary download, no public storage URL. Not-ready files return 409. Always a download, never inline active content.","parameters":[{"in":"path","name":"attachment_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File bytes","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/events":{"get":{"operationId":"listMailboxEvents","security":[{"mailbox":[]}],"description":"Durable chronological events. Without cursor replay from the beginning of this mailbox journal. Persist next_cursor only after processing; deduplicate by event ID. Even empty results have a cursor. Follow has_more immediately, otherwise wait poll_after_ms. Deleted messages are hidden. message.attachments_settled means all recorded attachments are ready OR failed; read the message for details. No historical backfill before event support.","parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"in":"query","name":"cursor","schema":{"type":"string","maxLength":4096}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["message.received","message.attachments_settled"]},"mailbox_id":{"type":"string"},"message_id":{"type":"string"},"created_at":{"type":"string"}},"required":["id","type","mailbox_id","message_id","created_at"],"additionalProperties":false}},"next_cursor":{"type":"string"},"has_more":{"type":"boolean"},"poll_after_ms":{"type":"number"}},"required":["data","next_cursor","has_more","poll_after_ms"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/webhook":{"get":{"operationId":"getMailboxWebhook","security":[{"mailbox":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","anyOf":[{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"string","enum":["active","paused"]},"attempts":{"type":"number"}},"required":["url","status","attempts"],"additionalProperties":false},{"type":"null"}]}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}},"post":{"operationId":"configureMailboxWebhook","security":[{"mailbox":[]}],"description":"One subscription per mailbox credential. HTTPS port 443, public IPv4 DNS targets, no redirects. Save a separate random 32-byte signing_secret (64 lowercase hex, from a cryptographic generator; obviously patterned values are refused) before registering; retries with the same configuration are idempotent. First registration starts at the journal end, replacements preserve delivery position. Changes, including removal, limited to one per minute. Body: {event, cursor}. Verify x-ridian-signature v1=<HMAC-SHA256 hex> using the UTF-8 secret string over x-ridian-timestamp + '.' + exact raw body, tolerate at most 300 seconds of clock skew, deduplicate event.id. Persist before replying 2xx. At-least-once ordered delivery; six attempts then paused. Signing key is never returned. Removing and re-registering starts at the then-current end; pull replay remains available.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"url":{"type":"string","maxLength":512},"signing_secret":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["url","signing_secret"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","anyOf":[{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"string","enum":["active","paused"]},"attempts":{"type":"number"}},"required":["url","status","attempts"],"additionalProperties":false},{"type":"null"}]}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}},"delete":{"operationId":"deleteMailboxWebhook","security":[{"mailbox":[]}],"responses":{"204":{"description":"Removed; journal preserved"},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/webhook/resume":{"post":{"operationId":"resumeMailboxWebhook","security":[{"mailbox":[]}],"description":"No request body (an empty JSON object is accepted). Resume a paused subscription from its last unacknowledged event. Active or absent subscription: no-op. Repeated resume does not reset an active retry budget.","responses":{"204":{"description":"Resumed or already active/absent"},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}},"/v1/mailboxes/current/access":{"delete":{"operationId":"revokeCurrentMailboxAccess","security":[{"mailbox":[]}],"description":"Revoke this bootstrap credential and remove its webhook subscription; does not delete mail or revoke the owner's ordinary access. Reusing setup cannot restore access.","responses":{"204":{"description":"Revoked"},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"405":{"$ref":"#/components/responses/405"},"409":{"$ref":"#/components/responses/409"},"413":{"$ref":"#/components/responses/413"},"415":{"$ref":"#/components/responses/415"},"429":{"$ref":"#/components/responses/429"},"503":{"$ref":"#/components/responses/503"}}}}}}