The server wallet authentication flow is designed to be idempotent — calling authenticate() multiple times with the same identity is safe and will reuse existing credentials when possible.

How It Works

authenticate()

  ├─ Token already in store? ──► Reuse it (no network call)

  └─ No token?

       ├─ Derive public key from accessKey
       ├─ POST /auth/create  (register identity)
       ├─ POST /auth/exchange (get access token)
       └─ Store token ──► Return session
On the first call, the SDK:
  1. Generates or accepts an accessKey (64-char hex string)
  2. Derives a public key from it
  3. Calls create to register the identity with the backend
  4. Calls exchange to obtain an access token
  5. Stores the token for future use
On subsequent calls with the same identity, the stored token is returned immediately.

Usage

import { ServerSignerClient } from '@abstraxn/server-signer';

const client = new ServerSignerClient({
  apiKey: process.env.ABSTRAXN_API_KEY!,
});

const session = await client.authenticate({
  userIdentity: 'merchant-backend-user-001',
  accessKey: process.env.SERVER_WALLET_ACCESS_KEY,  // optional on first run
  userName: 'Merchant Backend',
  userEmail: '[email protected]',
});

Parameters

ParameterTypeRequiredDescription
userIdentitystringYesUnique identifier for this server wallet user
accessKeystringNo64-char hex key. If omitted on first run, the SDK generates one
userNamestringNoDisplay name for the wallet user
userEmailstringNoEmail for the wallet user

Return Value

FieldTypeDescription
didCreatebooleantrue if this was a new identity, false if reusing existing token
accessTokenstringCurrent JWT access token
accessKeystringThe 64-char hex access key (generated or provided)
targetPublicKeystringPublic key derived from the access key
organizationIdstringOrganization ID for this wallet
walletAddressstringOn-chain wallet address

Access Key Management

The accessKey is the root secret for a server wallet identity. It is used to derive the public key that identifies the wallet on-chain.
If you lose the access key, you cannot recover the same wallet identity. Always persist it in a secure secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, etc.).
First run — let the SDK generate the key, then save it:
const session = await client.authenticate({
  userIdentity: 'merchant-backend-user-001',
});

// Persist this immediately
await secretsManager.set('SERVER_WALLET_ACCESS_KEY', session.accessKey);
Subsequent runs — provide the saved key:
const session = await client.authenticate({
  userIdentity: 'merchant-backend-user-001',
  accessKey: process.env.SERVER_WALLET_ACCESS_KEY,
});

Automatic Token Refresh

Authenticated API calls automatically handle expired tokens:
  1. A call receives a 401 Unauthorized response
  2. The SDK sends POST /auth/refresh with session credentials
  3. If the refresh succeeds, the access token is updated and the original call is retried
  4. If the refresh fails, the error is thrown to the caller
No configuration is needed — this behavior is built into every authenticated method (whoami, signTransaction, exportPrivateKey, etc.).

Identity Conflicts

If you call authenticate with a userIdentity that already exists but provide a different accessKey, the backend returns a 409 CONFLICT error:
ConflictError: userIdentity 'merchant-backend-user-001'
already exists with a different access key
This protects against accidental identity collisions. To resolve:
  • Use the original access key for this identity, or
  • Choose a different userIdentity string

Next Steps