A policy is a reusable set of permissions. Polyester uses two kinds:
- An API key policy limits what one API key can do. A key without a policy can only create and list deposit addresses.
- A Subaccount policy is the ceiling for a Subaccount. No member role and no API key can exceed it.
Both are managed through PolicyService with an interactive session; every policy read and write
accepts only a session token. API keys cannot create, change,
or attach policies.
How a request is checked
For an API key request, Polyester applies these checks in order. Each one can only remove permissions:
The effective permission is the intersection of the two policies. Attaching a broad API key policy to a key on a restricted Subaccount does not widen the Subaccount. Main Account keys have no Subaccount policy, so only the API key policy applies.
Interactive members follow the same order with their role in place of the API key policy.
Policy actions
Both policy kinds use the PolicyAction enum. A write action also grants the matching read.
| Action | Allows |
|---|---|
TRADE_SPOT | Every spot order mutation, cancel-all, cancel-all-after, and trigger placement or change. Includes READ_SPOT. |
READ_SPOT | Spot orders, trades, subscriptions, cancel-all dry-run, and effective fee rates. Never a mutation. |
READ_BALANCES | Balances, balance history, and equity. |
READ_INTERNAL_TRANSFERS | Ledger transfer history (ListTransfers). |
INTERNAL_TRANSFER | Trading-to-Trading internal transfers and Trading-to-Funding withdrawals. Includes READ_INTERNAL_TRANSFERS. |
EXTERNAL_WITHDRAW | Trading withdrawals to an external Network. Destination whitelists are checked separately. |
READ_ADDRESS_BOOK | Saved, recent, and whitelisted destinations. |
MANAGE_ADDRESS_BOOK | Address-book writes for sessions. On an API key policy it grants reads only, because writes need a session. |
READ_AUTO_WITHDRAW | The auto-withdraw rule and its runs. |
MANAGE_AUTO_WITHDRAW | Changing the auto-withdraw rule. Also needs EXTERNAL_WITHDRAW. API keys can never change a rule. |
SWAP | Quoting, creating, and reading Swaps of the account's own Trading balance. |
Deposit-address creation and listing are outside policy scope. No policy action controls them, and an attached policy never blocks them. See Deposits.
Market scope
spotMarketScope is ALL or ALLOWLIST. ALL allows every current and future market. ALLOWLIST allows only the Pairs listed in spotMarkets, by symbolId from the spot configuration. An ALLOWLIST with no markets is invalid.
Subaccount policies
A Subaccount policy carries the actions and market scope above, plus enforced limits:
| Field | Effect |
|---|---|
maxOrderNotional | Largest single-order notional, in quote microunits (one unit is 0.000001 USDT). 0 means no cap. Exceeding it returns POLICY_MAX_NOTIONAL. |
maxOpenOrders | Most resting orders at one time. 0 means no cap. Reaching it returns POLICY_MAX_OPEN_ORDERS. |
tradingHalted | Rejects new orders and exposure-increasing changes with POLICY_TRADING_HALTED. Cancels and pauses still work. |
locked | Write-protects the policy. Only the owner can lock, unlock, or change a locked policy. |
reviewAt and expiresAt are governance metadata only. They do not disable the policy.
Every Subaccount policy keeps a mandatory read-only floor: READ_BALANCES, READ_SPOT, READ_INTERNAL_TRANSFERS, READ_ADDRESS_BOOK, and READ_AUTO_WITHDRAW. With no policy attached, a
Subaccount uses exactly that floor, so it cannot trade or move funds.
Manage Subaccount policies
Each operation lists its method, then who can call it.
- List and read ·
ListSubaccountPolicies,GetSubaccountPolicy
Owner; current members for the attached policy. - Create ·
CreateSubaccountPolicy
Owner; an admin only when attaching in the same request. - Update ·
UpdateSubaccountPolicy
Owner; admins only for unlocked policies. - Delete an unused policy ·
DeleteSubaccountPolicy
Owner only. - Attach or replace ·
SetSubaccountPolicy
Owner; admins unless the current policy is locked. - Clear ·
SetSubaccountPolicywithpolicyId0
Owner only.
API key policies
An API key policy has a name, description, actions, market scope, and an isTemplate flag for
reuse. Read them with ListApiPolicies and GetApiPolicy.
Create one with CreateApiPolicy; set assignToKeyId to attach it to a key in the same request, which uses one step-up proof. Attach or
replace a policy later with SetApiKeyPolicy. Clearing a key's policy (policyId 0) is
owner-only and leaves the key with no permissions beyond deposit addresses.
A policy that is still attached cannot be deleted with DeleteApiPolicy; the request fails with AUTH_POLICY_IN_USE.
Updates with UpdateApiPolicy take an updateMask and expectedRevision. A stale revision fails before any change.
Right after a grant
A policy change can take a moment to reach every service. A request sent in that moment, which a
grant you just made allows, is not refused with a permission error. Orders, triggers, withdrawals,
and internal transfers answer a retryable Unavailable (REST 503) with the message "policy is not
mirrored yet; retry": UNAVAILABLE on orders and triggers, and SERVICE_UNAVAILABLE on withdrawals
and internal transfers. Nothing was placed, reserved, or moved. Retry with backoff and the same
idempotency identity. A refusal that the current policy confirms stays a permission error, such as POLICY_SPOT_TRADE_DENY; do not retry it unchanged.
API key lifecycle
Creating, updating, disabling, rotating, and revoking keys are session-only operations, and each
mutation needs a fresh step-up. Attach the policy with SetApiKeyPolicy after you create a key;
until then the key can only create and list deposit addresses. Every step, from registration to
rotation without downtime, is in API key lifecycle.
IP allowlists
Restrict where a key can be used with ipWhitelist, a list of up to 32 unique IPv4 or IPv6 CIDRs.
An empty list means no restriction. Requests from outside the list fail authentication with REST
code IP_NOT_ALLOWED (ConnectRPC AUTH_IP_NOT_ALLOWED). See API key IP allowlists.
Common refusals
| Code | Meaning |
|---|---|
API_KEY_POLICY_REQUIRED | The key has no policy attached. |
API_KEY_ACTION_DENY | The key's policy does not allow the action. |
API_KEY_MARKET_DENY | The key's policy does not allow this market. |
SUBACCOUNT_POLICY_DENY | The Subaccount policy does not allow the action. |
POLICY_SPOT_TRADE_DENY | Spot trading is not allowed by the effective policy. |
POLICY_MARKET_DENY | The Subaccount policy does not allow this market. |
ROLE_SPOT_TRADE_DENY | The member's role cannot trade. |
The exact code depends on the endpoint. See Error codes for the full catalog, and the API reference for field schemas.