access_refresh(recommended): a 15-minute access token plus a rotating refresh token. Extend the session by calling/refresh, and revoke it with/logoutor/logout-all.access_only(deprecated): a single JWT valid for 24 hours with no refresh or revocation. This is still the default whenauthModeis omitted.
Auth modes at a glance
Prerequisites
Signing challenges and transactions requires@solana/web3.js and bs58:
Step 1: Request a challenge
Request a challenge for your wallet. Thetype field selects how your wallet will sign, and accepts exactly two values:
Both prove wallet ownership and return the same tokens. Any other value returns a
400. Challenges expire after 5 minutes; request a new one if yours expires.
Step 2: Verify and get tokens
Sign the challenge with your wallet, then submit the signature to/verify. Add authMode: "access_refresh" to the request body to receive refresh tokens. The challenge step is identical for both auth modes.
For message signing:
access_refresh response:
If you omit
authMode, you get the deprecated access_only response instead: a single 24-hour token (read accessToken, not token, once you migrate), returned with Deprecation and Link headers.
Using the access token
Include the access token in all authenticated requests:Refresh the access token
BeforeexpiresAt, call /refresh with the current refresh token to get a new access token and refresh token. Every call rotates the refresh token: replace both stored tokens with the response. Do not send authMode here.
access_refresh verify response:
- Rotate and replace. Each successful
/refreshinvalidates the refresh token you sent and returns a new one. Always store the newest pair. - Retry grace. Repeating the same
/refreshrequest within a short grace window (a network retry) is tolerated and returns a valid pair, so a dropped response does not lock you out. - Reuse is rejected. Presenting an old refresh token outside that grace window returns
401, and the session is revoked. Send the user back through the challenge flow.
Handle 401 on protected routes
A 15-minute access token expires mid-session more often than a 24-hour one did. On a401 from any protected route, refresh once and retry the request. If /refresh itself returns 401, start a new challenge.
Log out
Revoke refresh tokens when the user signs out. Access tokens already issued remain valid until they expire (up to 15 minutes); logout stops new access tokens from being minted. One session (the device holding this refresh token). No authentication required, always returns200:
/logout revokes the single refresh token you pass. /logout-all invalidates every refresh token issued for the wallet, so all devices must re-authenticate.
Migrate from access_only
- Send
authMode: "access_refresh"on/verifyfor bothtype: "message"andtype: "transaction". The challenge step is unchanged. - Read
accessToken, nottoken. StoreaccessToken,refreshToken, andexpiresAt. Keep the refresh token out of logs and analytics. - Refresh before
expiresAt. Call/refreshwith the current refresh token and replace both tokens with the response. - Handle
401by refreshing once, then re-login. On a401from a protected route, refresh and retry once; if the refresh returns401, start a new challenge. - Wire logout. Call
/logouton sign-out, and/logout-allto revoke every session for the wallet.
Sequence after migration
Token lifecycle
Security notes
What happens if a token is leaked
The tokens grant limited access. An attacker with a leaked access or refresh token can:- Cancel orders: This stops an order from filling, but does not withdraw funds. Withdrawal requires signing a transaction with the wallet private key.
- Edit price-order parameters: Updating a price order’s trigger price or slippage does not require transaction signing. DCA orders cannot be edited.
- Withdraw funds: All withdrawal operations require the wallet owner to sign a transaction. The vault’s funds remain secure.
- Create new orders: Depositing tokens requires signing a deposit transaction with the wallet.
/logout-all to cut off every session. If the wallet private key is also compromised, an attacker could sign transactions and withdraw funds from the vault.