Object
type is individual or business. name is an individual’s first, middle, and last names joined by spaces, or a business’s legal name (the companyLegalName you send on create or update). A business customer has no person-name fields; its response returns companyLegalName and the company facts you sent, such as legalEntityType, registrationCountry, and incorporationAddress.
PII fields you send on create or update (birthDate, residentialAddress, ipAddress, identifyingInformation, and a business’s businessTaxId) are write-only. OMS accepts them but never returns them. A business response reports hasBusinessTaxId instead.
A single-customer GET /customers/{customerId} response also carries a totalBalance summary: totalUsd is fiatUsd + cryptoUsd to two decimals, covering fiat wallets and custodial crypto wallets. fiatUsd can be negative after an ACH clawback, so render the sign as received. Non-custodial wallets are not yet valued, so a customer holding one reads an undercount. totalBalance.updatedAt is when the custodial wallet provider last updated the crypto balances; it is omitted when the provider reports no timestamp, for example when the customer holds no custodial crypto wallet. The whole field is omitted when the rollup cannot be read, so treat an absent field as unknown rather than zero. The list, create, and update endpoints do not carry it.
List a customer’s wallets with GET /wallets?customerId={customerId}. See Wallets for the wallet resource.
Statuses
status tracks where the customer is in onboarding. Filter GET /customers by the same values.
Create request
POST /customers requires type. An individual requires firstName and lastName; a business requires companyLegalName and email and does not accept person-name fields. Other fields are optional in the schema, but your project’s verification policy decides what a create must carry (see below).
Whether a customer is verified, and whether OMS relies on your own verification or verifies the customer itself, is configured per project, separately for individuals (KYC) and businesses (KYB). It is not a per-request choice.
Required fields when your project requires KYC
On a project that requires KYC for individuals and provisions custodial wallets, an individual create must include all of the following:
Addresses in New York (
NY), Texas (TX), and Vermont (VT) are not supported on these projects. See Supported jurisdictions.
Create responses
Creation usually returns201 with the customer. When creation outlasts the request, OMS returns 202 with the ID the customer will have and a Retry-After header:
404 until creation finishes, and onboarding continues asynchronously after that. Repeat the same request with the same Idempotency-Key to follow it: the repeat returns 202 while creation is still running and 201 with the customer once it is done.
Validation errors
An invalid field returns400 with error code 2001 (invalid argument). The cause field names the specific field and reason; read it before you retry. Fields the schema does not define are ignored without an error, so a misspelled field name is silently dropped rather than rejected. Every response carries a Request-Id header; include it when you contact support.
In sandbox, avoid the word “test” in customer names and email addresses. Fraud checks run on sandbox customers too, and these values can be flagged.
Updating a customer
PATCH /customers/{customerId} adds or changes fields. identifyingInformation entries are appended, and signedAgreement can only move from false to true. Changes to residentialAddress, lastName, identifyingInformation, or ipAddress trigger re-evaluation of the customer’s endorsements.
DELETE /customers/{customerId} is a soft delete: the customer moves to offboarded.
Endorsements
Endorsements track what a customer is cleared for. Each unlocks a set of operations and carries its own status, so you can see exactly where a customer stands.
OMS requests
cryptoCustody and usd (which includes basic) for every new customer.
Each endorsement in the response carries its type and a status from the same set as the customer status. Where relevant, it also carries a requirements object listing fields that are complete, pending, missing, or have issues, and, when rejected, a failure. An endorsement never reads further along than its customer, and an endorsement that was not requested is left out. An endorsement must be active before its capability unlocks: for example, a quote that moves funds through a custodial wallet returns 403 KYCRequired when the customer’s cryptoCustody endorsement is not active.
Business onboarding
A business customer is onboarded with the people behind the company: its beneficial owners, controllers, directors, signatories, and representatives. Business onboarding must be enabled for your project.- Beneficiaries:
POSTandGET /customers/{customerId}/beneficiaries, andGET,PUT, andDELETE /customers/{customerId}/beneficiaries/{beneficiaryId}. Each beneficiary requiresroles(beneficialOwner,controller,director,signatory, orrepresentative).birthDate,taxId, andidentificationNumberare write-only; reads reporthasBirthDate,hasTaxId, andhasIdentificationNumber. - Onboardings:
POSTandGET /customers/{customerId}/onboardings, andGET /customers/{customerId}/onboardings/{onboardingId}. The request names one to fivebeneficiaryIdsand apartnerAttestation(id,provider,attestedAt) recording the business verification you performed.
pending and ends active or rejected, with a failureCode of rejected or processingFailed when it does not succeed. The customer’s status follows it: pending while the onboarding runs and rejected if it is rejected.
Both POST requests accept an Idempotency-Key header, so you can retry them safely.
Beneficiaries are versioned. PUT takes the current version and a full input: non-sensitive fields you omit are cleared, while write-only identifiers you omit keep their values and an empty string clears them. DELETE takes the current version as a query parameter.
Key operations
GET /customers filters by status, email, externalId, createdAfter, and createdBefore, and pages with limit and cursor. A status-filtered page can hold fewer than limit rows while hasMore is still true, so keep paging until hasMore is false.
POST requests require an Idempotency-Key header. Use a stable key tied to your internal user ID so a retry after a network failure cannot create a second customer.Webhook events
OMS emitscustomer.created, customer.statusChanged, and customer.updated for every change to a customer. The payload is the full customer in the shape above, so your handler can act on data.status, data.endorsements, and data.hold or data.failure without a follow-up read. A new customer is first announced as pending, then moved by customer.statusChanged. See Customers in the webhook events catalog for when each event fires.
Related
- Customer onboarding guide: create a customer and handle KYC and endorsements step by step
- Wallets: provision wallets for a customer
- Compliance: how KYC, KYB, and screening work in OMS
- Supported jurisdictions: blocked countries and US state restrictions