CRISP partners

SDK quickstart

Run a safe offline example, then connect your backend and follow one account through its first trade.

Evaluating the product first? Start with CRISP for partners and launch planning.

This is the recommended Node.js path. You do not need to implement HMAC signing or execution-host selection yourself. Prefer another backend language? Use the HTTP API setup and the HTTP tabs in each task guide.

First: run the offline example

Use Node.js 24+. Download the official SDK package and runnable quickstart into an empty folder:

npm install ./crisp-trade-partner-sdk-0.13.0.tgz
node partner-quickstart.mjs

The default is an offline mock: onboarding, funding reads, order acceptance, operation status and portfolio. No network requests or funds are used. It does not simulate venue liquidity/settlement. The SDK is downloadable here, not yet published to the npm registry.

Expected output includes:

MOCK: no network or funds used.
Account ready; trading cash: 10.000000
Command state: succeeded (not a fill guarantee)
Portfolio read complete. Use trade-fills for confirmed trade history.

The downloaded script is runnable as-is. The snippets below explain how to put the same flow in your application: names such as intent, selectedMarket, selectedOutcome and renderConfirmedFills are your storage/UI integration points, not additional SDK APIs. Never copy mock identifiers into a live trade.

1. Obtain approved access

CRISP supplies your key ID (cpk_…) and one-time secret (cps_…) through a secure channel. The production origin is https://partner-api.crisp.trade; paths start with /v1. There is no hosted test environment. Use the offline mock to test your code without funds; live calls use production services and real funds.

Store credentials only on your backend. Example variable names below belong to your integration, not the CRISP dashboard:

CRISP_PARTNER_API_BASE_URL=https://partner-api.crisp.trade
CRISP_PARTNER_API_KEY=provided-securely
CRISP_PARTNER_API_SECRET=provided-securely

Tell CRISP which features your application needs: accounts, market data, trading, portfolio, funding, withdrawals, referral claims and realtime. CRISP configures access for your credentials; you do not need to select internal permission scopes. Withdrawals and settlement require explicit enablement.

2. Make a read-only request

Install the SDK above. Do not import the main client into a browser bundle.

import { CrispClient } from '@crisp-trade/partner-sdk';

const crisp = new CrispClient({
  origin: process.env.CRISP_PARTNER_API_BASE_URL,
  keyId: process.env.CRISP_PARTNER_API_KEY,
  secret: process.env.CRISP_PARTNER_API_SECRET,
});
const result = await crisp.getCapabilities();
console.log(result.data); // Do not log credentials or full user payloads.

Capabilities describe enabled services; individual requests still enforce access. Use GET /v1/trading-status to show service restrictions in your product.

3. Provision an account

Only run this after CRISP approves your test account. Authenticate your own user first. Persist the external ID and intent key before sending the request.

const externalUserId = 'example:user-123'; // Stable ID chosen by your backend.
const created = await crisp.createAccount(
  {
    externalUserId,
    externalIdentity: { label: 'Username', value: '@example' },
    // Optional: referrerExternalUserId: 'already-onboarded-referrer',
  },
  'provision-example-user-123',
);
const status = await crisp.waitForAccount(externalUserId, { timeoutMs: 60_000 });
if (status.data.status !== 'ready') throw new Error('Account setup did not succeed');

Account access must be enabled. Use bounded exponential backoff (for example 1, 2, 4, 8, then 15 seconds) while provisioning. Stop on terminal failure/revocation; do not fund or trade until status is ready.

The optional referrer must already have a managed trading account registered under your organization, though its wallet may still be provisioning. Account creation and attribution commit atomically. CRISP does not create unknown referrer users on your behalf.

Checkpoint: your backend has saved the mapping and the account is ready. An HTTP 202 alone is not this checkpoint.

4. Fund the account

const funding = await crisp.getFunding(externalUserId, { details: 'full' });

Render returned supported assets and network-specific instructions. Follow the funding guide for a user-approved source-wallet transfer and final delivery. Pending bridge deposits are not spendable cash. Use details: 'trading' for ticket buying power, summary for a balance-only display, and full only when deposit/withdrawal details are needed. See cash balance and buying power for the exact balance.formatted and availableToTrade.formatted fields and display examples.

Checkpoint: the user has approved and sent a deposit, and trading buying power reflects delivery. Neither this SDK read nor a deposit quote transfers funds.

5. Submit and follow one approved trade

Choose a real market/outcome using listMarkets and getMarket. Retain the returned identifiers; mock token IDs are not tradable. Refresh requirements in the background rather than requiring another quote round trip on each click.

// Persist intent.id and this exact input before the first request.
const result = await crisp.marketBuy(externalUserId, {
  marketId: selectedMarket.id,
  tokenId: selectedOutcome.tokenId,
  spendAmount: '2.00',
}, intent.id);
// Render result.data immediately; it may already contain the confirmed fill.
let state = result.data.command.state;
if (['queued', 'running', 'retryable'].includes(result.data.command.state)) {
  const outcome = await crisp.waitForOperation(externalUserId, result.data.command.id);
  state = outcome.data.operation.state;
}
// Branch on state in your UI: succeeded, failed or ambiguous.
// A timeout throws: preserve the same intent for recovery, never a new order.

succeeded means command execution succeeded, not that an entire order filled. ambiguous means outcome unknown: do not place a replacement. Polling timeouts stop waiting, not the trade. Read recovery before enabling the submit button. The high-level helpers use cached direct execution-cell routing, with bounded same-intent fallback; low-level call remains one HTTP attempt. Call prepareTrading(externalUserId, [tokenId]) in the background when the ticket opens, not as a prerequisite to submitting. See the SDK trading UX checklist.

Checkpoint: you know the command outcome. Show “filled” only when the returned fill or canonical fill history establishes it, not simply succeeded.

6. Display positions and confirmed fills

const positions = await crisp.listPositions(externalUserId);
for await (const page of crisp.tradeFills(externalUserId, {
  from: reportStart.toISOString(),
  to: reportEnd.toISOString(),
  limit: 50,
})) {
  renderConfirmedFills(page.data.fills);
}

For this journey request accounts read/write, wallet read, markets read, orders read/write, portfolio read and fees read (canonical fills). Start with bounded refreshes; add realtime, referrals and withdrawals when the core flow works. Webhooks, traffic analytics and execution-cell capabilities are optional.

Move the runnable example to approved live access

Put the variables from step 1 and CRISP_EXTERNAL_USER_ID in your local backend environment. Node.js does not automatically load .env for this script:

node --env-file=.env partner-quickstart.mjs --live

This creates/provisions an account, then reads it and its balance. It is not a read-only command, but it does not trade or transfer funds. Do not run it until CRISP approves the environment/account. Keep .env out of version control.

For an explicitly approved trade, first obtain current CRISP_MARKET_ID and CRISP_TOKEN_ID through market discovery, fund the account, and set CRISP_SPEND_AMOUNT to the approved cash budget:

node --env-file=.env partner-quickstart.mjs --live --confirm-order

The script persists its keys/input in a local intent file. Rerunning reuses that intent; it is not a shortcut for placing another trade. Do not delete/change an unresolved intent to bypass recovery. In your application, use durable per-action storage and authenticated handlers rather than this CLI's local file.

Complete the launch checklist before opening trading to users. For automatic account refresh, use createAccountSync with authenticated resource loaders; no custom socket or cursor handling is needed. For the next feature, choose realtime, referrals, or withdrawals.

CRISP Partner Documentation