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.
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
CPN Console.
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:
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.
Example response:
{
"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.
Using the same clientName and country combination returns a 409 Conflict
error. Use a different clientName to create another client in the same
country.
1.3. Retrieve the newly created application
Retrieve the newly created application to inspect its sections and statuses:
curl --request GET \
--url https://api-sandbox.circle.com/v1/onboarding/partner/applications/${APPLICATION_ID} \
--header "Authorization: Bearer ${YOUR_API_KEY}"
Example response:
{
"data": {
"applicationId": "550e8400-e29b-41d4-a716-446655440000",
"status": "DRAFT",
"sections": [
{ "sectionName": "basicBusinessInfo", "status": "not_started" },
{ "sectionName": "physicalBusinessAddress", "status": "not_started" },
{ "sectionName": "beneficial_owners", "status": "not_started" }
],
"pendingRfis": []
}
}
Step 2. Discover the schema
Retrieve the JSON Schema (draft 2020-12) for your application. It defines every
required field:
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
for details.
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.
Step 3. List all sections
List all sections with their current completion status:
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:
{
"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:
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.
Example 422 error response:
{
"errors": [
{
"path": "businessWebsite",
"code": "format",
"message": "must be a valid URL"
}
]
}
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.
Example response:
{
"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:
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. 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:
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, the same structure
as the PATCH /data request body, making 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.
Example response:
{
"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:
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