Skip to main content

Documentation Index

Fetch the complete documentation index at: https://limitless-docs-ws-settlement-events.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

The PartnerAccountService creates sub-account profiles linked to the authenticated partner. Requires HMAC authentication with the account_creation scope.

Access

import { Client } from '@limitless-exchange/sdk';

const client = new Client({
  baseURL: 'https://api.limitless.exchange',
  hmacCredentials: { tokenId, secret },
});

// Use client.partnerAccounts.*

Server wallet mode

Creates a managed Privy wallet for the sub-account. Enables delegated signing — the partner submits unsigned orders and the server signs them.
const account = await client.partnerAccounts.createAccount({
  displayName: 'user-alice',
  createServerWallet: true,
});

console.log(account.profileId); // numeric profile ID
console.log(account.account);   // wallet address
New server wallets should be checked with checkAllowances() before the first delegated trade. If retryable targets are missing or failed, call retryAllowances() and poll again.

Allowance recovery

Server-wallet sub-accounts need delegated-trading approvals before they can trade. The partner allowance helpers use the Partner API only:
  • checkAllowances(profileId) calls GET /profiles/partner-accounts/:profileId/allowances
  • retryAllowances(profileId) calls POST /profiles/partner-accounts/:profileId/allowances/retry
  • both methods require HMAC credentials with account_creation and delegated_signing
  • profileId is the child/server-wallet profile id
import { APIError, RateLimitError } from '@limitless-exchange/sdk';

let allowances = await client.partnerAccounts.checkAllowances(account.profileId);

if (!allowances.ready) {
  const retryableTargets = allowances.targets.filter(
    (target) =>
      target.retryable &&
      (target.status === 'missing' || target.status === 'failed'),
  );

  if (retryableTargets.length > 0) {
    try {
      allowances = await client.partnerAccounts.retryAllowances(account.profileId);
    } catch (error) {
      if (error instanceof RateLimitError) {
        console.log(error.data?.retryAfterSeconds);
      } else if (error instanceof APIError && error.status === 409) {
        console.log('Retry already running; poll checkAllowances again shortly.');
      } else {
        throw error;
      }
    }
  }
}

if (allowances.targets.some((target) => target.status === 'submitted')) {
  // A sponsored tx/user operation was submitted by this retry request.
  // Poll checkAllowances() again after a short delay to observe confirmed chain state.
}
Recommended partner flow:
  1. Poll checkAllowances(profileId).
  2. If ready === true, continue.
  3. If targets are missing or failed with retryable === true, call retryAllowances(profileId).
  4. If retry returns submitted targets, poll checkAllowances() again after a short delay.
  5. If retry returns 429, wait retryAfterSeconds.
  6. If retry returns 409, wait briefly and call checkAllowances() again.

EOA mode

Creates a profile for an externally-owned address. The end user manages their own keys and signs orders themselves. EOA mode requires wallet ownership verification headers:
const account = await client.partnerAccounts.createAccount(
  {
    displayName: 'user-bob',
  },
  {
    account: '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed',
    signingMessage: '0x...',
    signature: '0x...',
  },
);
HeaderDescription
accountChecksummed Ethereum address (EIP-55)
signingMessageHex-encoded signing message
signatureHex-encoded signature from the wallet

Validation

  • displayName is optional, max 44 characters. Defaults to the wallet address if omitted.
  • Returns 409 Conflict if a profile already exists for the target address.
  • Cannot create a sub-account for the partner’s own address.
  • The SDK validates displayName length locally before sending the request.