CRISP partners

Accounts and identity

Headless provisioning without confusing app identity with custody.

Read Wallets and funds for custody, stable IDs and account-lifecycle boundaries. Your app owns login and user authorization.

Create the user's account

Before you start: configure the server client, authenticate your own user, and save their stable external ID and provisioning intent. Account access must be enabled for your integration. Example IDs and keys below are illustrative: use your own persisted values. HTTP tabs omit signing headers; see HTTP setup.

const result = await crisp.createAccount(
  {
    externalUserId: 'example:user-123',
    externalIdentity: { label: 'Username', value: '@example' },
  },
  'onboard-example-user-123',
);

POST /v1/accounts accepts:

FieldRules
externalUserIdRequired stable string, 1–200 letters/digits or ., _, :, @, -
referrerExternalUserIdOptional existing account registered under your organization; attribution commits atomically with account onboarding
emailOptional contact email; encrypted, not verified or login-enabled
externalWalletAddressOptional 20-byte EVM address; encrypted, unverified, not managed wallet or default withdrawal destination
externalIdentityOptional { label, value }; label starts with a letter, up to 64 letters/digits/spaces/underscores/hyphens; value up to 320 characters

No generic attributes, hosted return URLs, provider credentials or arbitrary metadata. externalIdentity is your operator-facing canonical display label, not wallet authority. Keep external IDs opaque and stable; display names can change.

Successful create returns 202 with data.crispAccountId, externalUserId, status, failureCode, createdAt and updatedAt. Persist the account mapping. Repeated provisioning upserts the same external ID, rather than making a second wallet. Display identity can be updated by provisioning again. Do not use this endpoint as a general profile/contact editor. Provisioning replay resolves the current account rather than freezing an obsolete asynchronous status.

For new referral integrations, supply the direct referrer here rather than running a separate attribution worker. If the referrer does not exist, CRISP returns 409 referrer_not_found and does not create the referred account/job. Onboard the referrer first and retry the same intent. Referrer wallet readiness is not required. Conflicting immutable edges, self-referrals and cycles fail without partial writes. Omitting this field retains the existing behavior.

Wait until ready

await crisp.waitForAccount(externalUserId) polls for you. Inspect result.data.status: ready, failed and revoked all stop the helper. A deadline stops waiting, not provisioning. For HTTP integrations, poll GET /v1/accounts/{externalUserId} with bounded backoff.

Account stateWhat your product does
provisioning / wallet_pendingWait and poll
polymarket_pendingWallet exists, venue setup is incomplete; wait
readyEnable eligible funding/trading capabilities
failedKeep trading unavailable; send safe failure/request IDs to CRISP
revokedDeny access to integration activity

Reads: GET /v1/accounts/{externalUserId}, /profile, /wallet. Encode path segments with encodeURIComponent. Profile can return profile_not_available when no contact/display/profile data exists; account provisioning can still be valid. Managed addresses only appear once created. Do not confuse an external contact wallet with the actual trading/deposit address.

GET /v1/accounts?limit=50&offset=0 lists the accounts registered under the organization identified by your API key; status optionally filters. General offset pagination allows limit 1–200. Do not expose this organization-wide endpoint directly to every end user.

Your backend must authorize every account path. A valid API key can access the accounts registered under your organization and therefore is more privileged than a single user's login.

Done when: account status is ready. Next, fund the account. Exact fields: createAccount and getAccount.

CRISP Partner Documentation