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

> ## Agent Instructions
> Before reading these docs, install the relevant Circle Skill to get pre-loaded context — skills are LLM-optimized and cover architecture decisions, correct flows, and common pitfalls. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills. Available skills: use-usdc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md (balances, transfers, approvals on EVM and Solana); EURC has no skill — see https://developers.circle.com/stablecoins/what-is-eurc.md; bridge-stablecoin https://github.com/circlefin/skills/blob/master/plugins/circle/skills/bridge-stablecoin/SKILL.md (crosschain transfers via CCTP, USDC, EURC, and third-party assets); use-arc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md (Arc chain config, contract deployment, USDC bridging — Arc docs: https://docs.arc.io/llms.txt); use-circle-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md (choose wallet type); use-developer-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md (custodial wallets for payouts and treasury); use-user-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md (embedded wallets with Web2 login); use-modular-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md (smart contract wallets with passkeys and ERC-4337); use-gateway https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md (unified USDC balance, nanopayments); use-smart-contract-platform https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md (deploy, interact, monitor contracts). Pair any skill with the Circle MCP server for live SDK signatures, contract addresses, and chain IDs: {"mcpServers":{"circle":{"url":"https://api.circle.com/v1/codegen/mcp"}}}.
> Read the product overview first. Each product has an overview explaining when and why to use it. Read it before quickstarts.
> Pick the right wallet type. Developer-controlled (you hold keys), user-controlled (end user holds keys via PIN/social login), or modular (smart contract wallets with passkeys). See https://developers.circle.com/wallets.md.
> Use CCTP V2 for crosschain transfers. CCTP natively transfers USDC and EURC via burn-and-mint, and supports permissionless wrapping of third-party assets via lock-and-mint. V1 is legacy; always use V2 unless V1 is specified or the chain requires it (Noble, Sui, and Aptos still require V1). Migration guide: https://developers.circle.com/cctp/migration-from-v1-to-v2.md.
> Use Bridge Kit for frontend bridging. Wraps CCTP with a simpler SDK for user-facing apps. Use CCTP directly for backend transfers.
> Gas Station vs Paymaster. Gas Station sponsors gas for Circle Wallet transactions. Paymaster lets users pay gas in USDC. Different use cases — read both overviews.
> Gateway Nanopayments for sub-cent payments. Gasless USDC micropayments down to $0.000001 via x402 and batched settlement. For pay-per-request APIs, AI agent payments, streaming.
> Look up USDC addresses per chain. Never hardcode — use https://developers.circle.com/stablecoins/usdc-contract-addresses.md.
> Prefer SDKs over raw API calls. Node.js and Python SDKs handle auth, retries, and errors.
> API key required. Bearer token in Authorization header. Testnet and mainnet use separate keys and may use different base URLs depending on the product.
> Set up webhooks when available. Most operations are async. Webhooks deliver transaction confirmations and state changes.
> When calling list endpoints, paginate using pageSize and pageAfter until no nextPageAfter cursor is returned—stopping at the first page silently misses records.
> Building an AI agent? Start with the Agent Stack—Circle CLI, agent wallets, and nanopayments built for autonomous use cases: https://developers.circle.com/agent-stack.md.

# Onboard customers

> Create a business client, complete KYB verification, and get an active stablecoin account using the End User Onboarding API in sandbox

Walk through the full onboarding flow: create a business client, complete KYB
verification, upload documents, submit the application, and retrieve your active
stablecoin account.

<Note>
  This is the Digital Asset Accounts onboarding path, built on Circle's shared
  [End User Onboarding API](/end-user-onboarding). Follow this quickstart for
  the DAA flow; see the End User Onboarding docs for the full API reference and
  advanced scenarios such as [Requests for
  Information](/end-user-onboarding/howtos/handle-rfis) and [device-risk
  signals](/end-user-onboarding/howtos/collect-device-risk-signals).
</Note>

<Note>
  The Digital Asset Accounts API base URL is `https://api-sandbox.circle.com` for
  sandbox and `https://api.circle.com` for production. Set your API key in the
  `Authorization` header using the format `Bearer YOUR_API_KEY`. See
  [Sandbox environment](/digital-asset-accounts/references/testing-in-sandbox) and
  [Going to production](/digital-asset-accounts/references/going-to-production)
  for environment details.
</Note>

## Prerequisites

Before you begin this quickstart, ensure you've:

* Requested and received Digital Asset Accounts sandbox access from your Circle
  representative. See
  [Sandbox environment](/digital-asset-accounts/references/testing-in-sandbox)
  for details.
* Obtained an API key for Digital Asset Accounts from your Circle
  representative.
