> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useasterisk.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Document only operations in the linked OpenAPI contract: the source-data ingestion operations and the source-scoped outbound webhook management operations.
> Treat the generated OpenAPI document as authoritative for request fields. Never invent compatibility fields, alternate endpoints, or additional source models.
> Preserve explicit nulls, decimal strings, timestamps, source identifiers, immutable version identifiers, and document-version links exactly as defined.

# Customers

> Create complete individual or business Customer records.

A Customer is an individual or business known by your system. The stable Customer keeps the same
identity across uploads. Each accepted change appends an immutable CustomerVersion containing the
complete source snapshot at that time.

`POST /api/ingestion/customers` is the canonical Customer endpoint. It creates exactly one Customer,
and `type` determines whether that Customer is an `INDIVIDUAL` or a `BUSINESS`. A business is not a
separate resource outside Customers.

## One typed shape

Set `type` to `BUSINESS` and provide `business`, or set it to `INDIVIDUAL` and provide `individual`.
The two shapes cannot be mixed. Every core canonical field is required in the nested JSON object.
Send the value when your source has it and `null` when it explicitly does not. Optional first-class
extensions cover provider-neutral onboarding, verification tier, declared use, source of wealth,
public listing, occupation, terms acceptance, and additional information. `customData` remains an
optional source-owned JSON object for source fields that do not yet have a canonical equivalent.

The exact nested fields and limits are in the generated API Reference. The stable outer fields are:

| Field | Meaning |
| - | - |
| `externalId` | Stable customer identifier in your system |
| `effectiveAt` | When this complete snapshot became true in your system |
| `lifecycleStatus` | `PENDING`, `ACTIVE`, `SUSPENDED`, or `CLOSED` |
| `onboardedAt` | Optional timestamp when the customer completed source onboarding |
| `type` | `BUSINESS` or `INDIVIDUAL` |
| `business` | Required only when `type` is `BUSINESS` |
| `individual` | Required only when `type` is `INDIVIDUAL` |
| `customData` | Optional source-owned extension object |
| `documents` | Optional links to already uploaded immutable document versions |

## Create one business Customer

```bash theme={null}
curl --request POST \
  --url https://api.sandbox.useasterisk.com/api/ingestion/customers \
  --header "Authorization: Bearer $KARSA_API_TOKEN" \
  --header "Idempotency-Key: customer-example-001-create" \
  --header "Content-Type: application/json" \
  --data '{
    "externalId": "customer-example-001",
    "effectiveAt": "2026-08-05T14:00:00Z",
    "lifecycleStatus": "ACTIVE",
    "onboardedAt": "2026-08-05T13:45:00Z",
    "type": "BUSINESS",
    "business": {
      "verificationTier": { "sourceText": "standard", "category": "STANDARD" },
      "onboardingContext": {
        "ipAddress": "203.0.113.10",
        "latitude": 39.1582,
        "longitude": -75.5244
      },
      "legalName": "Example Manufacturing LLC",
      "tradeNames": null,
      "legalForm": null,
      "formationJurisdiction": null,
      "formationDate": null,
      "registrationNumber": null,
      "taxIdentifiers": null,
      "registeredAddress": null,
      "email": "compliance@example.invalid",
      "website": null,
      "operatingAddress": null,
      "businessDescription": null,
      "industry": null,
      "accountPurpose": null,
      "transactionPurpose": "Pay suppliers and receive customer payments",
      "sourceOfFunds": null,
      "sourceOfWealth": "Operating revenue and retained earnings",
      "annualRevenue": null,
      "expectedMonthlyAmount": null,
      "expectedMonthlyTransactionCount": null,
      "operatingCountries": null,
      "handlesThirdPartyFunds": null,
      "publiclyTraded": false,
      "regulatedActivities": null
    },
    "documents": []
  }'
```

```json theme={null}
{
  "outcome": "CREATED",
  "resourceId": "customer_resource_example_01",
  "versionId": "customer_version_example_01",
  "currentVersionId": "customer_version_example_01"
}
```

Save both identifiers. Other records use the stable `resourceId`; a KYB dossier pins the exact
immutable `versionId` it evaluates.

## Create a business and its UBO Customers atomically

Use `POST /api/ingestion/business-onboardings` when your integration must guarantee that the
business, all of its beneficial owners, their relationships, and the KYB submission are accepted
together. This is a convenience operation over the Customer model, not a second kind of business
resource.

For every item in `beneficialOwners`, Karsa validates a complete `INDIVIDUAL` Customer payload and
creates or versions that individual Customer before recording the ownership and role relationships.
If any Customer, relationship, or dossier write fails, none of the onboarding is committed.

The response returns the business Customer identifiers and, for every beneficial owner, that
individual Customer's `resourceId`, `versionId`, and relationship identifiers. Retain those Customer
IDs exactly as you would for an individual created directly through
`POST /api/ingestion/customers`.

## Update a customer

Use `PUT /api/ingestion/customers/{customerId}` with Karsa's stable `resourceId`. Supply only the
mutable fields that changed. Omitted fields carry forward into the new complete version; an explicit
`null` clears a nullable field; a supplied `documents` array replaces that version's document links.
`externalId` and `type` are immutable and are rejected in the update body.

```bash theme={null}
curl --request PUT \
  --url https://api.sandbox.useasterisk.com/api/ingestion/customers/customer_resource_example_01 \
  --header "Authorization: Bearer $KARSA_API_TOKEN" \
  --header "Idempotency-Key: customer-example-001-update-002" \
  --header "Content-Type: application/json" \
  --data '{
    "business": {
      "phone": "+12025550124",
      "transactionPurpose": "Pay suppliers, payroll, and operating expenses"
    },
    "effectiveAt": "2026-08-06T14:00:00Z",
    "changeReason": "SOURCE_PROFILE_UPDATED"
  }'
```

The response returns the appended `versionId` and the `currentVersionId`. A backdated observation is
recorded in history without replacing a later effective current version.

## Complete snapshots

Every CustomerVersion represents the complete customer state reported by your system at
`effectiveAt`. A later upload with the same `externalId` and changed values creates another version.
Retry an identical logical write with the original idempotency key.

Upload files separately and link their immutable versions through `documents`. Owners and control
persons are separate Customers connected by relationships. Provider decisions, warnings, and
provider evidence belong in a [KYB dossier](/guides/kyb-dossiers) or Outcome rather than the
customer profile.

## Related

* [Business onboarding guide](/guides/business-onboarding): create a business and its UBO Customers atomically
* [KYB dossiers](/guides/kyb-dossiers): bind documents and related Customers to an exact business version
* [Transactions](/concepts/transactions): reference known customer parties
* [Outcomes](/concepts/outcomes): attach one source result to this customer


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.