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

# Management

> Create, search, update, and archive customer records

The `manage` sub-module handles customer CRUD operations, search, and wallet linking. All operations are scoped to the [instance](/protocol/infrastructure/instances) bound to your API key.

## Create a customer

Customers can be created with or without a wallet address. When no wallet is provided, the system generates a `referenceKey` that you can use to link a wallet later.

```typescript theme={null}
// With wallet
const customer = await trusset.customers.manage.create({
  walletAddress: '0x1234...abcd',
  name: 'Acme Capital GmbH',
  country: 'DE',
  investorType: 'PROFESSIONAL',
  externalId: 'your-crm-id-4821',
  metadata: { department: 'treasury' },
})

// Without wallet - gets a referenceKey
const pending = await trusset.customers.manage.create({
  name: 'Pending Investor AG',
  country: 'AT',
  externalId: 'crm-9920',
})
// pending.referenceKey -> "ref_a1b2c3d4..."

// Company customer with linked individuals
const company = await trusset.customers.manage.create({
  name: 'Acme Capital GmbH',
  customerType: 'COMPANY',
  companyUrl: 'acme.example.com',   // normalized to https://
})
await trusset.customers.manage.create({
  name: 'Jane Doe',
  companyId: company.id,            // link individual to the company
})
```

If the wallet address is already registered on-chain in the IdentityRegistry, the customer status is automatically set to `verified`.

<Expandable title="CreateCustomerInput fields">
  <ParamField body="walletAddress" type="string">
    Ethereum address. Validated client-side before sending.
  </ParamField>

  <ParamField body="name" type="string">
    Display name for the customer. Required for company customers.
  </ParamField>

  <ParamField body="country" type="string">
    ISO 3166-1 alpha-2 or alpha-3 country code. Stored uppercase.
  </ParamField>

  <ParamField body="investorType" type="string">
    `RETAIL`, `PROFESSIONAL`, `ELIGIBLE_COUNTERPARTY`, or a custom [verification profile](/sdk/customers/verification-profiles) key.
  </ParamField>

  <ParamField body="customerType" type="string" default="INDIVIDUAL">
    `INDIVIDUAL` or `COMPANY`. Immutable after creation.
  </ParamField>

  <ParamField body="companyUrl" type="string">
    Company customers only. Normalized to an absolute https URL.
  </ParamField>

  <ParamField body="companyId" type="string">
    Individual customers only: id of a `COMPANY` customer in the same instance to link to.
  </ParamField>

  <ParamField body="contactChannels" type="string[]">
    Up to 20 contact strings (emails, phone numbers), 200 characters each.
  </ParamField>

  <ParamField body="externalId" type="string">
    Your system's unique identifier. Used for deduplication and as a lookup key.
  </ParamField>

  <ParamField body="metadata" type="object">
    Arbitrary JSON. Not indexed, but stored and returned with the customer record.
  </ParamField>
</Expandable>

## Search

The SDK provides typed search methods that map to different lookup strategies. Each returns a single `Customer` object or throws a `TrussetError` with code `NOT_FOUND`.

```typescript theme={null}
// By wallet address
const c1 = await trusset.customers.manage.searchByWallet('0x1234...abcd')

// By your internal ID (resolves reliably regardless of ID format or length)
const c2 = await trusset.customers.manage.searchByExternalId('crm-4821')

// By reference key (for pre-wallet customers)
const c3 = await trusset.customers.manage.searchByReference('ref_a1b2c3d4...')

// By name (substring match, returns paginated list)
const results = await trusset.customers.manage.searchByName('Acme', {
  limit: 20,
  offset: 0,
})
// results.customers, results.total
```

## List customers

```typescript theme={null}
const page = await trusset.customers.manage.list({
  limit: 100,               // 1-200, default 100
  offset: 0,
  search: 'bank',           // Searches name, wallet, externalId, referenceKey, companyUrl
  customerType: 'COMPANY',  // Optional: INDIVIDUAL or COMPANY
  includeArchived: false,
})
// page.customers: Customer[]
// page.total: number
```

## Update

```typescript theme={null}
await trusset.customers.manage.update('customer-id', {
  country: 'CH',
  investorType: 'ELIGIBLE_COUNTERPARTY',
  metadata: { migrated: true },
})
```

Only provided fields are updated. Omitted fields remain unchanged.

## Link a wallet

For customers created without a wallet address, link one using the `referenceKey`:

```typescript theme={null}
await trusset.customers.manage.linkWallet({
  referenceKey: 'ref_a1b2c3d4...',
  walletAddress: '0x5678...efgh',
})
```

The wallet address must not already be assigned to another customer in the same instance. If the address is already verified on-chain, the customer status updates to `verified` automatically.

## Archive

Archiving soft-deletes a customer. Archived customers are excluded from list queries by default.

```typescript theme={null}
await trusset.customers.manage.archive('customer-id')
```

## Linked wallets

A customer has one primary wallet and any number of linked wallets. Linked wallets resolve to the same customer in lookups and country checks. A wallet can only belong to one customer per instance.

```typescript theme={null}
// List all wallets (primary + linked)
const wallets = await trusset.customers.manage.listWallets('customer-id')
// wallets.primary, wallets.total, wallets.wallets: [{ address, label, isPrimary, addedAt }]

// Link an additional wallet
await trusset.customers.manage.addWallet('customer-id', '0x9999...aaaa', 'Trading desk')

// Make a linked wallet the primary. The previous primary stays linked,
// labeled "Previously primary".
await trusset.customers.manage.promoteWallet('customer-id', '0x9999...aaaa')

// Remove a linked (non-primary) wallet
await trusset.customers.manage.removeWallet('customer-id', '0x9999...aaaa')
```

Conflicts return `409` with a specific code: `ALREADY_PRIMARY`, `WALLET_ALREADY_LINKED` (same customer), or `WALLET_IN_USE` (another customer).

## Batch country lookup

Retrieve country codes for a list of wallet addresses in a single call. Useful for compliance checks across large holder sets.

```typescript theme={null}
const countries = await trusset.customers.manage.batchGetCountries([
  '0xaaa...', '0xbbb...', '0xccc...',
])
// { "0xaaa...": "DE", "0xbbb...": "FR" }
```

Addresses without a matching customer record are omitted from the result.