* (Recommended) Configured a
  [webhook subscription](/api-reference/webhook-endpoints#v2-notifications) for
  tracking asynchronous events.

## Step 1: Create a business client

Create a new business client using the End User Onboarding API. Each client
represents a business entity that goes through KYB verification.

```shell theme={null}
curl --request POST \
  --url https://api-sandbox.circle.com/v1/partner/clients \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "clientName": "My Company ABC1",
    "country": "US",
    "clientType": "business",
    "businessDetails": {
      "natureOfBusiness": "paymentProcessorPlatform",
      "institutionType": "privateCo"
    }
  }'
```

Replace `YOUR_API_KEY` with your Bearer token. Use a unique `clientName` for
each new client, because the API rejects duplicate names.

<Warning>
  **Keep your API keys safe.** Never share your API key or record it in a publicly
  accessible medium such as client-side code or public repositories.
</Warning>

Save the `clientEntityId` and `applicationId` from the response. You need both
values for the remaining steps.

```json theme={null}
{
  "data": {
    "clientEntityId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "applicationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }
}
```

## Step 2: Complete business information

Fill out the required business information sections. Replace `{applicationId}`
with the value from step 1 in all of the following requests.

### 2.1. Basic business info

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/basicBusinessInfo \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "businessWebsite": "https://mycompany.example.com",
    "businessWebsiteProvided": true,
    "businessModelDescription": "Digital payments platform for stablecoin transfers",
    "customerTypesDescription": "Small businesses and individual consumers in the US",
    "productsAndServicesDescription": "USDC payments, deposits, and withdrawals"
  }'
```

### 2.2. Business address

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/physicalBusinessAddress \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "physicalAddressLine1": "1 Main St",
    "physicalAddressCity": "New York",
    "physicalAddressState": "NY",
    "physicalAddressPostalCode": "10001",
    "physicalAddressCountry": "US",
    "businessAddressRemote": false,
    "physicalAddressProofOfAddress": []
  }'
```

### 2.3. Business registration

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/businessRegistrationDetails \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "businessName": "My Company ABC1",
    "businessNameDifferent": false,
    "registrationNumber": "00-0000000",
    "taxId": "00-0000000",
    "countryOfFormation": "US",
    "businessStateOfRegistrationOfFormation": "NY",
    "dateOfFormation": "2010-01-01"
  }'
```

<Note>
  The `businessName` value must match the `clientName` you used in step 1.
</Note>

## Step 3: Complete the remaining KYB sections

Six more sections need data before you can submit the application. The following
calls use placeholder data that is valid for sandbox testing.

### 3.1. Entity operations

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/entityOperations \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "entityServesCustomers": true,
    "countriesWithMostCustomers": ["US"],
    "countriesWithPhysicalPresence": ["US"],
    "businessAcceptsPrivacyCoin": false,
    "customerBaseByType": { "individuals": "70", "businesses": "30" }
  }'
```

### 3.2. Compliance details

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/financialCrimesComplianceDetails \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "complianceOfficerDetailsProvided": false,
    "noComplianceOfficerDetailsReason": "Outsourced to external compliance firm",
    "lastYearAmlProgramProvided": false,
    "noLastYearAmlProgramReason": "Entity less than 1 year old",
    "amlTestingReportProvided": false,
    "noAmlTestingReportReason": "Entity less than 1 year old"
  }'
```

### 3.3. Licensing

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/licensingAndRegistration \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "licenseAndRegistrationRequired": false,
    "noLicenseAndRegistrationRequiredReason": "Not required in jurisdiction"
  }'
```

### 3.4. Beneficial owners

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/beneficialOwnersDetails \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "beneficialOwnersExist": false,
    "beneficialOwnershipExempted": true,
    "beneficialOwnershipExemptionReason": "Single owner private company"
  }'
```

### 3.5. Intended use of account

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/intendedUseOfAccount \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "accountPurpose": ["paymentProcessingPlatform"],
    "accountPurposeDescription": "USDC payments and transfers",
    "expectedMonthlyFiatActivity": "from0to100k",
    "expectedMonthlyCryptoActivity": "from0to100k",
    "expectedProductsForUsage": ["circleMint"],
    "sourceOfFunds": ["businessOperatingFunds"],
    "sourceOfFundsDescription": "Revenue from platform services",
    "financialDocumentsProvided": false,
    "noFinancialDocumentReason": "New entity",
    "assetsUnderManagement": "from0to10m",
    "bankBrokerageCryptoStatement": []
  }'
```

### 3.6. Control person

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/individualWithSignificantControlPersons \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '[{
    "controllerFirstName": "Jane",
    "controllerLastName": "Smith",
    "controllerDob": "1985-06-15",
    "controllerCitizenship": ["US"],
    "controllerIdentificationNumber": "000-00-0000",
    "controllerJobTitle": "Director",
    "controllerLine1": "1 Main St",
    "controllerCity": "New York",
    "controllerState": "NY",
    "controllerPostalCode": "10001",
    "controllerCountry": "US"
  }]'
