{"service":"Decoy API","description":"Privacy-first accounts, service-specific email addresses and credentials, for AI agents acting on a person's behalf. Everything sensitive is end-to-end encrypted; the server stores ciphertext it cannot read.","documentation":"https://decoys.me/documentation","openapi":"/openapi.yaml","discovery":"/.well-known/oauth-authorization-server","connect":{"how":"OAuth 2.0 Device Grant (RFC 8628). Start at /oauth/device, hand the user the returned verification_uri_complete, then poll /oauth/token until they approve in the Decoy app on their phone.","start":"/oauth/device","token":"/oauth/token","bounded_access":{"how":"To request access to only SOME things — a named account, or \"only the accounts and inboxes I create myself\" — submit RFC 9396 authorization_details to /oauth/par and pass the returned request_uri to /oauth/device. The rows set the token's scopes; you do not also need to send `scope`.","endpoint":"/oauth/par","example":[{"type":"https://decoys.me/oauth/types/unlock","kind":"account","actions":["create","read_metadata","write"],"created_by_self":true},{"type":"https://decoys.me/oauth/types/unlock","kind":"message","actions":["read_metadata","unlock_content"],"created_by_self":true}],"note":"`created_by_self: true` is the bound: it covers what THIS agent creates and never the person's existing accounts or inboxes. The owner can narrow further when they approve. Ask for the least you need — revealing a saved password (account.unlock) and signing in as the user with a passkey (account.passkey_assert) are separate, and are the two most sensitive things you can request."}},"access_model":{"summary":"Access is by named permission (account.read, acctmail.send, memory.save, …), asked for with POST /api/agent/grant-request { permissions, <selection>, reason }. A refusal (403 INSUFFICIENT_GRANT or GRANT_EXPIRED) names required_permission and the permission_request to send unchanged. A scope with no matching permission authorises nothing: list endpoints return an empty list, per-resource calls return 403.","details":"/openapi.yaml — see \"Access: named permissions\""},"agent_api_prefix":"/api/agent"}