Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/preview/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ These features are in active development and will be available soon. Some may be

| Feature | Description | ETA |
|---------|-------------|-----|
| <span style={{whiteSpace: 'nowrap'}}>-</span> | - | <span style={{whiteSpace: 'nowrap'}}>-</span> |
| <span style={{whiteSpace: 'nowrap'}}>[Account onboarding enhancements](/preview/new-onboarding)</span> | Redesigned onboarding mutations and queries with cleaner naming, typed responses, and improved data collection for compliance. | <span style={{whiteSpace: 'nowrap'}}>Q1, 2026</span> |

</div>

Expand All @@ -26,6 +26,6 @@ These features are in beta and available for testing. We use feedback to refine

| Feature | Description | ETA |
|---------|-------------|-----|
| <span style={{whiteSpace: 'nowrap'}}>[Card insurance](card-insurance)</span> | Comprehensive insurance coverage for Swan-issued cards including theft, fraud, and travel protection | <span style={{whiteSpace: 'nowrap'}}>In private beta</span> |
| <span style={{whiteSpace: 'nowrap'}}>[Card insurance](/preview/card-insurance)</span> | Comprehensive insurance coverage for Swan-issued cards including theft, fraud, and travel protection. | <span style={{whiteSpace: 'nowrap'}}>In private beta</span> |

</div>
132 changes: 132 additions & 0 deletions docs/preview/new-onboarding/company.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
---
title: Company onboarding fields
---

# Company onboarding fields

Field reference for company account holder onboarding.

:::warning Work in progress
Field requirements and validations are being finalized. This section will be updated before release.
:::

## Account

| API v1 | API v2 |
|---|---|
| `accountCountry` | `accountInfo.country` |
| `accountName` | `accountInfo.name` |
| - | `accountInfo.intendedUsages` <sup>(new)</sup> |

## Account administrator

| API v1 | API v2 |
|---|---|
| `legalRepresentativePersonalAddress.addressLine1` | `accountAdmin.address.addressLine1` |
| `legalRepresentativePersonalAddress.addressLine2` | `accountAdmin.address.addressLine2` |
| `legalRepresentativePersonalAddress.city` | `accountAdmin.address.city` |
| `legalRepresentativePersonalAddress.country` | `accountAdmin.address.country` |
| `legalRepresentativePersonalAddress.postalCode` | `accountAdmin.address.postalCode` |
| `legalRepresentativePersonalAddress.state` | `accountAdmin.address.state` |
| - | `accountAdmin.birthInfo.birthDate` <sup>(new)</sup> |
| - | `accountAdmin.birthInfo.city` <sup>(new)</sup> |
| - | `accountAdmin.birthInfo.country` <sup>(new)</sup> |
| - | `accountAdmin.birthInfo.postalCode` <sup>(new)</sup> |
| `email` | `accountAdmin.email` |
| - | `accountAdmin.firstName` |
| - | `accountAdmin.lastName` <sup>(new)</sup> |
| - | `accountAdmin.nationality` <sup>(new)</sup> |
| `language` | `accountAdmin.preferredLanguage` |
| - | `accountAdmin.taxIdentificationNumber` <sup>(new)</sup> |
| `typeOfRepresentation` | `accountAdmin.typeOfRepresentation` |
| - | `accountAdmin.unitedStatesTaxInfo.isUnitedStatesPerson` <sup>(new)</sup> |
| - | `accountAdmin.unitedStatesTaxInfo.unitedStatesTaxIdentificationNumber` <sup>(new)</sup> |
| - | `accountAdmin.userDeviceInfo.geoloc.lat` <sup>(new)</sup> |
| - | `accountAdmin.userDeviceInfo.geoloc.lng` <sup>(new)</sup> |
| - | `accountAdmin.userDeviceInfo.ip` <sup>(new)</sup> |
| - | `accountAdmin.userDeviceInfo.userAgent` <sup>(new)</sup> |

## Company

| API v1 | API v2 |
|---|---|
| `residencyAddress.addressLine1` | `company.address.addressLine1` |
| `residencyAddress.addressLine2` | `company.address.addressLine2` |
| `residencyAddress.city` | `company.address.city` |
| `residencyAddress.country` | `company.address.country` |
| `residencyAddress.postalCode` | `company.address.postalCode` |
| `residencyAddress.state` | `company.address.state` |
| `acquisitionChannel` | `company.acquisitionChannel` |
| `businessActivityDescription` | `company.businessActivityDescription` |
| - | `company.businessActivityCode` <sup>(new)</sup> |
| `companyType` | `company.companyType` |
| - | `company.forecastYearlyIncome` <sup>(new)</sup> |
| - | `company.headcount` <sup>(new)</sup> |
| - | `company.legalFormCode` <sup>(new)</sup> |
| `monthlyPaymentVolume` | `company.monthlyPaymentVolume` |
| `name` | `company.name` |
| - | `company.registrationDate` <sup>(new)</sup> |
| `registrationNumber` | `company.registrationNumber` |
| - | `company.regulatoryClassification` <sup>(new)</sup> |
| - | `company.signupDate` <sup>(new)</sup> |
| `taxIdentificationNumber` | `company.taxIdentificationNumber` |
| `tradeName` | `company.tradeName` |
| `vatNumber` | `company.vatNumber` |
| - | `company.websites` <sup>(new)</sup> |

