A client carries one or the other, never both. The maker rejects a request with both as
400 attribution_conflict.
Neither credential authorizes a claim, a refund, or any movement of funds. The per-swap swapAuth does that, and it stays separate.
Organization keys (client-side)
The key is a label, not a credential. Anyone can copy it, so it buys the caller no rate limit, discount, or access of its own. That is what makes it safe to ship in a bundle. The private half is used only to claim a revenue-share payout on the organization’s own machine; no KaleidoSwap software asks for it.- The key is sent only on
POST /v2/swap/{submarine,reverse,chain},POST /v2/swap/pay, and the corridor’sPOST /v1/swap, and only tomakerUrl, which must behttpsunless it is a loopback address. - A value that is not a valid curve point is rejected locally.
- The maker answers each creation with
X-Kaleido-Attribution: none | api_key | org_key. If an org-keyed creation comes back as anything else, the swap still goes ahead and the SDK logs a warning. - A page on another origin needs the maker’s edge to allow
X-Kaleido-Org-Keyin CORS. An extension’s host permissions make that moot. PayThroughClientandkaleidoswapHttpTransporttake anorgKeyoption too.
Organization API keys (servers)
- It is sent only to the configured maker URL, never to Esplora or a second maker. The URL must be
https(or loopback) and may not carry userinfo. - Native clients decline redirects. In the browser
fetchowns redirects, so a hop away from the maker is reported after the fact instead. - Nothing renders the secret: Rust’s
Debugredacts it, and Python and JavaScript expose only the key ID and environment. - A malformed key is rejected locally instead of reaching the maker as a
401, the same answer a revoked key gets.
includeLocalVariables or with_locals, pytest --showlocals) can read the key off a stack frame. Scrub apiKey in their before-send hook.