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

# How-to: Create and populate applications

> Retrieve onboarding applications, discover the schema, and save section data

<Note>
  The End User Onboarding API base URL is `https://api-sandbox.circle.com` for
  sandbox and `https://api.circle.com` for production. All requests require a
  Bearer token obtained via Circle key exchange in the `Authorization` header. All
  `POST` requests require an `X-Idempotency-Key` header with a client-generated
  UUID v4.
</Note>

Populate an onboarding application by creating a client, reading the schema,
listing sections, and saving field data (individually or in bulk), and cancel
draft applications you no longer need.

## Prerequisites

Before you begin, ensure that you've:

* Obtained an API key for the End User Onboarding API from the
  [Circle Mint Console](https://console.circle.com).

## Steps

### Step 1. Create a client and initialize the application

#### 1.1. Create a client record and initialize onboarding

Create a client record and initialize an onboarding application in one request:

```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 "Accept: application/json" \
  --data '{
    "clientName": "Acme Trust Co.",
    "country": "US",
    "clientType": "business",
    "businessDetails": {
      "natureOfBusiness": "trust",
      "institutionType": "trust"
    }
  }'
```

For the full list of request fields, see the
[Create partner client](/api-reference/end-user-onboarding/create-partner-client)
API reference.

**Example response:**

```json theme={null}
{
  "data": {
    "clientEntityId": "880e8400-e29b-41d4-a716-446655440099",
    "applicationId": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

#### 1.2. Save the application ID

Save the `applicationId`. You'll use it in all subsequent
`/v1/onboarding/partner/applications/...` calls.

<Note>
  Using the same `clientName` and `country` combination returns the existing
  client. Use a different `clientName` to create another client in the same
  country.
</Note>

#### 1.3. Retrieve the newly created application

Retrieve the newly created application to inspect its type, sections, and
status:

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

**Example response:**

```json theme={null}
{
  "data": {
    "applicationId": "550e8400-e29b-41d4-a716-446655440000",
    "type": "ONBOARDING",
    "status": "DRAFT",
    "sections": [
      { "sectionName": "basicBusinessInfo", "status": "not_started" },
      { "sectionName": "physicalBusinessAddress", "status": "not_started" },
      { "sectionName": "beneficial_owners", "status": "not_started" }
    ],
    "pendingRfis": []
  }
}
```

The `type` field identifies the purpose of the application. Partners can create
only `ONBOARDING` applications through the client creation flow shown here.
Other application types may appear in application responses, but they are not
partner-created through this flow. See
[Application types](/end-user-onboarding/references/application-states#application-types)
for the full list of types.

### Step 2. Discover the schema

Retrieve the JSON Schema (draft 2020-12) for your application. It defines every
required field:

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

The schema is a single JSON document. Top-level properties map to section names.
Each section lists its fields, types, and validation rules such as `minLength`,
`maxLength`, `pattern`, `enum`, and `format`.

Use this schema to:

* Enumerate all sections and their fields.
* Drive client-side form rendering and validation.
* Understand which fields are conditional. See
  [Conditional logic](/end-user-onboarding/concepts/conditional-logic) for
  details.

<Tip>
  Pass `?resolved=true` to receive a schema pruned against the application's
  current saved data. Conditional branches that have not been activated are
  removed, so you only see the fields relevant to the current application state.
</Tip>

### Step 3. List all sections

List all sections with their current completion status:

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

Each section has a status: `not_started`, `incomplete`, `complete`, or
`action_required`.

**Example response:**

```json theme={null}
{
  "data": {
    "sections": [
      { "sectionName": "basicBusinessInfo", "status": "not_started" },
      { "sectionName": "physicalBusinessAddress", "status": "not_started" },
      { "sectionName": "beneficial_owners", "status": "not_started" }
    ]
  }
}
```

To include each section's current field data in the same response, add
`?includeData=true`.

### Step 4. Save section data

Save data for a single section:

```shell theme={null}
curl --request PUT \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/${APPLICATION_ID}/sections/basicBusinessInfo \
  --header "Authorization: Bearer ${YOUR_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
    "businessWebsite": "https://example.com",
    "businessWebsiteProvided": true
  }'