### Legal representative information

| API v1 | API v2 |
|---|---|
| `representatives[i].residencyAddress.addressLine1` | `company.representatives[i].address.addressLine1` |
| `representatives[i].residencyAddress.addressLine2` | `company.representatives[i].address.addressLine2` |
| `representatives[i].residencyAddress.city` | `company.representatives[i].address.city` |
| `representatives[i].residencyAddress.country` | `company.representatives[i].address.country` |
| `representatives[i].residencyAddress.postalCode` | `company.representatives[i].address.postalCode` |
| `representatives[i].residencyAddress.state` | `company.representatives[i].address.state` |
| `representatives[i].birthDate` | `company.representatives[i].birthInfo.birthDate` |
| `representatives[i].birthCity` | `company.representatives[i].birthInfo.city` |
| `representatives[i].birthCountryCode` | `company.representatives[i].birthInfo.country` |
| `representatives[i].birthCityPostalCode` | `company.representatives[i].birthInfo.postalCode` |
| `representatives[i].entityName` | `company.representatives[i].entityName` |
| `representatives[i].firstName` | `company.representatives[i].firstName` |
| `representatives[i].lastName` | `company.representatives[i].lastName` |
| `representatives[i].legalForm` | `company.representatives[i].legalForm` |
| `representatives[i].nationality` | `company.representatives[i].nationality` |
| `representatives[i].preferredFirstName` | `company.representatives[i].preferredFirstName` |
| `representatives[i].registrationNumber` | `company.representatives[i].registrationNumber` |
| `representatives[i].roles` | `company.representatives[i].roles` |
| `representatives[i].gender` | `company.representatives[i].sex` |
| `representatives[i].type` | `company.representatives[i].type` |
| - | `company.representatives[i].email` <sup>(new)</sup> |

### Ultimate Beneficial Owners

| API v1 | API v2 |
|---|---|
| `individualUltimateBeneficialOwners[i].residencyAddress.addressLine1` | `company.ultimateBeneficialOwners[i].address.addressLine1` |
| `individualUltimateBeneficialOwners[i].residencyAddress.addressLine2` | `company.ultimateBeneficialOwners[i].address.addressLine2` |
| `individualUltimateBeneficialOwners[i].residencyAddress.city` | `company.ultimateBeneficialOwners[i].address.city` |
| `individualUltimateBeneficialOwners[i].residencyAddress.country` | `company.ultimateBeneficialOwners[i].address.country` |
| `individualUltimateBeneficialOwners[i].residencyAddress.postalCode` | `company.ultimateBeneficialOwners[i].address.postalCode` |
| `individualUltimateBeneficialOwners[i].residencyAddress.state` | `company.ultimateBeneficialOwners[i].address.state` |
| `individualUltimateBeneficialOwners[i].birthDate` | `company.ultimateBeneficialOwners[i].birthInfo.birthDate` |
| `individualUltimateBeneficialOwners[i].birthCity` | `company.ultimateBeneficialOwners[i].birthInfo.city` |
| `individualUltimateBeneficialOwners[i].birthCountryCode` | `company.ultimateBeneficialOwners[i].birthInfo.country` |
| `individualUltimateBeneficialOwners[i].birthCityPostalCode` | `company.ultimateBeneficialOwners[i].birthInfo.postalCode` |
| - | `company.ultimateBeneficialOwners[i].controlTypes` <sup>(new)</sup> |
| `individualUltimateBeneficialOwners[i].firstName` | `company.ultimateBeneficialOwners[i].firstName` |
| `individualUltimateBeneficialOwners[i].identityDocumentDetails.expiryDate` | `company.ultimateBeneficialOwners[i].identityDocumentDetails.expiryDate` |
| `individualUltimateBeneficialOwners[i].identityDocumentDetails.issueDate` | `company.ultimateBeneficialOwners[i].identityDocumentDetails.issueDate` |
| `individualUltimateBeneficialOwners[i].identityDocumentDetails.issuingAuthority` | `company.ultimateBeneficialOwners[i].identityDocumentDetails.issuingAuthority` |
| `individualUltimateBeneficialOwners[i].identityDocumentDetails.number` | `company.ultimateBeneficialOwners[i].identityDocumentDetails.number` |
| `individualUltimateBeneficialOwners[i].identityDocumentDetails.type` | `company.ultimateBeneficialOwners[i].identityDocumentDetails.type` |
| `individualUltimateBeneficialOwners[i].lastName` | `company.ultimateBeneficialOwners[i].lastName` |
| `individualUltimateBeneficialOwners[i].direct` | `company.ultimateBeneficialOwners[i].ownership.direct` |
| `individualUltimateBeneficialOwners[i].indirect` | `company.ultimateBeneficialOwners[i].ownership.indirect` |
| `individualUltimateBeneficialOwners[i].totalCapitalPercentage` | `company.ultimateBeneficialOwners[i].ownership.percentage` |
| - | `company.ultimateBeneficialOwners[i].qualificationType` <sup>(new)</sup> |
| `individualUltimateBeneficialOwners[i].gender` | `company.ultimateBeneficialOwners[i].sex` |
| `individualUltimateBeneficialOwners[i].taxIdentificationNumber` | `company.ultimateBeneficialOwners[i].taxIdentificationNumber` |
| - | `company.ultimateBeneficialOwners[i].unitedStatesTaxInfo.isUnitedStatesPerson` <sup>(new)</sup> |
| - | `company.ultimateBeneficialOwners[i].unitedStatesTaxInfo.unitedStatesTaxIdentificationNumber` <sup>(new)</sup> |
230 changes: 230 additions & 0 deletions docs/preview/new-onboarding/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
---
title: Account onboarding enhancements
---