```

## Step 4: Upload documents

Upload six PDF documents required for KYB verification. For sandbox testing,
create a minimal dummy PDF:

```shell theme={null}
printf '%%PDF-1.0\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj\nxref\n0 4\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \n0000000115 00000 n \ntrailer<</Size 4/Root 1 0 R>>\nstartxref\n190\n%%%%EOF' > /tmp/dummy.pdf
```

Upload each document. Save the `documentId` from each response because you need
them to link documents back to their sections.

```shell theme={null}
# Business formation document
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/documents \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  -F fileContent=@/tmp/dummy.pdf -F fileName=formation.pdf \
  -F datumName=businessFormationDocuments -F issuedCountry=US

# Financial statements
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/documents \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  -F fileContent=@/tmp/dummy.pdf -F fileName=financials.pdf \
  -F datumName=financialStatements -F issuedCountry=US

# Proof of address
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/documents \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  -F fileContent=@/tmp/dummy.pdf -F fileName=address.pdf \
  -F datumName=physicalAddressProofOfAddress -F issuedCountry=US

# Bank statement
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/documents \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  -F fileContent=@/tmp/dummy.pdf -F fileName=bank.pdf \
  -F datumName=bankBrokerageCryptoStatement -F issuedCountry=US

# Ownership chart
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/documents \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  -F fileContent=@/tmp/dummy.pdf -F fileName=ownership.pdf \
  -F datumName=ownershipChart -F issuedCountry=US
```

### 4.1. Upload the control person's government ID

The control person's government ID requires a `refId` and `documentType`. First,
retrieve the `refId`:

```shell theme={null}
curl --request GET \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/individualWithSignificantControlPersons \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

Find the `refId` value in `data.data[0].refId`, then upload the document:

```shell theme={null}
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/documents \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  -F fileContent=@/tmp/dummy.pdf -F fileName=govid.pdf \
  -F datumName=controllerGovernmentId -F issuedCountry=US \
  -F refId={refId} -F documentType=passport
```

### 4.2. Re-save sections with document references

After uploading, link the documents back to their sections by re-saving the
section with the `documentId` values. For example, re-save
`businessRegistrationDetails` with the formation document:

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/sections/businessRegistrationDetails \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "businessName": "My Company ABC1",
    "businessNameDifferent": false,
    "registrationNumber": "00-0000000",
    "taxId": "00-0000000",
    "countryOfFormation": "US",
    "businessStateOfRegistrationOfFormation": "NY",
    "dateOfFormation": "2010-01-01",
    "businessFormationDocuments": [{ "documentId": "YOUR_DOC_ID" }]
  }'
```

Repeat for these sections, adding the relevant `documentId` arrays:

* `physicalBusinessAddress`: add `physicalAddressProofOfAddress`
* `intendedUseOfAccount`: add `bankBrokerageCryptoStatement` and
  `financialStatements`
* `beneficialOwnersDetails`: add `ownershipChart`

## Step 5: Submit the application

Verify that all sections show a `complete` status:

```shell theme={null}
curl --request GET \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId} \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

When all sections are complete, submit the application:

```shell theme={null}
curl --request POST \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/{applicationId}/submit \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header "X-Idempotency-Key: $(uuidgen)" \
  --data '{
    "endUserIpAddress": "203.0.113.1",
    "endUserAgreesToTermsOfService": true
  }'
```

<Note>
  In sandbox, the application is auto-approved almost immediately. In production,
  KYB verification takes time and may result in rejection.
</Note>

## Step 6: Retrieve your account

After the application is approved, retrieve the account using the
`clientEntityId` from step 1:

```shell theme={null}
curl --request GET \
  --url "https://api-sandbox.circle.com/v1/accounts?clientEntityId={clientEntityId}" \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

The response includes your active stablecoin account:

```json theme={null}
{
  "data": [
    {
      "accountId": "1017407114",
      "clientEntityId": "992063fe-d52f-3b1e-ab2d-637dd0b0f36e",
      "type": "client",
      "status": "active",
      "description": "Digital Asset Account External Entity Wallet",
      "balances": []
    }
  ]
}
```

Your `accountId` is now ready for deposits, withdrawals, and transfers. See
[Wire deposits and withdrawals](/digital-asset-accounts/howtos/wire-deposits-and-withdrawals)
to fund your account.

<Note>
  If you serve end users in the European Economic Area (EEA), money-movement
  operations require Strong Customer Authentication (SCA). Whether SCA applies
  depends on each end user, not on your platform. Before your first transfer or
  withdrawal, see [How SCA
  works](/digital-asset-accounts/concepts/strong-customer-authentication) and
  [Implement
  SCA](/digital-asset-accounts/howtos/strong-customer-authentication).
</Note>

## Common issues

| Problem | Solution |
| :- | :- |
| `500` when creating client | The company name was already used. Use a different `clientName`. |
| `422` on intended use of account | Verify that enum values are exact matches. |
| Section stuck on `incomplete` | Confirm that `taxId` is set in `businessRegistrationDetails`. |
| `400` on submit | A section is not complete, or the `X-Idempotency-Key` header is missing. |
| `422` on government ID upload | Add `documentType=passport` to the upload request. |
