Use this file to discover all available pages before exploring further.
Para’s Server SDK can import a session that a user created in your client application. This lets your backend perform authenticated operations for that user, including signing, without asking the user to re-authenticate for the server request. Session validity and duration are enforced by the Para API and the API key’s session length configuration.
Export the authenticated client session, send it to your backend over HTTPS, then import it into a fresh ParaServer instance for the request.
Create a new ParaServer instance for each imported session. A server SDK instance holds one active session at a time, so reusing one instance across users can mix request state.
waitAndExportSession() waits until the SDK has reached an authenticated state before reading session data. Use it for handoff flows immediately after login.
If your backend needs to sign for the user, do not export with { excludeSigners: true }. That option removes the wallet signer data required for server-side signing.
If your backend only needs to validate the user session and will not sign, you can export without signer data:
Import the serialized session before running user-authenticated operations:
import { Para as ParaServer } from "@getpara/server-sdk";import express from "express";const app = express();app.use(express.json());const paraApiKey = process.env.PARA_API_KEY;if (!paraApiKey) { throw new Error("PARA_API_KEY is required");}app.post("/api/sign-message", async (req, res) => { const { session, message } = req.body; const para = new ParaServer(paraApiKey); await para.importSession(session); if (!(await para.isSessionActive())) { return res.status(401).json({ error: "Session expired" }); } const sessionExtended = await para.keepSessionAlive(); if (!sessionExtended) { return res.status(401).json({ error: "Session expired" }); } const walletId = para.findWalletId(); const result = await para.signMessage({ walletId, messageBase64: Buffer.from(message).toString("base64"), }); return res.status(200).json({ walletId, signature: result.signature, });});
keepSessionAlive() extends the active imported session according to the API key’s configured session length. It returns false if the session cannot be extended.
Each exported session belongs to one authenticated user. Import each session into its own ParaServer instance when your backend handles multiple users or parallel requests:
import { Para as ParaServer } from "@getpara/server-sdk";async function signForImportedSession(session: string, message: string) { const para = new ParaServer(process.env.PARA_API_KEY!); await para.importSession(session); const walletId = para.findWalletId(); return para.signMessage({ walletId, messageBase64: Buffer.from(message).toString("base64"), });}const [firstSignature, secondSignature] = await Promise.all([ signForImportedSession(firstUserSession, "Message for first user"), signForImportedSession(secondUserSession, "Message for second user"),]);
Once a user is signed in, you can request a Para JWT token. This token will provide attestations for the user’s ID, their identity, and any wallets they have provisioned via your application.To request a token, use the issueJwt method. The method returns the token itself as well as the JWKS key ID (kid) for the keypair that signed it.
The token’s expiry will be determined by your customized session length, or else will default to 30 minutes. Issuing a token, like most authenticated API operations, will also renew and extend the session for that duration.
The token’s aud field will be set to your API key’s unique ID, linking it specifically to your application.
Depending on the user in question, a decoded token payload might resemble the following:
For non-Node.js servers or scenarios where you only need to validate a session without importing it, Para provides dedicated verification endpoints:
// Client-side: Get a verification tokenconst verificationToken = await para.getVerificationToken();// Send to your serverawait fetch("/api/verify-session", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ verificationToken }),});
On your server, verify the token against Para’s API.
Use your Secret API Key from the Developer Portal to authenticate requests to the verification endpoints. This key is different from the public-facing API Key used in the Para client.
Session length is configured per API key in the or CLI. The Para API enforces that duration, and keepSessionAlive() extends the active session according to the configured value.
refreshSession() starts a login or refresh flow and returns a login URL. For imported server sessions, use keepSessionAlive() to extend the active session.
Create a fresh server instance per session: Initialize a new Para Server SDK instance for each imported user session or request.
Secure session transport: Always use HTTPS when transferring sessions between client and server. Do not log serialized sessions.
Export signer data only when needed: Use { excludeSigners: true } only when the server does not need to sign.
Validate before operations: Check that the imported session is active before performing authenticated operations.
Handle expiration explicitly: If the session is expired or cannot be extended, ask the client to authenticate again and export a new session.
Use verification tokens for auth-only checks: When you only need to verify who the user is, use verification tokens instead of importing a full session.
Configure session length intentionally: Set the API key’s session length in the Developer Portal or CLI based on your application’s security model.
To verify that a wallet address matches one of your users’ embedded wallets, you can send a request to one of the following endpoints:
Environment
URL
BETA
https://api.beta.getpara.com/wallets/verify
PROD
https://api.getpara.com/wallets/verify
Use your Secret API Key from the Developer Portal to authenticate requests to this endpoint. This key is different from the public-facing API Key used in the Para client.
Pass the address for the wallet in the POST request body:
Node.js
// Server-side verificationapp.post("/api/verify-wallet", async (req, res) => { const { address } = req.body; if (!address) { return res.status(400).json({ error: "Missing address" }); } // Set the correct URL based on your environment const verifyUrl = "https://api.beta.getpara.com/wallets/verify"; const response = await fetch(verifyUrl, { method: "POST", headers: { "content-type": "application/json", "x-external-api-key": "YOUR_SECRET_API_KEY" }, body: JSON.stringify({ address }), }); if (response.status === 404) { return res.status(404).json({ error: `Wallet not found with address: ${address}` }); } const { walletId } = await response.json(); return res.status(200).json({ walletId });});
To learn more about using sessions on the server, check out this example. Each example route will have both pregen and session based routes for you to test with.