# Account onboarding enhancements

Redesigned onboarding mutations and queries with cleaner naming, typed responses, and improved data collection for enhanced risk assessment and regulatory compliance.

:::info Target availability
This API is in active development and will be available by the end of Q1 2026.
:::

## Overview

We are introducing a redesigned onboarding API that replaces the existing mutations and queries. The new API provides improved developer experience through consistent naming conventions, structured input types, and typed responses.

### What's changing

| Aspect | Current API | New API |
|---|---|---|
| **Naming** | Mixed patterns (`onboardIndividualAccountHolder`, `unauthenticatedOnboardPublic...`). | Consistent pattern (`createIndividualAccountHolderOnboarding`, `createPublicIndividualAccountHolderOnboarding`). |
| **Input structure** | Flat input with all fields at root level. | Nested structure with `accountInfo`, `accountAdmin`, and `company` objects. |
| **Data requirements** | Limited data collection. | New fields to strengthen risk assessment and compliance. |
| **Response types** | Generic `Onboarding` type for all responses. | Typed `IndividualAccountHolderOnboarding` and `CompanyAccountHolderOnboarding`. |
| **Registry data** | Automatically populates empty onboarding fields. | Dedicated query; no auto-population. |

### Authentication patterns

The new API uses a consistent pattern across all endpoints.

| Endpoint type | Token required | Use case |
|---|---|---|
| `Public` mutations and queries | None | Public onboarding links. |
| Standard mutations and queries | Project access token | Backend integrations, partner-initiated onboarding. |
| `finalize` mutation | User access token | Completing onboarding after user identification. |

## Individual onboarding

### Create an individual onboarding

Call the `createIndividualAccountHolderOnboarding` mutation with a project access token.

| New mutation | Replaces |
|---|---|
| `createIndividualAccountHolderOnboarding` | `onboardIndividualAccountHolder` |
| `createPublicIndividualAccountHolderOnboarding` | `unauthenticatedOnboardPublicIndividualAccountHolder` |

The input uses a nested structure with two required objects:

- `accountInfo`: Account-level details (`country`, `name`, `intendedUsages` <sup>(new)</sup>).
- `accountAdmin`: Individual's personal information (`email`, `employmentStatus`, `monthlyIncome`, `address`, `sourcesOfFunds` <sup>(new)</sup>, etc.).

```graphql
input CreateIndividualAccountHolderOnboardingInput {
accountInfo: IndividualAccountHolderOnboardingAccountInput!
accountAdmin: IndividualAccountHolderOnboardingAccountAdminInput!
oAuthRedirectParameters: OAuthRedirectParametersInput
}
```

### Update an individual onboarding

Call the `updateIndividualAccountHolderOnboarding` mutation with a project access token.

| New mutation | Replaces |
|---|---|
| `updateIndividualAccountHolderOnboarding` | `updateIndividualOnboarding` |
| `updatePublicIndividualAccountHolderOnboarding` | `unauthenticatedUpdateIndividualOnboarding` |

## Company onboarding

### Create a company onboarding

Call the `createCompanyAccountHolderOnboarding` mutation with a project access token.

| New mutation | Replaces |
|---|---|
| `createCompanyAccountHolderOnboarding` | `onboardCompanyAccountHolder` |
| `createPublicCompanyAccountHolderOnboarding` | `unauthenticatedOnboardPublicCompanyAccountHolder` |

