Skip to main content
The Programmatic API enables partners to build integrations that create and manage user accounts, place orders on behalf of users, and operate with fine-grained access control — all through HMAC-authenticated API tokens with scoped permissions.

Join the Limitless Builders Chat

Building a partner integration? Join the Builders Chat on Telegram for API and SDK updates, integration help, and to connect with other builders.
Building a bot or trading for yourself? You do not need to apply for the Programmatic API. Derive a scoped API token with the trading scope from the Authentication page and start trading immediately. The Programmatic API and the application below are for platforms and partners that need to create and manage sub-accounts on behalf of their users.
HMAC credentials contain a secret key and must only be used in backend or BFF environments. Never expose them in browser-side code.
Recommended setup for production integrations:
  • Store the real HMAC credentials on your backend. The tokenId and secret should never leave your server infrastructure.
  • Use the SDK server-side to sign partner-authenticated requests. All trading, account creation, and delegated signing calls should be made from your backend.
  • Expose only your own app-specific endpoints to the frontend. Your frontend talks to your backend API — your backend talks to the Limitless API.
  • Keep public market reads in the browser. Unauthenticated endpoints like market data and orderbooks can be called directly from the frontend.

Maintenance awareness

Production integrations should check Maintenance Mode before submitting trading actions and handle 425 Too Early responses with a trading-mode code from trading endpoints. During maintenance, trading can temporarily become post-only, cancel-only, or disabled.

Overview

The programmatic API introduces three capabilities:

Partner lifecycle

1

Bootstrap your partner account

Create a standard Limitless account by logging in with your wallet at limitless.exchange. This gives you a profileId and wallet address.
2

Get partner capabilities enabled

Apply for programmatic API access. The team will review your application and enable token management and allowed scopes on your account.

Apply for Programmatic API Access

Fill out the partner application form to get started. You’ll need your Limitless wallet address from Step 1.
3

Derive a scoped API token

Authenticate with your Privy identity token and call POST /auth/api-tokens/derive to create a scoped token. The response includes a tokenId and secret — store the secret securely, it is only returned once.
4

Create sub-accounts

Use the scoped token to create sub-accounts for your end users. Choose server wallet mode for Web2 integrations (delegated signing) or EOA mode for Web3 users who manage their own keys.
5

Trade on behalf of sub-accounts

With the delegated_signing scope and server wallet accounts, submit unsigned orders — the server signs them automatically. GTC (resting limit), FAK (fill-and-kill limit), and FOK (fill-or-kill market) order types are supported.GTC order — stays on the orderbook until filled or cancelled:
FAK order — matches immediately up to available size and cancels any remainder:
FOK order — executes immediately at market price or is cancelled entirely:

Scopes

Scope requirements by operation

Sub-account modes

Server wallet (Web2 partners)

Set createServerWallet: true when creating a sub-account. The server provisions a managed Privy wallet and links it to the profile. The partner submits unsigned orders and the server signs them via the managed wallet.
Server wallet mode requires both account_creation and delegated_signing scopes on your API token.

Allowance readiness before trading

Before placing the first delegated order for a server-wallet child profile, check live allowance state:
  1. Poll GET /profiles/partner-accounts/:profileId/allowances.
  2. If ready=true, continue with delegated trading.
  3. If targets are missing or failed with retryable=true, call POST /profiles/partner-accounts/:profileId/allowances/retry.
  4. If retry returns submitted targets, poll GET again after a short delay.
  5. If retry returns 429, wait retryAfterSeconds.
  6. If retry returns 409, wait briefly and call GET again.

Lifecycle after a trade

For server wallet sub-accounts, it helps to treat trading, market resolution, and redemption as separate stages:
  1. Order execution - Place and cancel orders through POST /orders or the SDK DelegatedOrderService.
  2. Portfolio resolution state - Portfolio endpoints such as GET /portfolio/positions and GET /portfolio/{account}/positions may later show status: RESOLVED and winningOutcomeIndex once the winning side is known.
  3. On-chain payout settlement - Winning positions become redeemable only after the underlying conditional token payout has been reported on-chain.
winningOutcomeIndex is an index into the fixed outcomeTokens: ['Yes', 'No'] array: 0 means YES resolved, 1 means NO resolved, null means not yet resolved. For negrisk groups, the field is set on the individual sub-market that resolved YES.
status: RESOLVED and winningOutcomeIndex in the portfolio response do not by themselves guarantee that the underlying conditional token position is already redeemable on-chain. Resolution in the API can appear before the CTF condition has been settled on-chain.
If your integration checks settlement directly on-chain, wait until the payout vector has been posted before attempting redemption. For CTF-based positions, a condition is not yet settled if payoutDenominator(conditionId) is still 0.

Redemption and withdrawal support

Server wallet partner flows now include direct endpoints for payout settlement and treasury movement: The SDKs provide helper methods for server wallet claim (redeem), withdrawal, and withdrawal-address allowlist management. See the SDK getting-started pages for details.

EOA (Web3 partners)

