Use a session when your partner app acts for a signed-in user. Wallet login returns a bearer access token, encoded as a JWT, for that user's account. Use Ed25519 API keys for unattended bots and market-making workloads.
Testnet is the public environment and runs the latest release. Mainnet is coming soon. The examples
below use https://api.testnet.polyester.com; see regions and connectivity for regional API hosts.
Sign in with a wallet
The wallet must be an externally owned account (EOA) that controls the target smart account. auth.v1.AuthService issues the login challenge and verifies the signed response. Signing
the login message does not authorize a transaction.
Request a challenge
Call CreateWalletChallenge or POST /v1/auth/wallet-challenge.
Supply smartAccountAddress, the controlling wallet's signerAddress, your app's origin as uri, and purpose: "LOGIN".
The origin includes scheme, host, and an optional port, without a path, query, fragment, or
trailing slash. In a browser, it must match the request's Origin header. The response contains
the canonical EIP-4361 message and expiresAt. The challenge expires after five minutes.
Sign the returned message
Ask the wallet to sign the exact UTF-8 bytes of message using personal_sign, with EIP-191
semantics. Do not hash, edit, or reconstruct the message. Present the server-issued message
to the user as the login request.
Verify the signature and receive a session
Call LoginWithWallet or POST /v1/auth/login/wallet with smartAccountAddress, the unchanged message, and the wallet's signature.
Success returns accessToken, expiresAt, accountId, session, and username when one is
set. The initial session
level is PRIMARY_AUTHENTICATED. The challenge is consumed on successful login; request a
new challenge after an expired, replaced, or consumed challenge fails.
The API field names above use JSON spelling. Generated Protobuf clients expose the equivalent fields in their language's naming style. Neither challenge creation nor wallet verification requires an existing session.
Login does not accept terms on the user's behalf. After explicit user consent, call AcceptTerms (REST). Acceptance is required before creating
a Subaccount, API key, or deposit address.
Send the session token
Use the returned access token in the HTTP header for REST and ConnectRPC requests:
Authorization: Bearer <accessToken>Do not put bearer tokens in URLs or logs. Keep them in protected application storage and send them only to the intended API host over TLS. Anyone holding a token can act with its authority.
Read the current identity and assurance level with Me or GET /v1/auth/me. A session identifies the root account;
access to each Subaccount still depends on the user's role and applicable policy. See Subaccounts and roles.
Lifetime and renewal
Session access tokens have a default lifetime of 24 hours. Use the response's expiresAt as the expiry for the token you received rather than calculating a deadline from that default. MFA responses return the replacement token's deadline as accessTokenExpiresAt.
There is no public refresh-token exchange. When the session expires, repeat the wallet challenge and login flow. Do not invent a refresh endpoint or keep retrying with an expired bearer token.
Successful MFA verification and factor enrollment can return a new MFA-elevated accessToken.
Replace your stored token and expiry with the returned values. This requires user verification
and is not a background refresh flow.
Token expiry and recent MFA are separate deadlines. A session token can still be valid when an operation requires the user to complete MFA again.
Operations that require a session
The API reference marks session-only methods as "Session token". An API key cannot call these methods, even with a permissive API-key policy. Important groups include:
- API key administration ·
CreateApiKey,ListApiKeys,GetApiKey,UpdateApiKey, andDeleteApiKey.
Reading key metadata also requires a session. See API key lifecycle. - Policy administration ·
ListApiPolicies,SetApiKeyPolicy, andSetSubaccountPolicy.
Reading, creating, updating, deleting, and assigning API-key and Subaccount policies require a session. See API key policies. - Account and identity settings ·
AcceptTerms,GetProfile, andResolveAccount.
Profile changes, username operations, and social verification also require a session. - Subaccount administration ·
CreateSubaccount,InviteSubaccountMember, andGetEffectiveSubaccountPermissions.
Creation challenges, updates, member lists, role changes, removals, invite responses, and member-MFA settings require a session. This does not make every Subaccount read session-only. - Saved destinations ·
CreateAddressBookEntryandCreateAddressBookTag.
Entry creation, updates, deletion, copying, and tag mutations require a session. Authorized address-book reads can accept API keys. - MFA ·
ListMFAFactorsandBeginMFAChallenge.
Factor enrollment, challenges, factor management, and recovery-code rotation require an interactive session.
These examples are not a replacement for each operation's authentication requirements.
Wallet-based withdrawals and auto-withdraw rule changes also use sessions. Conversely, Me accepts either a session or an API key.
Order-entry trade WebSockets require API keys.
An API key sent to a session-only method receives AUTH_SESSION_KIND_NOT_ALLOWED with HTTP 403. REST returns a problem response; ConnectRPC returns permission_denied with an auth.v1.AuthErrorDetail. Authenticate with a user session instead of retrying the same key.
See error responses and error codes.
Complete step-up MFA
Primary wallet login does not satisfy every protected operation. A request can require a recent MFA-elevated session or a separate fresh proof for one protected action.
For AUTH_MFA_ELEVATION_REQUIRED, begin an MFA challenge with purpose MFA_CHALLENGE_PURPOSE_SESSION_ELEVATION. For AUTH_STEP_UP_REQUIRED, use MFA_CHALLENGE_PURPOSE_FRESH_STEP_UP instead.
Call BeginMFAChallenge, then
complete the available factor with VerifyTOTPChallenge, FinishPasskeyChallenge,
or VerifyRecoveryCodeChallenge.
Replace the bearer token with the returned accessToken.
A fresh-step-up response also supplies stepUpToken and stepUpExpiresAt. Send that proof in X-Auth-Step-Up alongside the bearer access token on the protected request. The proof is bound
to the account and session, and is for one protected action.
Authorization: Bearer <accessToken>. Do not reuse a fresh
proof for a different action or across independent requests.API key mutations, policy mutations, factor deletion, and recovery-code rotation are examples that need fresh step-up. Requirements for other actions can depend on enrollment or the user's role. Follow multi-factor authentication for enrollment, factor availability, and operation-specific requirements.
Log out
Stop authenticated requests, close the app's private streaming connections, and remove the access token, step-up proof, and connection and subscription tokens from memory and persistent storage. Prevent pending work from restoring a token or reopening a connection after logout.
There is no public logout or session-revocation operation. Clearing your app's credentials does not invalidate copies of an issued bearer token; treat them as usable until their expiry. Disconnecting a wallet also does not revoke a JWT already issued to the app.
Choose sessions or API keys
Choose sessions for signed-in user experiences, account administration, consent, and MFA. Your app must handle token expiry and let the user complete wallet and MFA prompts.
Choose Ed25519 API keys for unattended trading. Restrict each workload with API key policies and IP allowlists. Keep the administrative session separate from the bot's credentials.