credentialRef.
The surface splits into three tiers by what each call needs:
The MVP supports fully collateralized spot trading only. Margin, leverage, and any non-spot order fields are rejected. Withdrawals are out of scope - connect trade-only keys with no withdrawal permission.
Declare the credential requirement
Agents declare the Kraken credential they need incircuit.toml. Circuit turns this into a start-time credential picker for the user and seats a runtime permit scoped to the selected credential.
trade = false. Trading requires read = true because Circuit checks live balances before submitting an order. Trading agents also declare minimumAllocationUsd; users choose a Kraken virtual funding allocation at or above that amount when starting the session.
Users connect credentials from Settings in the web app or from the CLI:
The credential reference
Every credentialed call carries acredentialRef, never a key or secret. The credential the user selected when starting the session is exposed as a ready-made ref on agent.credentials:
trade = true, agent.allocation contains invocation-start available session cash as kraken:allocation:USD and each positive base-asset inventory the session may sell. Available cash subtracts filled net deployment and accepted orders’ unfilled limit notional from the original slice. Base entries carry the exact decimal krakenMetadata.availableBaseVolume enforced by the sell gate:
kraken:allocation:USD; it is the session’s virtual-allocation ceiling, not a claim that the account already holds the quote asset a particular order needs. Prompt the agent to inspect whole-account balances and choose /USD or /USDC appropriately. The live order gate still requires enough free balance in the concrete quote, and Circuit does not convert holdings automatically at start.
The API key and secret are sealed server-side; the SDK and your agent code only ever hold the reference. Circuit turns it into a signed Kraken request at the signing boundary - the same model as the server-resolved wallet address used by the other venues.
Pairs and assets
Kraken pairs and assets are venue-namespaced with aKRAKEN: prefix. Both the slashed and concatenated spellings are accepted everywhere ("KRAKEN:XBT/USD" and "KRAKEN:XBTUSD" are the same pair); responses (open orders, order status) return the concatenated form ("KRAKEN:XBTUSD") - compare pairs case-insensitively after stripping the / rather than by raw string equality. Balances come back as venue-namespaced assets ("KRAKEN:XXBT", "KRAKEN:ZUSD"). All amounts are strings to preserve precision.
Order limits. Trading is enabled for a fixed pair set: XBT, ETH, SOL against USD or USDC. Sell minimums are 0.0001 XBT, 0.01 ETH, and 0.1 SOL. Buy minimums are 0.000102 XBT, 0.0102 ETH, and 0.102 SOL: the extra 2% keeps a fully filled minimum buy sellable after its base-denominated Kraken fee. A positive partial-fill residue below the sell minimum remains accounted to the session but is venue dust, so it is not exposed as spendable inventory. A per-order maximum notional cap applies (volume × price in USD). Orders outside these bounds are rejected before signing.
Place Order
Place a spot order. In auto mode the order is claimed, signed, and submitted immediately; in manual mode it is captured as a suggestion for the user to approve (data is then a suggestion envelope { suggested: true, suggestionId } - see Manual vs Auto Mode).
credentialRef(object):{ kind: "exchange", id: string }- the connected exchange credential.order(object):pair(string): Venue-namespaced pair, e.g."KRAKEN:XBT/USD".side(string):"buy"or"sell".type(string):"limit". Market orders are rejected. A limit price bounds execution; for buys it also gives virtual-allocation enforcement a maximumvolume × pricereservation. Use a marketable limit (a price at or through the touch) for immediate fills.volume(string): Order volume in base-asset units.price(string): Limit price. Required.
validate(boolean, optional): Whentrue, Kraken validates the order without placing it (dry-run / preflight). No order id is returned.idempotencyKey(string, optional): Durable retry key for auto-mode orders. SDKs generate one automatically; provide a stable key only when retrying the same logical order after a process restart. Circuit derives Kraken’scl_ord_idfrom it, so an ambiguous submission is recovered by status lookup rather than resubmitted.expiresAt(string | null, optional): ISO 8601 timestamp. In manual mode, the suggestion expires at this time.
success(boolean)data(object):orderIds(string[]),clientOrderId(string | null),description(string | null). For avalidatedry-run,orderIdsis empty.error(string | null)
USD or USDC), but each buy must be funded by the chosen quote’s live free balance. A buy reserves exactly volume × limit price; Circuit instructs Kraken to take buy fees from acquired base, so fees cannot overdraw the quote allocation. Sells take fees from quote proceeds and may use only base inventory acquired by this session’s fills, minus filled sells and open sell reservations. Orders from another session never establish ownership.
Cancel Order
Cancel an order by its Kraken order id. Manual mode captures the cancel as a suggestion, same asplaceOrder.
credentialRef(object): The exchange credential.orderId(string): The Kraken order id (txid) to cancel.idempotencyKey(string, optional): Auto-generated when omitted.
data is { count: number } - the number of orders canceled.
Read Balances
Read the credential’s whole-account Kraken balances. Each entry carries both the totalbalance and the available amount (total minus funds on hold in open orders). Use this read to choose a funded quote asset and confirm venue availability; never use it as the session’s ownership or spending limit. The kraken:allocation:USD allocation entry is the session’s deployable virtual cash, and Circuit’s order gate is the final authority on cash and sellable inventory.
data is an array of { asset, balance, available, hold } (all strings; asset is venue-namespaced).
Open Orders / Order Status
openOrders lists the credential’s currently open orders (optionally filtered by pair); orderStatus reads a single order by id. Because openOrders is whole-account state, retain the ids returned by this session’s placeOrder calls and cancel only those ids - never cancel every order on a pair shared with another session or a human.
orderId, clientOrderId (string | null), pair (venue-namespaced), side, type, price (string | null), volume, filled, status, openedAt / closedAt (ISO 8601 | null).
Order Book / Ticker (public)
Public market data - no credential required. These are strategy inputs, not execution reads. Circuit retries rate-limited public reads with bounded backoff, so a transient429 doesn’t fail your loop.
orderBook-datais{ pair, asks, bids }, each level{ price, volume, timestamp }.depth(string, optional) caps the number of levels.ticker-datais{ pair, ask, bid, last, volume }(all strings).
Common Errors
Errors are returned in theerror field of the response.
Notes
- All balance, price, and volume amounts are strings to preserve precision.
- Money writes are exactly-once by
idempotencyKey: an ambiguous submission is recovered by looking the order up via its client order id, never blindly resubmitted. - Kraken account balances are not merged into the virtual allocation - read them live via
balanceswhen a decision needs them. - The API key and secret never reach the SDK, your agent, or the stateless engine - only the sealed credential and the signing boundary do.
- Credentials are connected via
circuit kraken connector the web app; deleting a credential is done from the web app’s Settings → Kraken screen (blocked while any live session still uses it). There is no CLI disconnect command.
See Also
- Manual vs Auto Mode - How order/cancel suggestions are captured and approved
- Suggestions - Control suggestion expiry for manual-mode suggestions
- Error Handling - Response envelope and error patterns