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

> ## Agent Instructions
> If you are an AI assistant operating Infinite for a user, read the skill first: https://docs.infinite.dev/agent-skill.md (setup per host, tool reference, rules for moving money, journeys).
> When operating Infinite for a user, use the MCP server. Sign in at https://bot.api.infinite.dev/mcp (production, acts as the user) or send `Authorization: Bearer <key>` to https://bot.api.infinite.dev/mcp/sse. Prefer its tools over raw HTTP; use REST only for steps no tool covers, and check `get_endpoint_schema` before guessing a request shape.
> Net-new Infinite Connect (org_connect) is operator-assisted: do not grant end users shared org_connect Auth Kit membership or the shared platform org API key — those credentials are org-wide on /v1. BYO org keys onboard under that customer's org id. Operator sessions should show org_connect in get_organization_info.
> The key decides the tools. Every organization key (`sk_sandbox_…` / `sk_live_…`) gets docs, onboarding, `get_account_balance`, and request logs for your own organization. BYO organizations add payees an agent will pay with `create_payee` (payable once ACTIVE). Platform Connect sessions instead get bound-customer payment lookups (`get_quote`, `get_transfer`, `list_transfers`, `list_account_balances`), payee drafts (`create_payee_draft` / `get_payee_draft`; screening only, never payable), and transfer drafts that wait for Infinite approval (`create_transfer_draft` / `get_transfer_draft`; never POST /v1/transfers). Where offered, platform `create_transfer` files a real transfer that Infinite holds in review before funding; it cannot be submitted from DRAFT.
> An agent key (`sk_sandbox_agent_…` / `sk_live_agent_…`) moves money within that agent's limits: `create_transfer` → `submit_transfer` → `wait_for_transfer`.
> On sandbox organization-key sessions, `sandbox_approve_customer` (makes the capabilities you pass READY, and related ones may turn READY too; `request_capabilities` is not needed), `sandbox_fund_account`, and `sandbox_complete_transfer` stand in for verification, funding, and settlement, so a whole flow runs from MCP. BYO keys can pass `customerId` on each call without binding; platform sessions must bind a customer first (`create_business_customer` auto-binds, or send `X-Infinite-On-Behalf-Of`).
> When searching documentation without a key, use the docs MCP at https://docs.infinite.dev/mcp.
> Start in sandbox (https://sandbox.api.infinite.dev). Do not use production unless the user explicitly asks.
> Confirm amount, currency, and payee with the user before any payment is submitted. Pass the invoice number as `reference` on `create_transfer`; the summary says what the payee will see.
> REST amounts are integer minor units (`"4000"` = 40.00 USD). MCP payment tools take exact decimal strings (`"40.00"`). Never mix them.
> Agent denials return `403 { denial: { code, message, window, limit, used, remaining, attemptedAmount, currency }, hint }` with decimal amounts; per-transfer denials omit `used` and `remaining`. Report them to the user; do not work around them.

# Customers

Customers are the foundation of the Infinite platform. They represent individuals or businesses that will be onboarded for verification and payment processing.

## Restricted Countries

Infinite cannot onboard customers from certain countries due to regulatory restrictions. These include OFAC-sanctioned countries and other jurisdictions with compliance limitations.

**OFAC Sanctioned Countries:**

* Cuba (CU)
* Iran (IR)
* North Korea (KP)
* Russia (RU)
* Syria (SY)

**Additional Restricted Countries:**

* Ukraine (UA)

<Warning>
  Attempting to create or update a customer with a country code from a restricted country will result in a `400 Bad Request` error. The country selection will be automatically filtered in the verification UI.
</Warning>

## Customer Types

Infinite supports two primary customer types:

### Individual Customers

Individual customers represent natural persons who need to complete personal KYC verification.

```json theme={null}
{
  "id": "cus_individual_123",
  "customerName": "John Doe",
  "email": "john@example.com",
  "type": "INDIVIDUAL",
  "countryCode": "US",
  "status": "DRAFT"
}
```

### Business Customers

Business customers represent companies or organizations that require business verification and beneficial ownership disclosure.

```json theme={null}
{
  "id": "cus_business_456",
  "customerName": "Acme Corp",
  "email": "compliance@acme.com",
  "type": "BUSINESS",
  "countryCode": "US",
  "status": "IN_REVIEW"
}
```

## Intent-Based State Machine

Customer creation follows an **intent-based state machine** pattern. This means you create a customer as an "intent" in DRAFT status, progressively add data, and explicitly submit when ready for verification.

<Frame>
  ```mermaid theme={null}
  stateDiagram-v2
      [*] --> DRAFT: Create customer
      DRAFT --> IN_REVIEW: Submit for verification
      IN_REVIEW --> NEED_ACTIONS: Missing information
      IN_REVIEW --> ACTIVE: Verification passed
      IN_REVIEW --> REJECTED: Verification failed
      NEED_ACTIONS --> IN_REVIEW: Re-submit with updates
      ACTIVE --> SUSPENDED: Compliance issue
      SUSPENDED --> ACTIVE: Issue resolved
      ACTIVE --> INACTIVE: Offboarded
      SUSPENDED --> INACTIVE: Offboarded
      REJECTED --> IN_REVIEW: Reopened for review
      REJECTED --> INACTIVE: Offboarded
      INACTIVE --> IN_REVIEW: Reopened for review
      INACTIVE --> ACTIVE: Reactivated
      INACTIVE --> SUSPENDED: Compliance issue
  ```
</Frame>

<Note>
  Compliance can also move a customer to `INACTIVE` or `SUSPENDED` from any non-terminal status, and reopen a `REJECTED` or `INACTIVE` customer for re-review.
</Note>

### Why Intent-Based?

1. **Progressive data collection**: Build up customer data over multiple API calls without triggering validation until you're ready
2. **Flexible workflows**: Collect information in any order, from any source
3. **Clear submission point**: Explicitly control when verification begins
4. **RFI handling**: Easy loop for handling requests for additional information

## Customer Status

| Status | Description | Capabilities |
| - | - | - |
| `DRAFT` | Customer intent created, data collection in progress | `IN_REVIEW` at best |
| `IN_REVIEW` | Submitted for verification, under compliance review | `IN_REVIEW` at best |
| `NEED_ACTIONS` | Verification requires additional information (RFI) | `IN_REVIEW` at best |
| `ACTIVE` | KYC/KYB verification passed, compliance approved | `READY` as each capability's onboarding completes |
| `REJECTED` | Verification failed or compliance issues | `UNAVAILABLE` |
| `SUSPENDED` | Account temporarily suspended | `UNAVAILABLE` |
| `INACTIVE` | Customer offboarded or deactivated | `UNAVAILABLE` |

<Note>
  `ACTIVE` means the customer passed Infinite's compliance review — it is a prerequisite for transacting, not a guarantee that every capability is ready. Individual capabilities (e.g. balance accounts, specific payment rails) become `READY` as their underlying onboarding completes. Check the [customer capabilities endpoint](/api-reference/customers/get-customer-capabilities) or subscribe to `customer.capability.updated` webhooks.
</Note>

## Customer Creation Patterns

### Pattern 1: Intent-First (Recommended)

Create customer in DRAFT status, add data progressively, then submit.

<Steps>
  <Step title="Create Intent">
    Create customer with basic info. Customer starts in `DRAFT` status.
  </Step>

  <Step title="Add Data">
    Use `PATCH /customers/:id` to add verification data, documents, addresses as you collect them.
  </Step>

  <Step title="Submit">
    Call `POST /customers/:id/submit` when ready. Customer transitions to `IN_REVIEW`.
  </Step>

  <Step title="Handle RFI (if needed)">
    If status becomes `NEED_ACTIONS`, add missing data via PATCH and re-submit.
  </Step>
</Steps>

#### Step 1: Create Intent

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/customers/individuals',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      json={
          'customerName': 'Jane Smith',
          'countryCode': 'US',
          'email': 'jane@example.com',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/individuals',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer sk_live_...',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        customerName: 'Jane Smith',
        countryCode: 'US',
        email: 'jane@example.com',
      }),
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite api POST /v1/customers/individuals --body '{
    "customerName": "Jane Smith",
    "countryCode": "US",
    "email": "jane@example.com"
  }'
  ```

  ```text MCP theme={null}
  Create an individual customer Jane Smith (jane@example.com) in the US.

  # Infinite MCP is read-only today — run the CLI tab to execute.
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.infinite.dev/v1/customers/individuals" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "customerName": "Jane Smith",
      "countryCode": "US",
      "email": "jane@example.com"
    }'
  # Response: { "id": "cus_abc123", "status": "DRAFT", ... }
  ```
</CodeGroup>

#### Step 2: Add Data

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.patch(
      'https://api.infinite.dev/v1/customers/cus_abc123',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      json={
          'customerDetails': {
              'firstName': 'Jane',
              'lastName': 'Smith',
              'dateOfBirth': '1990-01-15',
              'phone': '+14155551234',
          },
          'addresses': [
              {
                  'addressLine1': '123 Main St',
                  'city': 'San Francisco',
                  'state': 'CA',
                  'postalCode': '94102',
                  'country': 'US',
              }
          ],
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/cus_abc123',
    {
      method: 'PATCH',
      headers: {
        Authorization: 'Bearer sk_live_...',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        customerDetails: {
          firstName: 'Jane',
          lastName: 'Smith',
          dateOfBirth: '1990-01-15',
          phone: '+14155551234',
        },
        addresses: [
          {
            addressLine1: '123 Main St',
            city: 'San Francisco',
            state: 'CA',
            postalCode: '94102',
            country: 'US',
          },
        ],
      }),
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite customers update cus_abc123 --body '{
    "customerDetails": {
      "firstName": "Jane",
      "lastName": "Smith",
      "dateOfBirth": "1990-01-15",
      "phone": "+14155551234"
    },
    "addresses": [{
      "addressLine1": "123 Main St",
      "city": "San Francisco",
      "state": "CA",
      "postalCode": "94102",
      "country": "US"
    }]
  }'
  ```

  ```text MCP theme={null}
  Update cus_abc123: first name Jane, last name Smith, born 1990-01-15, phone +14155551234, address 123 Main St, San Francisco, CA 94102, US.

  # Infinite MCP is read-only today — run the CLI tab to execute.
  ```

  ```bash cURL theme={null}
  curl -X PATCH "https://api.infinite.dev/v1/customers/cus_abc123" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "customerDetails": {
        "firstName": "Jane",
        "lastName": "Smith",
        "dateOfBirth": "1990-01-15",
        "phone": "+14155551234"
      },
      "addresses": [{
        "addressLine1": "123 Main St",
        "city": "San Francisco",
        "state": "CA",
        "postalCode": "94102",
        "country": "US"
      }]
    }'
  ```