Omit createServerWallet or set it to false. The partner proves wallet ownership using x-account, x-signing-message, and x-signature on POST /profiles/partner-accounts. The end user keeps their private key in their own wallet and signs each order (EIP-712) themselves — Limitless never holds their key. Scopes: trading and account_creation are sufficient for EOA partner flows. You do not need delegated_signing unless you also use server wallet sub-accounts.

End-to-end flow

  1. Register the user’s wallet (once per address)POST /profiles/partner-accounts with EOA headers. The response returns profileId and the wallet account. If a profile already exists for that address, the API returns 409 Conflict — your app should reuse the stored profileId instead of re-registering.
  2. Persist the mapping in your backend — save at least walletAddress → profileId (and your own user id if you have one). You are not storing a Limitless “session object”; you are storing your app’s record so you know which profileId to pass on orders. See What to persist below.
  3. User signs each order — build the order per EIP-712 signing and have the user sign in the browser (e.g. wagmi/viem/ethers). maker and signer must be the user’s EOA address.
  4. Submit the order from your backend (HMAC)POST /orders with HMAC auth, onBehalfOf set to the user’s profileId, and ownerId set to that same profileId when you send a signed order body. The order’s maker / signer must match the sub-account wallet. (If you use delegated signing with an unsigned order, the server sets ownerId for you — that path is for server-wallet sub-accounts, not pure EOA signing.)

Common EOA auth error

If POST /orders returns Signer does not match authenticated profile account, check all three fields point to the same user account:
  • ownerId = user’s profileId
  • onBehalfOf = same user’s profileId
  • order.maker and order.signer = that user’s wallet address
Using the partner profile ID in ownerId while signing with a user wallet causes this error.

Architecture (browser + backend)

Typical layout for a Next.js (or any SPA) app:
  • Browser: connect wallet (e.g. wagmi + RainbowKit); sign the ownership proof for step 1; sign EIP-712 orders for step 3. Never put partner HMAC secrets in client bundles.
  • Backend (Next.js Route Handlers, server actions, or a separate API): holds the scoped token tokenId / secret; signs every request to api.limitless.exchange with HMAC; forwards POST /orders after the client submits the signed order payload (or proxies market data as needed).
There is no official Next.js sample app in the public GitHub org today; use the TypeScript SDK on the server with the pattern above. Generic Node examples in Quickstart: Node.js illustrate HMAC and orders — swap in partner hmacCredentials and partnerAccounts.createAccount for EOA registration.

What to persist for EOA partners

You can recover partner-owned sub-account metadata with GET /profiles/partner-accounts?account=<wallet>, or list all child accounts with GET /profiles/partner-accounts. Treat walletAddress -> profileId persistence as recommended integration state for latency and auditability, but the API can recover the mapping when needed.
Wallet UX: Standard wallet connectors remember the user’s connection across visits, so users don’t necessarily “reconnect from scratch” every time — but each order still needs a signature unless you move to server wallet + delegated signing.

Delegated order types

Delegated orders support three execution strategies:

GTC (Good-Til-Cancelled)

Limit orders that rest on the orderbook at a specified price until they are filled or explicitly cancelled. Use price and size to specify the order.

FAK (Fill-And-Kill)

Limit orders that use price and size like GTC but only match immediately available liquidity. Any unmatched remainder is cancelled.

FOK (Fill-Or-Kill)

Market orders that execute immediately at the best available price or are cancelled entirely — no partial fills. Instead of price and size, FOK orders use makerAmount.

Reading sub-account data

Partners can read portfolio, order, and position data for their sub-accounts using the x-on-behalf-of header. This lets you show users their positions, trade history, and order status without requiring the sub-account to authenticate directly.

How it works

Add the x-on-behalf-of header with the sub-account’s profileId to any supported read endpoint. The response is exactly what the sub-account would see if they called the endpoint themselves.

Requirements

  1. Scope — your API token must include the delegated_signing scope.
  2. Ownership — the target profile must be a sub-account linked to your partner profile.
  3. Auth — use your existing HMAC flow (lmts-api-key, lmts-signature, lmts-timestamp). Nothing new.

Supported endpoints

More read endpoints will be enabled over time.

Without the header

If you omit x-on-behalf-of, these endpoints behave exactly as before — you read your own data. The header is purely additive.

Error responses

Error messages on 403 are intentionally generic — the API does not confirm or deny the existence of specific profile IDs.

HMAC authentication

All day-to-day programmatic API calls use HMAC-SHA256 request signing. See the Authentication page for the signing protocol, canonical message format, and code examples.

API endpoints

SDK support

All four official SDKs provide built-in support for the programmatic API:
Server-wallet redeem, withdraw, and withdrawal-address allowlist helpers are available in the TypeScript, Go, Python, and Rust SDKs.

TypeScript

Client with hmacCredentials, apiTokens, partnerAccounts, delegatedOrders, serverWallets

Python

Client with hmac_credentials, api_tokens, partner_accounts, delegated_orders, server_wallets

Go

Client with WithHMACCredentials, ApiTokens, PartnerAccounts, DelegatedOrders, ServerWallets

Rust

Client with HmacCredentials, api_tokens, partner_accounts, delegated_orders, server_wallets