Skip to main content
With a JWT in hand, authenticate the wallet client and operate wallets as the user: create, sign, and keep the session alive.
Before this: a Dynamic user JWT minted with your session public key bound in — see Sign In with Email OTP, Sign In with a Private Key, or Sign In with an External JWT — and access to the session private key.

Authenticate the wallet client

authenticateJwt installs the JWT as the bearer token for all subsequent calls. There is no token exchange: the client only checks the token’s structure (a compact JWS with three segments); the server validates it on every request. getSessionSignature keeps key custody with you. The session private key never enters the SDK — the SDK sends messages to your callback and uses the signatures it returns. signSessionMessage implements the callback for a stored JWK; a KMS- or HSM-backed signer works the same way as long as it returns the same encoding.
getSessionSignature must return the signature as lowercase hex: the raw 64-byte ECDSA P-256 r‖s, exactly as signSessionMessage produces. Base64 output corrupts the proof — base64 can contain /, which breaks the /-delimited composite the SDK sends to the keyshares relay.

Create wallets and sign

With the signer configured, use the client as usual. When you pass backUpToDynamic: true, the SDK automatically attaches a signed-session proof to the backup and recovery calls — it signs the JWT’s session ID and a single-use server nonce with your callback. Without a signer, those calls fail with a 400 from the keyshares relay for agent JWT sessions.

Reuse an existing wallet

Creation is a one-time step. On later runs, load the persisted walletMetadata and externalServerKeyShares from your stores instead of creating a new wallet, and sign directly:
Calling createWalletAccount on every run creates a new wallet each time. Create once, persist the returned artifacts, and reuse them for the life of the wallet.

Refresh long-running sessions

User JWTs are short-lived. refreshAuthToken refreshes the JWT using the current session, installs the replacement on the client, and returns it so you can persist it. The session signer you passed to authenticateJwt is preserved across refreshes.
Sign-in returns expiresAt — schedule refreshes ahead of it instead of waiting for a 401. The server caps how long a session can be extended via the JWT’s refreshExp claim. Past that limit, refreshAuthToken fails with a 401 and a new sign-in is required — refresh cannot extend a session indefinitely. For a human user, that means re-approving (a new OTP code or SIWE signature). For an autonomous agent with an agent signing token, re-authentication is just another programmatic sign-in.
refreshAuthToken also throws a descriptive error when the environment is configured for cookie-based auth: refresh responses then carry no JWT in the body, and agent flows require header-based JWTs.

Next steps

API reference

Last modified on July 17, 2026