</CodeGroup>

#### Step 3: Submit

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/customers/cus_abc123/submit',
      headers={
          'Authorization': 'Bearer sk_live_...',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/cus_abc123/submit',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer sk_live_...',
      },
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite api POST /v1/customers/cus_abc123/submit
  ```

  ```text MCP theme={null}
  Submit customer cus_abc123 for verification.

  # Infinite MCP is read-only today — run the CLI tab to execute.
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.infinite.dev/v1/customers/cus_abc123/submit" \
    -H "Authorization: Bearer sk_live_..."
  # Response: { "id": "cus_abc123", "status": "IN_REVIEW", ... }
  ```
</CodeGroup>

### Pattern 2: Immediate Submission

If you have all data upfront, create the customer first, then save verification
and request review in the same call using `?submit=true`.

#### Step 1: Create Customer

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/customers/individuals',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      json={
          'customerName': 'Jane Smith',
          'countryCode': 'US',
          'email': 'jane@example.com',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/individuals',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer sk_live_...',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        customerName: 'Jane Smith',
        countryCode: 'US',
        email: 'jane@example.com',
      }),
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite api POST /v1/customers/individuals --body '{
    "customerName": "Jane Smith",
    "countryCode": "US",
    "email": "jane@example.com"
  }'
  ```

  ```text MCP theme={null}
  Create an individual customer Jane Smith (jane@example.com) in the US.

  # Infinite MCP is read-only today — run the CLI tab to execute.
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.infinite.dev/v1/customers/individuals" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "customerName": "Jane Smith",
      "countryCode": "US",
      "email": "jane@example.com"
    }'
  # Response: { "id": "cus_abc123", "status": "DRAFT", ... }
  ```