The input uses a nested structure with three required objects:

- `accountInfo`: Account-level details (`country`, `name`, `intendedUsages` <sup>(new)</sup>).
- `accountAdmin`: Legal representative's personal information (`email`, `firstName`, `lastName`, `typeOfRepresentation`, etc.).
- `company`: Company details (`registrationNumber`, `name`, `legalForm`, `ultimateBeneficialOwners`, `representatives`, etc.).

```graphql
input CreateCompanyAccountHolderOnboardingInput {
accountInfo: CompanyAccountHolderOnboardingAccountInput!
accountAdmin: CompanyAccountHolderOnboardingAccountAdminInput!
oAuthRedirectParameters: OAuthRedirectParametersInput
company: CompanyInfoInput!
}
```

### Update a company onboarding

Call the `updateCompanyAccountHolderOnboarding` mutation with a project access token.

| New mutation | Replaces |
|---|---|
| `updateCompanyAccountHolderOnboarding` | `updateCompanyOnboarding` |
| `updatePublicCompanyAccountHolderOnboarding` | `unauthenticatedUpdateCompanyOnboarding` |

## Finalize onboarding

The `finalizeAccountHolderOnboarding` mutation replaces `finalizeOnboarding`. It requires a **user access token** and returns an `AccountHolderOnboarding` union type.

| New mutation | Replaces |
|---|---|
| `finalizeAccountHolderOnboarding` | `finalizeOnboarding` |

## Queries

### Retrieve onboarding information

| New query | Authentication | Replaces |
|---|---|---|
| `publicAccountHolderOnboarding` | None | `onboardingInfo` |
| `accountHolderOnboarding` | Project access token | `onboarding` |
| `accountHolderOnboardings` | Project access token | `onboardings` |

Single-onboarding queries return a payload union that includes the `AccountHolderOnboarding` on success. The `accountHolderOnboardings` query returns an `AccountHolderOnboardingConnection` for [paginated results](/developers/using-api/pagination).

### Company registry data

A new dedicated query retrieves company information from official registries, enabling pre-fill capabilities for smoother onboarding. Currently available for companies registered in **France (`FRA`) only**. This replaces the previous behavior where empty onboarding fields were automatically populated with registry data.

| New query | Authentication |
|---|---|
| `companyInfoRegistryData` | Project access token |

The query requires a `registrationNumber` and `residencyAddressCountry`.

:::caution Behavior change
The new API **does not** automatically populate onboarding fields with registry data. You must explicitly query the registry, then use that data when creating or updating the onboarding.
:::

#### Query

```graphql
query GetCompanyRegistryData {
companyInfoRegistryData(
input: {
registrationNumber: "123456789"
residencyAddressCountry: FRA
}
) {
... on CompanyInfoRegistryDataSuccessPayload {
companyInfo {
name
legalForm
registrationDate
address {
addressLine1
city
postalCode
country
}
ultimateBeneficialOwners {
firstName
lastName
}
representatives {
... on OnboardingIndividualRepresentative {
firstName
lastName
roles
}
}
}
}
... on CompanyRegistryNotFoundRejection {
message
registrationNumber
country
}
}
}
```

## Field reference

:::warning Work in progress
Field requirements and validations are being finalized. This section will be updated before release.
:::

The following pages provide complete field mappings from the deprecated API to the new API:

- [Individual onboarding fields](./individual)
- [Company onboarding fields](./company)

Field requirements vary by country. French company onboardings support pre-fill via the `companyInfoRegistryData` query for company, representative, and UBO fields.

## Response types

### IndividualAccountHolderOnboarding

```graphql
type IndividualAccountHolderOnboarding implements AccountHolderOnboardingBase {
id: ID!
statusInfo: OnboardingStatusInfo!
supportingDocumentCollection: SupportingDocumentCollection
createdAt: DateTime!
updatedAt: DateTime!
accountInfo: IndividualAccountHolderOnboardingAccount
accountAdmin: IndividualAccountHolderOnboardingAccountAdmin
}
```

### CompanyAccountHolderOnboarding

```graphql
type CompanyAccountHolderOnboarding implements AccountHolderOnboardingBase {
id: ID!
statusInfo: OnboardingStatusInfo!
supportingDocumentCollection: SupportingDocumentCollection
createdAt: DateTime!
updatedAt: DateTime!
accountInfo: CompanyAccountHolderOnboardingAccount
accountAdmin: CompanyAccountHolderOnboardingAccountAdmin
company: CompanyInfo
}
```

### AccountHolderOnboarding union

```graphql
union AccountHolderOnboarding = IndividualAccountHolderOnboarding | CompanyAccountHolderOnboarding
```
Loading