> ## 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.

# Accounts

> Upload a customer-linked bank or payment account and append immutable observations.

An Account is a stable identity supplied by your system. Each accepted request appends an immutable
AccountVersion. Use one Account for each distinct bank account, virtual account, blockchain wallet,
custodial wallet, or off-ramp wallet. Use the Karsa Customer `resourceId` in `customerId` when the
account belongs to an uploaded customer.

## Upload an account

```bash theme={null}
curl --request POST "$KARSA_API_URL/api/ingestion/accounts" \
  --header "Authorization: Bearer $KARSA_API_KEY" \
  --header "Idempotency-Key: account-example-001-observation-1" \
  --header "Content-Type: application/json" \
  --data '{
    "externalId": "account-example-001",
    "sourceExternalId": "provider-account-000123456789",
    "customerId": "customer_resource_example_01",
    "accountKind": "VIRTUAL_ACCOUNT",
    "accountType": "NAMED_VIRTUAL_ACCOUNT",
    "status": "ACTIVE",
    "openedAt": "2026-07-01T09:00:00Z",
    "accountDetails": {
      "displayName": "Primary USD collection account",
      "country": "US",
      "assets": ["USDC"],
      "paymentRails": ["ACH", "WIRE", "RTP", "SWIFT"],
      "bank": {
        "accountHolderName": "Example Manufacturing LLC",
        "accountClass": "BUSINESS",
        "recipientRelationship": "FIRST_PARTY",
        "beneficiaryIndustry": {
          "system": "NAICS",
          "code": "541511",
          "label": "Custom Computer Programming Services"
        },
        "institutionName": "Example Partner Bank",
        "institutionAddress": null,
        "beneficiaryAddress": null,
        "identifiers": [
          { "type": "ACCOUNT_NUMBER", "value": "000123456789", "paymentRail": "ACH" },
          { "type": "ROUTING_NUMBER", "value": "021000021", "paymentRail": "ACH" },
          { "type": "SWIFT_BIC", "value": "EXAMPLE0XXX", "paymentRail": "SWIFT" }
        ]
      },
      "wallet": null,
      "relatedAccounts": []
    },
    "customData": null,
    "effectiveAt": "2026-08-05T14:10:00Z",
    "changeReason": null,
    "documents": []
  }'
```

```json theme={null}
{
  "outcome": "CREATED",
  "resourceId": "account_resource_example_01",
  "versionId": "account_version_example_01",
  "currentVersionId": "account_version_example_01"
}
```

`customerId` is nullable because a source may report an account before its owner is known. Set it
only when the source has verified that the account belongs to that customer, using the Customer
`resourceId`; do not send the customer's source `externalId`. A transaction counterparty or
beneficiary association alone is not verified ownership.

`accountKind` is the provider-neutral category. `accountType`, identifier `type`, payment rails,
assets, networks, custody types, and relationship types remain source-defined strings so the
contract can preserve a provider's vocabulary without adopting that provider's schema.

On the first `POST`, omitting `accountKind` creates the account as `OTHER`. On a later `POST` for
the same source identity, omitting `accountKind` preserves the current kind; it does not silently
change a `VIRTUAL_ACCOUNT`, wallet, or bank account to `OTHER`.

Supply a stable `sourceExternalId` when the source will append another version or use `PUT` later.
An account with `sourceExternalId: null` is deliberately unbound: its first observation can be
stored, but no ingestion source can claim it, append another `POST` version, or update it with
`PUT`. Upload a new source-bound Account instead when continued source ownership is required.

Use `bank` for account-holder, institution, beneficiary-address, and routing identifiers. Common
identifier types include `ACCOUNT_NUMBER`, `ROUTING_NUMBER`, `IBAN`, `SWIFT_BIC`, `PIX_KEY`,
`CLABE`, `CVU`, `CBU`, `BANK_CODE`, and `BRANCH_CODE`. Use `wallet` for a blockchain network,
address or signature transaction hash, custody type, and account-abstraction flag. A virtual account
can contain `bank` details and relate to a separately uploaded settlement wallet through
`relatedAccounts`. An off-ramp wallet can relate to its destination bank account in the same way.

Use `bank.recipientRelationship` for the source's relationship classification, such as
`FIRST_PARTY`. Use `bank.beneficiaryIndustry` for a structured industry code and identify its
taxonomy in `system`. These are source facts; Karsa applies separately versioned policy when it
decides whether a relationship or industry combination is unusual.

Keep provider-only fields in `customData`. Never send private keys, seed phrases, signing secrets,
API credentials, or other authentication material in either `accountDetails` or `customData`.

## Update an account

Use the Karsa Account `resourceId` in the URL. Omitted mutable fields carry forward from the current
snapshot; explicit `null` clears a nullable field. `accountKind` and `accountType` are stable. If
either changes, upload a new Account instead.

```bash theme={null}
curl --request PUT "$KARSA_API_URL/api/ingestion/accounts/account_resource_example_01" \
  --header "Authorization: Bearer $KARSA_API_KEY" \
  --header "Idempotency-Key: account-example-001-observation-2" \
  --header "Content-Type: application/json" \
  --data '{
    "status": "ACTIVE",
    "accountDetails": {
      "displayName": "Primary USD collection account",
      "country": "US",
      "assets": ["USDC"],
      "paymentRails": ["ACH", "WIRE", "RTP", "SWIFT"],
      "bank": {
        "accountHolderName": "Example Manufacturing LLC",
        "accountClass": "BUSINESS",
        "recipientRelationship": "FIRST_PARTY",
        "beneficiaryIndustry": {
          "system": "NAICS",
          "code": "541511",
          "label": "Custom Computer Programming Services"
        },
        "institutionName": "Example Partner Bank",
        "institutionAddress": null,
        "beneficiaryAddress": null,
        "identifiers": [
          { "type": "ACCOUNT_NUMBER", "value": "000123456789", "paymentRail": "ACH" },
          { "type": "ROUTING_NUMBER", "value": "021000021", "paymentRail": "ACH" }
        ]
      },
      "wallet": null,
      "relatedAccounts": []
    },
    "effectiveAt": "2026-08-06T14:10:00Z",
    "changeReason": "SOURCE_ACCOUNT_UPDATED"
  }'
```

Account identity and routing details belong in AccountVersion. A wallet balance is a time-varying
financial observation, not account identity; do not overwrite account details with balance
snapshots.

`documents` contains immutable Document `versionId` values with their role on this account
observation. Omit no contract fields: send `null` or `[]` where the API schema allows it.


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