</CodeGroup>

#### Step 2: Save and Submit

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/customers/cus_abc123/verification/individual',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      params={'submit': 'true'},
      json={
          'firstName': 'Jane',
          'lastName': 'Smith',
          'email': 'jane@example.com',
          'dateOfBirth': '1990-01-15',
          'phone': '+14155551234',
          'address': {
              'addressLine1': '123 Main St',
              'city': 'San Francisco',
              'state': 'CA',
              'postalCode': '94102',
              'country': 'US',
          },
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/cus_abc123/verification/individual?submit=true',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer sk_live_...',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        firstName: 'Jane',
        lastName: 'Smith',
        email: 'jane@example.com',
        dateOfBirth: '1990-01-15',
        phone: '+14155551234',
        address: {
          addressLine1: '123 Main St',
          city: 'San Francisco',
          state: 'CA',
          postalCode: '94102',
          country: 'US',
        },
      }),
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite api POST '/v1/customers/cus_abc123/verification/individual?submit=true' --body '{
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "dateOfBirth": "1990-01-15",
    "phone": "+14155551234",
    "address": {
      "addressLine1": "123 Main St",
      "city": "San Francisco",
      "state": "CA",
      "postalCode": "94102",
      "country": "US"
    }
  }'
  ```

  ```text MCP theme={null}
  Save and submit verification for cus_abc123: Jane Smith, jane@example.com, born 1990-01-15, phone +14155551234, address 123 Main St, San Francisco, CA 94102, US.

  # Infinite MCP is read-only today — run the CLI tab to execute.
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.infinite.dev/v1/customers/cus_abc123/verification/individual?submit=true" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane@example.com",
      "dateOfBirth": "1990-01-15",
      "phone": "+14155551234",
      "address": {
        "addressLine1": "123 Main St",
        "city": "San Francisco",
        "state": "CA",
        "postalCode": "94102",
        "country": "US"
      }
    }'
  # Response: data is saved. Status stays DRAFT until every required
  # field and document is present, then becomes IN_REVIEW.
  # {
  #   "customerId": "cus_abc123",
  #   "status": "DRAFT",
  #   "missingRequirements": [
  #     { "requirementType": "FIELD", "key": "metadata.infiniteTosAcceptanceId", "displayName": "Infinite Terms of Service & Privacy Policy" },
  #     { "requirementType": "DOCUMENT", "key": "identity.government_id_front", "displayName": "Government ID" }
  #   ]
  # }
  ```
</CodeGroup>

Business customers use `POST /customers/businesses` then
`POST /customers/:id/verification/business`.

<Note>
  `?submit=true` does not fail when data is incomplete. The payload is saved and
  the customer stays in `DRAFT` with `missingRequirements`. Status becomes
  `IN_REVIEW` only after every required field and document is present. Check
  [customer compliance requirements](/api-reference/customers/get-customer-compliance-requirements)
  or the [individual verification](/api-reference/customers/save-individual-customer-verification)
  payload for the full set.
</Note>

## Handling Request for Information (RFI)

When verification requires additional data, the customer status changes to `NEED_ACTIONS` and the response includes `missingFields` and/or `missingDocuments`.

```json theme={null}
{
  "id": "cus_abc123",
  "status": "NEED_ACTIONS",
  "missingFields": [
    { "fieldPath": "individualData.occupation", "displayName": "Occupation" },
    { "fieldPath": "individualData.sourceOfIncome", "displayName": "Source of Income" }
  ],
  "missingDocuments": [
    { "documentType": "government_id", "displayName": "Government ID" }
  ]
}
```

To resolve:

1. Add the missing data via `PATCH /customers/:id`
2. Upload any missing documents via `POST /documents`
3. Re-submit via `POST /customers/:id/submit`

## Customer Data

### Required Fields

* `customerName` - Full name (individual) or company name (business)

Customer type is chosen by the endpoint: `POST /customers/individuals` or
`POST /customers/businesses`. Do not send `type` on those requests.

### Recommended Fields

* `email` - Primary contact email address
* `countryCode` - ISO 3166-1 alpha-2 country code

### Core Profile Fields

Send profile fields at the top level of the create request — `POST /customers/individuals` for individuals and `POST /customers/businesses` for businesses.
Use `customerDetails` on `PATCH /customers/:id` when updating the saved customer profile.
Use `POST /customers/:id/verification/individual` or `POST /customers/:id/verification/business` for full verification payloads.

For **Individual** customers:

* `firstName`, `lastName`, `middleName`
* `dateOfBirth` (YYYY-MM-DD format)
* `phone` with country code
* `occupation`, `sourceOfIncome`
* Transliteration fields when names contain non-Latin characters

`occupation` should be provided as an occupation code, for example `151252`.
`sourceOfIncome` is an enum field and should use values like `SALARY`, `COMPANY_FUNDS`, `INVESTMENTS_LOANS`, `INHERITANCE`, `SAVINGS`, or `PENSION_RETIREMENT`.

For **Business** customers:

* `businessName`, `tradeName`
* `businessType` (LLC, Corp, etc.)
* `taxId`
* `yearEstablished`
* `website`, `industry`

## Working with Customers

### Retrieving Customers

#### Get All Customers

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.infinite.dev/v1/customers',
      headers={'Authorization': 'Bearer sk_live_...'},
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.infinite.dev/v1/customers', {
    headers: {
      Authorization: 'Bearer sk_live_...',
    },
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite customers list --limit 10
  ```

  ```text MCP theme={null}
  List all my customers.
  ```

  ```bash cURL theme={null}
  curl -X GET "https://api.infinite.dev/v1/customers" \
    -H "Authorization: Bearer sk_live_..."
  ```
