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

# Applications

> Submit an onboarding application referencing persons, consents, and evidence

An **onboarding application** (`onba_...`) ties [persons](/docs/onboarding/persons), consents, and evidence together into one request that kicks off compliance review.

Submission is synchronous. We validate and either accept (`pending`, awaiting review) or return `400` with a precise explanation.

## Request structure

`POST /onboarding-applications` with four top-level fields.

| Field           | Type  | Required | Description                                                                                                |
| --------------- | ----- | -------- | ---------------------------------------------------------------------------------------------------------- |
| `customer_type` | enum  | yes      | `individual`, `business`, or `joint`. See [requirements by customer type](#requirements-by-customer-type). |
| `authorities`   | array | yes      | Non-empty. Persons acting on the resulting customer, and in what capacity.                                 |
| `consents`      | array | no       | Legal document consents. Defaults to empty.                                                                |
| `evidence`      | array | no       | Evidence files. Defaults to empty.                                                                         |

Items reference persons via `person`.

### Authorities

Each authority pins a person to a role. Valid `authority_type` values: `owner`, `joint_owner`, `signatory`, `power_of_attorney`, `trading`. The accepted set and counts are fixed per `customer_type`; see [authority composition](#authority-composition).

A business application pairs a legal-person `owner` with one or more natural-person `signatory` authorities:

```json theme={"theme":"catppuccin-mocha"}
{
  "authorities": [
    {"person": "per_legal_entity", "authority_type": "owner"},
    {"person": "per_ada",          "authority_type": "signatory"}
  ]
}
```

<Note>
  A person can hold at most one authority slot. Duplicate `person` IDs across `authorities` return `400 invalid_request`.
</Note>

<Tip>
  The duplicate-person check runs before the authority-type check. If the same `person` appears under two `authority_type`s, you'll see the duplicate error first. Use distinct persons per slot when debugging authority-type errors.
</Tip>

### Consents

A consent records that a person agreed to a specific [legal document version](/api-reference/list-versions-of-a-legal-document), or made an attestation. See [required consents](#required-consents).

| Field                    | Type     | Required    | Notes                                                                                                    |
| ------------------------ | -------- | ----------- | -------------------------------------------------------------------------------------------------------- |
| `person`                 | string   | yes         | An authority or related person; see [attribution](#per-person-attribution).                              |
| `consent_type`           | string   | yes         | E.g. `terms_of_service`, `data_accuracy`. See [required consents](#required-consents) for the full list. |
| `legal_document_version` | string   | conditional | Required for every `consent_type` except `data_accuracy`. For `data_accuracy`, omit.                     |
| `consented_at`           | datetime | yes         | ISO-8601 timestamp.                                                                                      |

<Warning>
  Legal-document consents need a valid `legal_document_version` whose document type matches the `consent_type`. `data_accuracy` is an attestation; omit `legal_document_version` entirely. Either rule violated returns `400 invalid_request`.
</Warning>

### Evidence

Upload files via the [Files API](/api-reference/create-a-file), then reference the returned IDs.

| Field           | Type         | Required    | Notes                                                                          |
| --------------- | ------------ | ----------- | ------------------------------------------------------------------------------ |
| `person`        | string       | yes         | Person this evidence is for.                                                   |
| `evidence_type` | enum         | yes         | See [evidence taxonomy](#evidence-taxonomy).                                   |
| `document_type` | enum \| null | conditional | See the `document_type` column in the [evidence taxonomy](#evidence-taxonomy). |
| `file`          | string       | yes         | ID of an uploaded file.                                                        |

## Per-person attribution

Every consent and evidence item's `person` must be either an **authority** on this application or a **related person** declared in a `relationships` claim on a legal authority. Anything else returns `400`.

## Duplicate submissions

Applications are de-duplicated by `customer_type` and the set of `(person, authority_type)` pairs in `authorities`.

While an earlier matching application is `pending` or `processing`, a new submission returns `409 conflict`. Once it reaches `completed`, you can resubmit. There's no self-service cancellation; contact support.

## Requirements by customer type

Requirements are defined **per authority slot**: each `(customer_type, authority_type)` pair carries its own required claims, evidence bundles, consents, expected `person_type`, and count. A business `owner` and `signatory` have different sets; neither inherits.

### Authority composition

| `customer_type` | `authority_type` | Expected `person_type` | Count                       |
| --------------- | ---------------- | ---------------------- | --------------------------- |
| `individual`    | `owner`          | `natural`              | exactly 1                   |
| `business`      | `owner`          | `legal`                | exactly 1                   |
| `business`      | `signatory`      | `natural`              | at least 1 (no upper bound) |
| `joint`         | `owner`          | `natural`              | exactly 1                   |
| `joint`         | `joint_owner`    | `natural`              | at least 1 (no upper bound) |

Any other `(customer_type, authority_type)` combination returns `400 invalid_request`. See [composition errors](/docs/onboarding/errors#per-authority-composition-errors).

### Individual

One natural-person `owner`.

**Required claims**: `identity`, `contact_details`, `nationalities`, `residence`, `tax_residencies`, `fatca_status`, `pep_status`, `employment`, `financial_profile`, `investment_experience`, `expected_activity`.

**Required evidence**: three independent requirements:

| For the `identity` claim | Acceptable bundles                                                                           |
| ------------------------ | -------------------------------------------------------------------------------------------- |
|                          | A single `identity_document` of type `passport`                                              |
|                          | **or** two `identity_document` items: one `national_id_front` **and** one `national_id_back` |

| For the `identity` claim | Acceptable bundles                     |
| ------------------------ | -------------------------------------- |
|                          | A single `selfie` (no `document_type`) |

| For the `residence` claim | Acceptable bundles                                                                                     |
| ------------------------- | ------------------------------------------------------------------------------------------------------ |
|                           | One `proof_of_address` with any compatible document type (see [evidence taxonomy](#evidence-taxonomy)) |

**Consents**: owner supplies every consent in [required consents](#required-consents), attributed to themselves.

### Business

One legal-person `owner`, at least one natural-person `signatory`, plus related persons on the legal owner's `relationships` claim. Owner and signatory slots have different requirements.

#### Owner (legal person)

**Required claims**: `registration`, `lei`, `contact_details`, `registered_address`, `business_nature`, `relationships`.

An additional `operating_address` claim is required when `registered_address.operating_address_is_same` is `false`. See [conditional requirements](#conditional-requirements).

**Required evidence**:

| On claim             | Required                           | When                                                            |
| -------------------- | ---------------------------------- | --------------------------------------------------------------- |
| `registration`       | One `certificate_of_good_standing` | Always.                                                         |
| `registered_address` | One `proof_of_registered_address`  | Always.                                                         |
| `operating_address`  | One `proof_of_operating_address`   | When `registered_address.operating_address_is_same` is `false`. |
| `business_nature`    | One `financial_statements`         | Always.                                                         |
| `relationships`      | One `certificate_of_directors`     | Always.                                                         |
| `relationships`      | One `certificate_of_shareholders`  | Always.                                                         |
| `relationships`      | One `ownership_structure`          | Always.                                                         |
| `relationships`      | One `nominee_agreement`            | When `business_nature.has_nominee_shareholders` is `true`.      |

Six items are always required; two are predicate-gated. Missing or unmatched evidence surfaces as `400 invalid_request` with `detail: "No acceptable evidence bundle submitted for claim '<claim_type>' on person <legal_owner_person_id>."`; the `<claim_type>` matches the first column above, so you can map the error straight back to the row you missed.

**Consents**: none. The legal owner's consent bundle is empty; consents come from the signatories.

**Related persons**: see [related-person requirements](#related-person-requirements).

#### Signatory (natural person)

One per person signing for the business. Signatories carry the full natural-person profile.

**Required claims**: `identity`, `contact_details`, `nationalities`, `residence`, `tax_residencies`, `fatca_status`, `pep_status`, `employment`, `financial_profile`, `investment_experience`, `expected_activity`.

**Required evidence**:

| For the `identity` claim | Acceptable bundles                                                                           |
| ------------------------ | -------------------------------------------------------------------------------------------- |
|                          | A single `identity_document` of type `passport`                                              |
|                          | **or** two `identity_document` items: one `national_id_front` **and** one `national_id_back` |

| For the `identity` claim | Acceptable bundles                     |
| ------------------------ | -------------------------------------- |
|                          | A single `selfie` (no `document_type`) |

| For the `residence` claim | Acceptable bundles                                       |
| ------------------------- | -------------------------------------------------------- |
|                           | One `proof_of_address` with any compatible document type |

| Authorising claim     | Required                                             |
| --------------------- | ---------------------------------------------------- |
| For signing authority | One `board_resolution`, attributed to this signatory |

**Consents**: each signatory supplies every consent in [required consents](#required-consents), attributed to themselves.

### Joint

One natural-person `owner` plus one or more natural-person `joint_owner`s. Every party carries the same requirements as an individual owner, each attributed to that person.

**Required claims (per party)**: `identity`, `contact_details`, `nationalities`, `residence`, `tax_residencies`, `fatca_status`, `pep_status`, `employment`, `financial_profile`, `investment_experience`, `expected_activity`.

**Required evidence (per party)**: three independent requirements:

| For the `identity` claim | Acceptable bundles                                                                           |
| ------------------------ | -------------------------------------------------------------------------------------------- |
|                          | A single `identity_document` of type `passport`                                              |
|                          | **or** two `identity_document` items: one `national_id_front` **and** one `national_id_back` |

| For the `identity` claim | Acceptable bundles                     |
| ------------------------ | -------------------------------------- |
|                          | A single `selfie` (no `document_type`) |

| For the `residence` claim | Acceptable bundles                                       |
| ------------------------- | -------------------------------------------------------- |
|                           | One `proof_of_address` with any compatible document type |

**Consents**: every natural authority supplies every consent in [required consents](#required-consents), each attributed to the party giving it.

### Required consents

Who supplies the consents depends on customer type:

* **Individual**: the owner.
* **Joint**: every natural authority, each attributed to themselves.
* **Business**: every signatory, each attributed to themselves. The legal-entity owner does not consent.

The same nine consents apply in every case:

| `consent_type`                      | `legal_document_version` |
| ----------------------------------- | ------------------------ |
| `terms_of_service`                  | required                 |
| `investment_service_agreement`      | required                 |
| `risk_disclosures`                  | required                 |
| `conflicts_of_interest_policy`      | required                 |
| `complaints_handling_policy`        | required                 |
| `client_assets_safeguarding_policy` | required                 |
| `investor_compensation_fund_policy` | required                 |
| `order_execution_policy`            | required                 |
| `data_accuracy`                     | must be omitted          |

`data_accuracy` is an attestation; the person attests that the information they provided is accurate, so there is no legal document to version. Sending `legal_document_version` with it returns `400 invalid_request`.

For every other consent, fetch a live document version via [`GET /legal-documents/{legal_document_id}/versions`](/api-reference/list-versions-of-a-legal-document) and pass its ID. The version's document type must equal the `consent_type`; mismatches return `400 invalid_request`.

<Note>
  On a business application, any consent attributed to the legal-entity `owner` is accepted silently and counts for nothing. Missing the required consents on the signatories will still fail the application. Make sure you attribute every consent to a natural `signatory`.
</Note>

## Related-person requirements

Persons declared in a legal authority's `relationships` claim carry their own claim and evidence requirements. Related persons don't supply consents; the application's natural authorities (owner, signatory, joint owners) carry that surface; see [required consents](#required-consents).

**Required claims (every relationship type)**: the full natural-person KYC set, identical to what a natural owner or signatory supplies: `identity`, `contact_details`, `nationalities`, `residence`, `tax_residencies`, `fatca_status`, `pep_status`, `employment`, `financial_profile`, `investment_experience`, `expected_activity`.

Missing any of these returns `400 invalid_request` with `detail: "Missing required claims on {relationship_type} {related_person_id}: [...]"`; the list names the missing `claim_type` values.

**Evidence**: only the appointment-authority bundle varies by role:

| `relationship_type`                                     | Required evidence attributed to this person                                                                                                                             |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `director`, `authorised_signatory`                      | One `identity_document` (passport, **or** `national_id_front` + `national_id_back`); one `selfie` (no `document_type`); one `proof_of_address`; one `board_resolution`. |
| `shareholder`, `beneficial_owner`, `trustee`, `settlor` | One `identity_document` (passport, **or** `national_id_front` + `national_id_back`); one `selfie` (no `document_type`); one `proof_of_address`.                         |

## Conditional requirements

Two requirements on a business application depend on the content of the legal owner's claims. Send the claim values first, then assemble the application with the matching evidence.

### Operating address

If the legal entity operates from its registered address, set `operating_address_is_same` to `true` on the `registered_address` claim and you're done:

```json theme={"theme":"catppuccin-mocha"}
{
  "claim_type": "registered_address",
  "line1": "10 Castle Street",
  "city": "Douglas",
  "postal_code": "IM1 2EZ",
  "country_code": "IM",
  "operating_address_is_same": true
}
```

If the operating address differs, set it to `false`, add an `operating_address` claim, and attach a `proof_of_operating_address` evidence to the legal owner:

```json theme={"theme":"catppuccin-mocha"}
{
  "claim_type": "registered_address",
  "line1": "10 Castle Street",
  "city": "Douglas",
  "postal_code": "IM1 2EZ",
  "country_code": "IM",
  "operating_address_is_same": false
}
```

```json theme={"theme":"catppuccin-mocha"}
{
  "claim_type": "operating_address",
  "line1": "25 Harbour Road",
  "city": "Douglas",
  "postal_code": "IM1 4LB",
  "country_code": "IM"
}
```

Missing either piece returns `400 invalid_request` referencing the legal owner's `person_id`.

### Nominee agreement

If the legal entity uses nominee shareholders, set `has_nominee_shareholders` to `true` on the `business_nature` claim and attach a `nominee_agreement` evidence to the legal owner:

```json theme={"theme":"catppuccin-mocha"}
{
  "claim_type": "business_nature",
  "business_activity": "financial_services",
  "annual_turnover_eur": "1m_3m",
  "is_regulated": true,
  "issues_bearer_shares": false,
  "has_nominee_shareholders": true,
  "has_shell_bank_relationships": false
}
```

Without the evidence, submission fails. If the entity has no nominees, set the field to `false` and omit the evidence.

<Tip>
  The exact error string names the missing claim or evidence and the `person_id` it was expected on. Log these; they tell you exactly what to add before you retry.
</Tip>

## Evidence taxonomy

Combinations outside this matrix return `400 invalid_request`.

| `evidence_type`                | `document_type` | Allowed values                                              |
| ------------------------------ | --------------- | ----------------------------------------------------------- |
| `identity_document`            | required        | `passport`, **or** `national_id_front` + `national_id_back` |
| `selfie`                       | null only       | —                                                           |
| `board_resolution`             | required        | `board_resolution`                                          |
| `proof_of_address`             | optional        | `utility_bill`, `bank_statement`, `tax_document`            |
| `proof_of_registered_address`  | optional        | `utility_bill`, `bank_statement`                            |
| `proof_of_operating_address`   | optional        | `utility_bill`, `bank_statement`                            |
| `certificate_of_good_standing` | optional        | `certificate_of_good_standing`, `incumbency_certificate`    |
| `certificate_of_shareholders`  | optional        | `shareholder_register`, `share_certificate`                 |
| `certificate_of_directors`     | optional        | `director_register`, `board_minutes`                        |
| `financial_statements`         | optional        | `audited_accounts`, `management_accounts`                   |
| `ownership_structure`          | optional        | `ubo_declaration`, `org_chart`                              |
| `nominee_agreement`            | optional        | `trust_deed`, `nominee_agreement`                           |

`optional` means: omit `document_type` to match the generic bundle, or pass one of the listed values to pin the kind. Any other value returns `400 invalid_request` with `detail: "document_type '<Y>' is not compatible with evidence_type '<X>'"`. Sending `document_type` for `selfie` returns `Evidence type 'selfie' does not accept a document_type.`

<Note>
  `driving_license`, `driving_license_front`, and `driving_license_back` are in the `DocumentType` enum but don't satisfy the default `identity_document` bundle. National IDs are always the front + back pair; there's no single-sided `national_id`.
</Note>

### Which evidence types apply to each person type

Natural-person evidence (`identity_document`, `proof_of_address`, `selfie`, `board_resolution`) is only valid against natural-person authorities and related persons. Legal-entity evidence (`certificate_of_*`, `financial_statements`, `ownership_structure`, `proof_of_registered_address`, `proof_of_operating_address`, `nominee_agreement`) is only valid against legal-person authorities. Mismatches return `400`.

`board_resolution` belongs to the natural person it authorises; the signatory on a business application, or the `director` / `authorised_signatory` related person on the legal owner's `relationships` claim. Attribute it via that person's `person_id`, not the legal entity's.

## Response

`201 Created` with the application resource:

```json theme={"theme":"catppuccin-mocha"}
{
  "id": "onba_m4k7r9s2",
  "created_at": "2026-04-18T09:30:00Z",
  "modified_at": "2026-04-18T09:30:00Z",
  "customer_type": "individual",
  "status": "pending",
  "outcome": null,
  "application": {
    "customer_type": "individual",
    "authorities": [
      {"person": "per_ada", "authority_type": "owner"}
    ],
    "consents": [
      {"person": "per_ada", "consent_type": "terms_of_service", "legal_document_version": "legal_doc_ver_tos_v3", "consented_at": "2026-04-18T09:30:00Z"}
    ],
    "evidence": [
      {"person": "per_ada", "evidence_type": "identity_document", "document_type": "passport", "file": "fil_passport"}
    ]
  }
}
```

| Field           | Description                                           |
| --------------- | ----------------------------------------------------- |
| `id`            | Application ID, prefix `onba_`.                       |
| `customer_type` | Echoes the submitted value.                           |
| `status`        | Always `pending` on submission.                       |
| `outcome`       | Always `null` on submission. Populated once terminal. |
| `application`   | The submitted payload, stored as-is.                  |

### Application statuses and outcomes

| `status`     | Meaning                       |
| ------------ | ----------------------------- |
| `pending`    | Queued for compliance review. |
| `processing` | Under active review.          |
| `completed`  | Terminal. Check `outcome`.    |

| `outcome`   | Meaning                                                         |
| ----------- | --------------------------------------------------------------- |
| `approved`  | Approved; we provision the customer and accounts automatically. |
| `rejected`  | Rejected.                                                       |
| `withdrawn` | Withdrawn before a decision.                                    |

<Note>
  Post-submission transitions happen in our compliance systems. Poll the application via [`GET /onboarding-applications/{id}`](#retrieving-an-application) for updates.
</Note>

## Retrieving an application

`GET /onboarding-applications/{id}` with the `read` scope. Use it to poll an application after submission; reads have no side effects and are safe to call repeatedly.

```bash theme={"theme":"catppuccin-mocha"}
curl https://api.engine.usesophic.com/onboarding-applications/onba_m4k7r9s2 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

| Path parameter | Required | Notes                                                                                   |
| -------------- | -------- | --------------------------------------------------------------------------------------- |
| `id`           | yes      | The application ID returned by `POST /onboarding-applications`. Format `onba_<suffix>`. |

A successful request returns `200 OK` with the same shape as the submission response. `status` and `outcome` reflect the current lifecycle; `application` is the payload exactly as persisted at submission time; we don't re-derive it from the person's current claims or re-run validation.

```json theme={"theme":"catppuccin-mocha"}
{
  "id": "onba_m4k7r9s2",
  "created_at": "2026-04-18T09:30:00Z",
  "modified_at": "2026-04-18T10:15:00Z",
  "customer_type": "individual",
  "status": "processing",
  "outcome": null,
  "application": {
    "customer_type": "individual",
    "authorities": [
      {"person": "per_ada", "authority_type": "owner"}
    ],
    "consents": [
      {"person": "per_ada", "consent_type": "terms_of_service", "legal_document_version": "legal_doc_ver_tos_v3", "consented_at": "2026-04-18T09:30:00Z"}
    ],
    "evidence": [
      {"person": "per_ada", "evidence_type": "identity_document", "document_type": "passport", "file": "fil_passport"}
    ]
  }
}
```

Unknown or invisible IDs return `404 not_found`:

```json theme={"theme":"catppuccin-mocha"}
{
  "code": "not_found",
  "detail": "Not Found"
}
```

## Errors

Most integration failures are `400 invalid_request` with a precise `detail` pointing at the person, claim, consent, or evidence at fault. See [errors](/docs/onboarding/errors) for the catalogue.