```

The server validates the payload against the JSON Schema before saving. If
validation fails, the API returns a `422` response with per-field errors. Each
error includes a dot-notation path, error code, and message.

<Tip>
  By default, array/object/number field values are returned as strings on
  [Get section](/api-reference/end-user-onboarding/get-section),
  [List sections](/api-reference/end-user-onboarding/list-sections),
  [Save section](/api-reference/end-user-onboarding/save-section),
  [Bulk save](/api-reference/end-user-onboarding/bulk-save), and
  [Get all application data](/api-reference/end-user-onboarding/get-all-data).
  Pass `?typedValues=true` on any of these to receive native JSON types instead.
</Tip>

**Example `422` error response:**

```json theme={null}
{
  "errors": [
    {
      "path": "businessWebsite",
      "code": "format",
      "message": "must be a valid URL"
    }
  ]
}
```

<Warning>
  Saving a section may change other sections' statuses. For example, a conditional
  section may become required. The response includes a `sectionsChanged` flag.
  Check this flag and re-fetch sections as needed.

  The response also includes a `fieldsChanged` flag. When `true`, the server
  modified one or more field values during save (for example, clearing a field
  that is no longer applicable after a conditional change). Re-fetch the section
  data if you need to display the current saved state.
</Warning>

Array sections have their own save semantics on top of the preceding flags.

<Note>
  Array sections, such as beneficial owners or controllers, use create-or-update
  semantics. Save an existing entity with its `refId`; omitting `refId` creates a
  new entity. If you upload a document for an array entity, save the array section
  again with the returned `documentId` in the entity's document field. See
  [Array sections](/end-user-onboarding/concepts/array-sections) and
  [Upload documents](/end-user-onboarding/howtos/upload-documents) for examples.
</Note>

**Example response:**

```json theme={null}
{
  "data": {
    "data": {
      "businessWebsite": "https://example.com",
      "businessWebsiteProvided": true
    },
    "sections": [
      { "sectionName": "basicBusinessInfo", "status": "complete" },
      { "sectionName": "physicalBusinessAddress", "status": "not_started" },
      { "sectionName": "beneficial_owners", "status": "not_started" }
    ],
    "sectionsChanged": false,
    "fieldsChanged": false
  }
}
```

### Step 5. Bulk save (optional)

If your backend already has all the data, use the bulk save endpoint. It fills
multiple sections in one request:

```shell theme={null}
curl --request PATCH \
  --url https://api-sandbox.circle.com/v1/onboarding/partner/applications/${APPLICATION_ID}/data \
  --header "Authorization: Bearer ${YOUR_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
    "basicBusinessInfo": {
      "businessWebsite": "https://example.com",
      "businessWebsiteProvided": true
    },
    "physicalBusinessAddress": {
      "physicalAddressLine1": "123 Main St",
      "physicalAddressCity": "San Francisco",
      "physicalAddressCountry": "US",
      "physicalAddressPostalCode": "94102"
    }
  }'
```

Validation is atomic. The API checks all sections against the JSON Schema before
saving. If any section fails, no data is written. The response lists errors
across all sections.

After validation passes, sections save one at a time. Saving a section may
activate other conditional sections. Sections are checked against data already
saved, so a field that turns on a section and that section's data can't be in
the same request. Save the gate field first. If a failure occurs mid-save,
earlier sections may already be persisted.

#### When to use bulk vs. per-section

| Use case | Recommended endpoint |
| - | - |
| Interactive form-based UI (one section at a time) | `PUT /sections/{sectionName}` |
| Programmatic integration with all data available | `PATCH /data` |
| RFI response updating multiple affected sections | `PATCH /data` |
| Reading saved data or deleting individual entities | `GET`/`DELETE /sections/...` |

### Step 6. Read all saved data

To retrieve the complete current state of an application in one request, use the
bulk read endpoint:

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

The response `data` field is an object keyed by section name, using the same
structure as the `PATCH /data` request body. This makes it straightforward to
pre-fill a UI or sync application state to your backend. The `sections` array
lists each visible section with its current status. For full parameter and
response details, see the
[Get all application data](/api-reference/end-user-onboarding/get-all-data) API
reference.

**Example response:**

```json theme={null}
{
  "data": {
    "data": {
      "basicBusinessInfo": {
        "businessWebsite": "https://example.com",
        "businessWebsiteProvided": true
      },
      "physicalBusinessAddress": {
        "physicalAddressLine1": "123 Main St",
        "physicalAddressCity": "San Francisco",
        "physicalAddressCountry": "US",
        "physicalAddressPostalCode": "94102"
      }
    },
    "sections": [
      { "sectionName": "basicBusinessInfo", "status": "complete" },
      { "sectionName": "physicalBusinessAddress", "status": "complete" }
    ]
  }
}
```

## Cancel an application

Cancel a `DRAFT` application that is no longer needed:

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

You can only cancel applications in `DRAFT` status. Other statuses return a
`409` error.

## See also

* [Upload documents](/end-user-onboarding/howtos/upload-documents)
* [Submit and track applications](/end-user-onboarding/howtos/submit-and-track-applications)
* [Application types and states](/end-user-onboarding/references/application-states#application-types)
* [Conditional logic](/end-user-onboarding/concepts/conditional-logic)
* [Array sections](/end-user-onboarding/concepts/array-sections)