</CodeGroup>

#### Get Specific Customer

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.infinite.dev/v1/customers/cus_abc123',
      headers={'Authorization': 'Bearer sk_live_...'},
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/cus_abc123',
    {
      headers: {
        Authorization: 'Bearer sk_live_...',
      },
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite customers get cus_abc123
  ```

  ```text MCP theme={null}
  Show me customer cus_abc123.
  ```

  ```bash cURL theme={null}
  curl -X GET "https://api.infinite.dev/v1/customers/cus_abc123" \
    -H "Authorization: Bearer sk_live_..."
  ```
</CodeGroup>

#### Filter by Status

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.infinite.dev/v1/customers',
      headers={'Authorization': 'Bearer sk_live_...'},
      params={'status': 'DRAFT'},
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers?status=DRAFT',
    {
      headers: {
        Authorization: 'Bearer sk_live_...',
      },
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite customers list --status DRAFT --limit 10
  ```

  ```text MCP theme={null}
  List customers still in DRAFT.
  ```

  ```bash cURL theme={null}
  curl -X GET "https://api.infinite.dev/v1/customers?status=DRAFT" \
    -H "Authorization: Bearer sk_live_..."
  ```
</CodeGroup>

### Updating Customers

Update customer data at any time while in `DRAFT` or `NEED_ACTIONS` status:

For individual customer profile updates, send `occupation` as an occupation code and `sourceOfIncome` as an enum value.

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.patch(
      'https://api.infinite.dev/v1/customers/cus_abc123',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      json={
          'customerDetails': {
              'occupation': '151252',
              'sourceOfIncome': 'SALARY',
          },
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.infinite.dev/v1/customers/cus_abc123',
    {
      method: 'PATCH',
      headers: {
        Authorization: 'Bearer sk_live_...',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        customerDetails: {
          occupation: '151252',
          sourceOfIncome: 'SALARY',
        },
      }),
    },
  );
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=sk_live_...
  infinite customers update cus_abc123 --body '{
    "customerDetails": {
      "occupation": "151252",
      "sourceOfIncome": "SALARY"
    }
  }'
  ```

  ```text MCP theme={null}
  Update cus_abc123's occupation to 151252 and source of income to SALARY.

  # Infinite MCP is read-only today — run the CLI tab to execute.
  ```

  ```bash cURL theme={null}
  curl -X PATCH "https://api.infinite.dev/v1/customers/cus_abc123" \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "customerDetails": {
        "occupation": "151252",
        "sourceOfIncome": "SALARY"
      }
    }'
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Use idempotency keys">
    Always include an `Idempotency-Key` header when creating customers to prevent duplicate records from retries.
  </Accordion>

  <Accordion title="Collect data progressively">
    Use the intent pattern to collect data across multiple sessions or sources without worrying about validation until submission.
  </Accordion>

  <Accordion title="Handle RFI proactively">
    Check `missingFields` and `missingDocuments` on customer responses to understand what's needed before submission.
  </Accordion>

  <Accordion title="Monitor status via webhooks">
    Subscribe to `customer.status_changed` webhooks to react to status changes, and `customer.capability.updated` to know when a capability becomes ready.
  </Accordion>
</AccordionGroup>

## Next Steps

Once you've created a customer, the next step is typically to initiate [verification](/concepts/verification) to comply with KYC/AML requirements.

<CardGroup cols={2}>
  <Card title="Verification" icon="shield-check" href="/concepts/verification">
    Learn how to verify customer identities for compliance
  </Card>

  <Card title="Create Customer API" icon="code" href="/api-reference/customers/create-a-new-individual-customer">
    Full API reference for customer creation
  </Card>
</CardGroup>


## Related topics

- [Welcome](/welcome.md)
- [Verification](/concepts/verification.md)
- [Agents](/concepts/agents.md)
- [Accounts](/concepts/accounts.md)
- [Fixed Routes](/concepts/fixed-routes.md)
