Give each trading workload its own Ed25519 API key. Register a public key, attach the permissions it needs, and keep a separate interactive session available for administration and recovery. Polyester never receives the private key.
On Testnet, manage keys on https://api.testnet.polyester.com; Mainnet is coming soon.
Session or API key?
An API key cannot create its replacement, list or read key metadata, change its configuration, attach its own policy, or revoke itself. These operations require an authorized interactive session, even when the target is the key making the request. See Session login for obtaining one.
| Task | Interactive session | MFA |
|---|---|---|
| List or read keys | Required | No step-up |
| Create a key | Required | Enrollment and fresh step-up |
| Update or disable/enable | Required | Fresh step-up |
| Attach or clear a policy | Required | Fresh step-up |
| Revoke a key | Required | Fresh step-up |
Send the single-use proof in X-Auth-Step-Up. Obtain a new proof for each protected mutation;
see Multi-factor authentication.
An API key presented to a session-only operation is refused with HTTP 403 and AUTH_SESSION_KIND_NOT_ALLOWED.
Once configured, a key can make signed trading, cancellation, read, or money-movement requests where the endpoint accepts API keys and its policy permits the action. These requests do not prompt for interactive MFA. See Ed25519 API keys for signing, and Withdrawals and transfer security for movement authorization.
Create and authorize a key
Generate the keypair locally
Generate an Ed25519 keypair in your signing environment. Store the private key securely and submit only the public key. Use a label that identifies the workload and environment.
Register the public key
With an interactive session and fresh step-up, call CreateApiKey (REST create). The acting account must have accepted
the current terms. Save the returned keyId with your private-key configuration.
Choose Main Account or Subaccount scope at creation. A Subaccount key requires owner or admin access to that Subaccount. See Subaccounts and roles.
Attach the minimum policy
A newly registered key has no attached API-key policy. Before trading or moving funds, attach one
with SetApiKeyPolicy (REST policy binding), using a separate
fresh step-up. Policy attachment is a separate operation from updating key metadata.
See API key policies for actions, market limits, and Subaccount policy checks. Clearing the policy is owner-only and removes the key's permissions.
Verify from the workload
Configure the IP allowlist for the workload's egress addresses and test a permitted read. Confirm account scope and required permissions before sending trading traffic. Set an expiry after creation if needed; creation does not accept an expiry.
The user guide to API keys covers the interactive management screens.
List, read, and update
Use ListApiKeys (REST list) for visible non-revoked keys, or GetApiKey (REST read) for one key. Both require an
interactive session. Lists exclude revoked keys; disabled keys remain visible.
Change labels, display metadata, IP allowlists, status, or expiry with UpdateApiKey (REST update). The public key and account scope
are fixed. Register another key to replace either.
An IP allowlist update replaces the entire list. Omitting it leaves it unchanged; sending an empty list removes the IP restriction. Read the allowlist guide before changing network access on a live workload.
Conditional updates and conflicts
REST updates require If-Match with the latest key revision encoded as a quoted positive decimal
number. Use the revision from a fresh read. A successful update returns the resulting revision in ETag. Send only the fields you intend to change.
For ConnectRPC, provide expectedRevision and an explicit updateMask; only selected fields change.
Policy binding uses its own operation and does not take the key-update revision precondition.
A stale key revision returns HTTP 409. ConnectRPC reports aborted with AUTH_REVISION_CONFLICT. Read the key again, compare the current configuration with your intended
change, then retry only if that change is still appropriate. Obtain another fresh step-up for the
retry. Repeatedly resending the stale revision cannot resolve the conflict.
If a response is lost, read the current key before retrying. This also lets you detect an update that succeeded despite the client timeout. See Error responses for transport handling.
Disable, enable, and expire
Set status to DISABLED through UpdateApiKey to pause authentication. Re-enable it by setting ACTIVE. Both changes use the conditional-update procedure and require fresh step-up.
Re-enabling does not override expiry, policy restrictions, or the IP allowlist.
Set expiresAt to a future UTC time through an update. After that time the key cannot authenticate,
even if its status is ACTIVE. REST reports KEY_EXPIRED; the corresponding ConnectRPC
authentication detail is AUTH_KEY_EXPIRED on trading and balance APIs. See authentication errors.
Omitting expiry from a REST update preserves it; expiresAt: null clears it. On ConnectRPC,
select expires_at in the mask and omit its value to clear it. With no expiry set, the key has no
configured expiry deadline. Monitor expiry ahead of time so rotation can finish while both keys work.
Rotate without downtime
Rotation registers a second public key and overlaps two credentials on the same account. It does
not change the public key behind an existing keyId.
Prepare the replacement
Create a new keypair and register its public key through the interactive session. Use the same account scope, attach the required policy, and configure the intended IP allowlist and expiry. Keep the old key active during preparation.
Verify access and order control
Test the replacement from every egress path the workload uses. Verify that it can read and manage the account's existing orders with the required permissions. Orders belong to the account, so changing credentials does not move or duplicate them.
Move traffic and heartbeats
Switch workers to the replacement. Coordinate the dead-man switch heartbeat handover so one worker renews it for the intended account, symbol, and side. A new arm replaces the account's existing switch scope. Do not disarm the switch during the handover.
Reconcile uncertain writes using each endpoint's retry contract. See API key replay protection.
Revoke the old key
After the replacement handles traffic and heartbeats successfully, stop every old-key worker and revoke the old key through the interactive session. Verify the resulting key state and remove the old private key from the workload's secret storage.
lastUsedAt is approximate and can lag recent authentication. Use worker telemetry as well as key
metadata to confirm that the old credential is no longer in use.
Revoke and manage open orders
DeleteApiKey (REST delete) permanently revokes a key. It is
not a reversible disable. The key becomes REVOKED, disappears from lists, and cannot be re-enabled.
Use an owner session with fresh step-up.
For an immediate trading stop, use another authorized credential to cancel the account's orders and verify the result. The dead-man switch cancels open orders within its recorded scope when it fires; it does not cancel triggers. Cancel live triggers separately if they must stop placing orders.
Key changes must propagate before all subsequent authentication checks observe them. Do not treat revocation as cancellation of requests or movements already accepted.
Monitor changes and audit activity
The API key updates stream reports key configuration, including status, policy binding, revision, and update time. The API policy updates stream reports policy changes that can affect a key's permissions. Both use the protobuf encoding listed in their references. Use an authorized realtime connection and reconcile key metadata after a reconnect.
For Subaccount audit history, use ListSubaccountActivity (REST activity). Key activity uses
the API-key entity category. Events describe the action, actor, time, and available details;
security details depend on the caller's role. This read accepts authorized sessions or API keys.
Configuration updates and audit history serve different purposes: use metadata to establish current
state and activity records to investigate changes. Neither lastUsedAt nor the configuration stream
is a log of every signed request. See the error catalog when diagnosing a refusal.