Customers

Create a customer

Creates a customer - the anchor resource that quotes, verifications, accounts, payout destinations, wallets, and transfers all reference. Supply type: individual with an individual block (including individual.tax_id) or type: business with a business block (including business.registration); the required identity is enforced server-side. The customer always starts status: pending and is verified separately (see POST /verifications). Accepts an optional Idempotency-Key (recommended). Returns the created Customer.

A customer already registered for your organization - through this API or through your onboarding link - is not created twice: the request returns 409 CUSTOMER_ALREADY_EXISTS (same tax identity) or CUSTOMER_EMAIL_ALREADY_EXISTS (same email), and error.details tells you which customer it is. When the existing customer was created through this API, details carries existing_source: api and existing_id - its ozav_cus_ id in the same environment as your key (use it with GET /customers/{customer_id}). details is omitted when that id cannot be resolved. When the existing customer came through your onboarding link, details carries existing_source: onboarding_link and existing_id (its customer id, or null while that registration is still under verification).

The record persists and reads back. Customer creation does not open a real wallet or bank account by itself. In sandbox, verification simulation can materialize simulated wallet and BRL/Pix account projections after approval; live provisioning requires enablement for your organization.

post/customers

Request

  • Base URL
    https://developers.ozav.io/v2
  • Auth
    • API key in header X-API-Key
    • or HTTP bearer

Headers

Idempotency-Keystring

Optional idempotency key (16-256 characters of [A-Za-z0-9_-]); same semantics as on money-moving operations.

Request body

type'individual' | 'business' required

Whether the customer is a natural person or a company:

  • individual - a person; supply the individual block (including individual.tax_id).
  • business - a company; supply the business block (including business.registration).
external_refstring

Your own identifier for this customer, echoed back on the resource. Optional; need not be unique.

emailstring email required

Contact email for the customer. Required. At most 254 characters.

phonestring

Contact phone number in E.164 form (e.g. +5511999998888). Optional. At most 20 digits.

verification_mode'full' | 'reliance'

The verification posture for this customer (see CustomerVerification.mode). Optional: omitted, the organization's posture applies - reliance when your organization holds the kyc_reliance product (the default for API integrators), otherwise full.

  • reliance - you verified the person and attest it; the end-customer does nothing. OZAV still screens against designated lists and assesses economic capacity, and approves automatically once the profile is complete, the partner document is received and screening is clear. OZAV terms (terms_session_id) are not required. Requires the kyc_reliance entitlement (403 ENTITLEMENT_REQUIRED otherwise).
  • full - OZAV verifies the end-customer: in a hosted session (POST /verifications: document, liveness, face match) or, where hosted capture is off, from the identity document and selfie you upload (pending_documents lists what is missing).
monitoringboolean

Recorded only: OZAV does not re-screen this customer on list updates nor send an event for it. Screen again with POST /screenings when you need a current result.

terms_session_idstring

The id (ts_…) of an accepted terms-of-service session. Not required for a reliance customer (the default posture for API integrators): the contract with the end-customer is yours. For full customers, mint it with POST /customers/terms-sessions, present terms_url to your end user, record the acceptance with POST /customers/terms-sessions/accept, then pass the same id here. Consumed at provisioning for personas that settle or hold funds: provisioning a settlement customer fails closed with 422 TERMS_ACCEPTANCE_REQUIRED when there is no accepted session, and the customer stays unprovisioned (status: pending). Not required for compliance-only (verification-only) personas, which are never provisioned at a settlement layer.

Sandbox: a test key never resolves this field - the attestation is simulated and any value (or none) is accepted. The gate is real only on live. Do not read a sandbox 201 as proof that your terms flow works.

custody_model'managed' | 'self_custody'

Which custody to provision for this customer, when your organization has both custody products enabled.

Omit it and the default applies: self_custody when you send self_custody.address or your organization has no managed custody, otherwise managed. With both products enabled and no address, the customer gets managed custody, with a deposit address and a custody balance an off-ramp can debit.

Asking for a model your organization has not contracted returns 403 ENTITLEMENT_REQUIRED naming the missing product - never a silent fallback to the other model. When it resolves to self_custody, self_custody.address is required.

metadataMetadata

Free-form string map (max 50 keys).

Example request

{
  "business": {
    "cnae_codes": [
      "6201-5/01"
    ]
  }
}

Response

Customer created.

idstring required

Opaque customer identifier, prefixed ozav_cus_.

object'customer' required

Resource type discriminator; always the literal customer.

type'individual' | 'business' required

Whether the customer is a natural person (individual) or a company (business).

status'pending' | 'in_review' | 'approved' | 'rejected' | 'suspended' required

Onboarding / KYC lifecycle state of a customer.

ValueMeaning
pendingCreated; verification has not completed. The customer cannot transact yet.
in_reviewChecks were submitted and are under (automated or manual) review.
approvedVerification passed. The customer may transact once OZAV has everything a payout will need; see the note below.
rejectedVerification failed; the customer cannot be onboarded.
suspendedA previously active customer has been blocked by a compliance or operational action.

approved is about the checks, not about being able to operate. OZAV activates a customer only when it also holds everything a payout will need: the holder's name, a valid tax document for the country declared on it, and an address. A Brazilian company with a valid CNPJ is exempt from the address, because the public registry supplies it.

A customer can therefore sit at approved and still be refused, with 422 on POST /accounts and on the money paths. The gap shows up there, before any funds are committed, and not at payout time.

The request body cannot resolve it. Send the missing field through the customer update path, or ask OZAV: the blocked queue names each customer and the exact field it is waiting on.

account_status'active' | 'pending'

Whether the account can operate - a different question from whether the verification passed, which is status. active means named accounts, cards and payouts are available. pending means they are not, and the calls that need them refuse with 422 ACCOUNT_NOT_ACTIVATED. An approved customer can sit at pending for two different reasons. When data is missing, requirements.due names it and requirements.owner reads integrator - send the field with PATCH /customers/{customer_id} and the account activates in the same response. When due is empty, the account is simply not provisioned yet and nothing is owed by you. Read this field instead of inferring operability from status: an approved customer is not necessarily one that can move money.

external_refstring

Your own identifier for this customer, as supplied at creation.

emailstring email

Contact email for the customer.

phonestring

Contact phone number (E.164).

created_atstring date-time

When the customer was created (RFC 3339 / ISO 8601, UTC).

updated_atstring date-time

When the customer was last modified (RFC 3339 / ISO 8601, UTC).

metadataMetadata

Free-form string map (max 50 keys).

still_requiredCustomerDocumentType[]

The documents this customer will need before an account can be opened for them, given their type and country of registration. Returned on POST /customers so you learn the list when the customer is created, not when the account is refused.

This is not requirements.documents_due, and the difference matters. documents_due is what OZAV has formally asked for, each item with a deadline and a reason; right after creation it is empty, because nothing has been asked yet. still_required is what the corridor will demand regardless - a Brazilian company needs seven documents (plus four per associated person, reported by GET /customers/{customer_id}/documents in still_required_by_person) whether or not anyone has asked.

Absent, never [], for a customer whose requirement set is not modelled: an empty list would assert "nothing is missing", and that promise is only safe to make for the shapes the gate actually models. The same field, computed the same way, is returned by GET /customers/{customer_id}/documents once documents start arriving.

Example response

{
  "business": {
    "cnae_codes": [
      "6201-5/01"
    ]
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.