Human session
Interactive sign-in with a DFNS passkey or Google. The browser holds a short-lived
session used while trading in the Demo, and re-authentication is another passkey
approval. Built for a person at the keyboard.
API key
A scoped key sent as
Authorization: Bearer <key> on every request, with no human in
the loop after approval. This is the standard for automated and market-maker access, the
same shape as an Alpaca or Coinbase API key. Bots trade on this same rail.Human session
A person authenticates in the browser: a DFNS passkey (FIDO2) or a Google sign-in that resolves to the same DFNS EndUser. Login returns a short-lived DFNS EndUser bearer that authorizes private REST calls while the person trades, and every step that moves value is a fresh passkey approval. WebSocket account channels never carry the bearer; the session mints a short-lived, account-scoped ticket instead. This model is interactive by design. It expects a human to approve, so it is not the way to run an unattended strategy. For the full setup, see For Humans and the Authentication section of the introduction.API key
An agent or a market maker authenticates with a key it holds, sent asAuthorization: Bearer <key> on every request. There is no session to refresh and no human
in the loop once the key exists: the program reads and trades on its own schedule. A key
belongs to one account and carries a fixed set of scopes.
The account owner approves a key once, in the browser, through the agent-connect device
grant. See the Market maker quickstart for the
end-to-end flow, and For Agents for the agent-specific runbook and
the optional MCP server.
Scopes
A key carries one or both scopes.trade includes everything read allows, because an
order you cannot read back is not useful.
Public market data (the book, trades, marks, funding) needs no key at all. A
read key that
tries to place an order is refused with 403 and the reason scope_insufficient.
What a key can never do
A key can read and trade one account. It can never deposit, never withdraw, never change the account’s Canton Party binding, and never manage keys (it cannot approve another agent, list keys or revoke keys). Those actions require the human passkey session. This is a security guardrail, not a convention. The venue authorizes a key against a default-deny allowlist: a key reaches only the named read and trade routes, and every other authenticated route, including deposits, withdrawals, the Party binding and key management, refuses the key with403 and the reason passkey_required. Because the default is deny,
any authenticated route added later stays closed to keys until a reviewed change explicitly
opens it. The guard runs in front of every authenticated route and is locked by tests.
The practical consequence for a market maker: a leaked or misused key is bounded. It can
trade the account it was issued for, which is why you protect it, but it can never move
money off the venue or take over the identity. Deposits, withdrawals and Party changes stay
behind the owner’s passkey.
Lifetime, renewal and revocation
A key expires on its own. An agent key lives 24 hours by default and can be approved for as little as 5 minutes or as long as 7 days; the owner chooses the lifetime at approval time. Expiry is checked against the clock on every request, so an expired key stops working the moment it lapses.- Renew. There is no self-service rotation for an agent key. When a key nears expiry, run the device grant again and have the owner approve a fresh one, so every extension of access stays behind a human approval.
- Revoke. The owner revokes a key at any time from the account with their passkey session
(
DELETE /v1/accounts/:accountId/api-keys/:keyId). Revocation takes effect immediately. - Inspect. A program reads its own key’s metadata with
GET /v1/api-keys/current: the account, scopes, display prefix, expiry and state. This route returns metadata only and never the secret.
401 with the closed reason expired, revoked, unknown or
malformed. The response never says whether some other key would have worked; the program
simply connects again.
Events arrive over WebSockets, not webhooks
Edel has no webhooks. Live data is pushed over the realtime WebSocket. Market channels (market.book, market.trades, and the rest) are open to everyone; your account events
(account.orders, account.fills, account.positions, account.balance, and the rest)
arrive on account channels behind a short-lived ticket you mint with your key. Do not poll
REST for state the socket already pushes. See the
Market maker quickstart for the connect flow and
the WebSockets tab for each channel.