Skip to main content
A customer is the top-level identity record in OMS. Every wallet belongs to a customer, and so does every transaction. No financial operation can happen without one.

Object

{
  "id": "cst_...",
  "object": "customer",
  "type": "individual",
  "firstName": "Jane",
  "lastName": "Smith",
  "email": "jane@example.com",
  "phone": "+12125551234",
  "nationality": "US",
  "externalId": "usr_12345",
  "status": "active",
  "signedAgreement": true,
  "signedAgreementAt": "2026-03-20T14:15:22Z",
  "wallets": [
    {
      "id": "wlt_...",
      "type": "custodial",
      "address": "0x7B3a...D9b1",
      "network": "polygon",
      "asset": "usdc",
      "balance": "1234.56",
      "estimatedValueUsd": "1234.56"
    }
  ],
  "endorsements": [
    { "name": "basic", "status": "ACTIVE" },
    { "name": "cryptoCustody", "status": "ACTIVE" },
    { "name": "usd", "status": "PENDING" }
  ],
  "createdAt": "2026-01-15T10:30:00Z",
  "updatedAt": "2026-01-15T10:30:00Z"
}
type is individual, the only type supported today. status is active or inactive; an inactive customer cannot create new transactions. There are no intermediate customer states: all compliance granularity lives in the endorsement statuses. PII fields you send on create or update (birthDate, residentialAddress, ipAddress, identifyingInformation) are write-only. OMS accepts them but never returns them. The wallets array is a simplified flat view, one entry per wallet-asset combination. Read the full wallet representation with GET /wallets/{id}/balance. See Wallets for the wallet resource.

Create a customer

POST /customers. The only required field is type; everything else is optional and can be added later with PATCH /customers/{customerId}.
{
  "type": "individual",
  "firstName": "Jane",
  "lastName": "Smith",
  "email": "jane@example.com",
  "phone": "+12125551234",
  "nationality": "US",
  "birthDate": "1990-05-15",
  "residentialAddress": {
    "line1": "123 Main St",
    "city": "New York",
    "state": "NY",
    "country": "US",
    "zipCode": "10001"
  },
  "identifyingInformation": [
    { "type": "ssn", "issuingCountry": "US", "number": "123456789" }
  ],
  "endorsements": ["cryptoCustody", "usd"]
}
Create the customer record first, then collect the identifying fields for your KYC flow and submit them on create or with a later update. OMS handles compliance screening; your application handles identity collection. In sandbox, endorsements are auto-approved.

Endorsements

Endorsements track KYC and compliance status. Each unlocks a set of operations, and each carries its own status so you can see exactly where a customer stands.
EndorsementUnlocks
basicBaseline identity checks. Auto-included whenever another endorsement is requested.
cryptoCustodyCustodial stablecoin wallets.
usdUSD fiat rails, including bank and cash payouts.
Request endorsements in the endorsements array on create or update. If you omit the array on create, OMS defaults to cryptoCustody and usd, which auto-includes basic. On update, listing endorsement names adds them and triggers re-evaluation; existing endorsements are never removed. Each endorsement in the response carries a status, and where relevant a requirements object (fields that are complete, pending, missing, or have issues) and rejectionReasons.
Endorsement statusMeaning
INACTIVENot yet requested or not started.
PENDINGUnder compliance review.
ISSUESRequires attention; see requirements.issues.
ACTIVEApproved and usable.
REJECTEDDenied; see rejectionReasons.
REVOKED_ISSUESPreviously active, now revoked pending resolution.
OFFBOARDEDTerminated.

Balance

GET /customers/{id}/balance returns the customer’s estimated total balance aggregated across all of their wallets and assets. Pass estimatedBalanceCurrencyCode to value the aggregate in a currency other than USD.
{
  "data": {
    "customerId": "cst_...",
    "estimatedBalanceValue": "1234.56",
    "estimatedBalanceCurrencyCode": "USD",
    "updatedAt": "2026-01-15T10:30:00Z"
  }
}

Key operations

OperationEndpoint
Create a customerPOST /customers
List customersGET /customers
Retrieve a customerGET /customers/{customerId}
Update a customerPATCH /customers/{customerId}
Delete a customerDELETE /customers/{customerId}
Get aggregated balanceGET /customers/{id}/balance
List walletsGET /customers/{id}/wallets
Create a walletPOST /customers/{id}/wallets
POST, PATCH, and DELETE requests accept an Idempotency-Key header. Use a stable key tied to your internal user ID to safely retry on network failure.