---
updatedAt: 2026-09-11T16:10:26.000Z
---

Fetch the complete documentation index at: https://developer.drivewealth.com/apis/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Onboarding a Trust Entity

## Overview

A **Trust Entity** is a trust (including an Australian Self-Managed Super Fund) opening a DriveWealth<br />trading account. This is `type: TRUST` on the Entities API. See <Anchor target="_blank" href="https://developer.drivewealth.com/apis/v1.0-ticker_add_entity_guides/docs/entity">Creating an entity</Anchor> if you're not sure this is the one you need — a corporation, LLC, or partnership uses <Anchor target="_blank" href="https://developer.drivewealth.com/apis/v1.0-ticker_add_entity_guides/docs/onboarding-a-business-entity">Onboarding a Business Entity</Anchor> instead.

## Create the entity

```bash
curl -X POST https://bo-api.drivewealth.io/back-office/entities \
  -H "Authorization: Bearer $DW_BEARER_TOKEN" \
  -H "dw-client-app-key: $DW_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ibID": "80f9b672-120d-4b73-9cc9-42fb3262c4b9",
    "type": "TRUST",
    "attributes": {
      "name": "Wise Family Trust",
      "incorporationCountry": "USA",
      "incorporationProvince": "NJ",
      "incorporationDate": "2014-09-29"
    },
    "identifications": {
      "ssn": "891234589"
    },
    "contact": {
      "addresses": {
        "primary": {
          "street1": "15 Exchange Place",
          "street2": "Unit 1100",
          "city": "Jersey City",
          "province": "NJ",
          "zipcode": "07302",
          "country": "USA"
        }
      },
      "phone": "+12025550149",
      "email": "trustee@example.com"
    },
    "disclosures": {
      "termsOfUse": {
        "agreed": true,
        "signedBy": "Justin Case",
        "signedWhen": "2026-09-08T19:00:00Z"
      },
      "customerAgreement": {
        "agreed": true,
        "signedBy": "Justin Case",
        "signedWhen": "2026-09-08T19:00:00Z"
      },
      "rule14b": {
        "agreed": true,
        "signedBy": "Justin Case",
        "signedWhen": "2026-09-08T19:00:00Z"
      }
    }
  }'
```

**Required top-level:** `ibID`, `type`, `attributes` (needs `name` + `incorporationCountry`),
`identifications`, `contact` (needs `addresses`, `phone`, `email`).

`subType`**&#x20;is optional for&#x20;**`TRUST` — the only valid value is `SMSF` (Australian Self-Managed Super
Fund); omit it entirely for a standard trust.

`identifications.ssn` here is documented as "Social Security Number of the grantor for trust entity"
(9 digits, no hyphens) — the trust's own tax identification, distinct from any grantor `User` you create in
step 3.

> `disclosures`**&#x20;is optional per the schema, but required in practice before you can open the trust
> Account.** Skipping it here (or via a later `PATCH /entities/{entityId}`) makes step 5's `POST /accounts` fail with `U040`: `"Missing/Incomplete documents: [Document: DISCLOSURES - Missing fields: [ termsOfUse rule14b customerAgreement signedBy ] ]"`. Send `termsOfUse`, `customerAgreement`, and `rule14b` up front — each needs `agreed`, `signedBy`, and `signedWhen`.

### Response — 201

```json
{
  "id": "ded54b83-f6e4-4086-a745-f5366f376a57",
  "ibID": "80f9b672-120d-4b73-9cc9-42fb3262c4b9",
  "wlpID": "DW",
  "type": "TRUST",
  "attributes": {
    "name": "Wise Family Trust",
    "incorporationCountry": "USA",
    "incorporationProvince": "NJ",
    "incorporationDate": "2014-09-29"
  },
  "identifications": {
    "SSN": "****4589"
  },
  "contact": {
    "addresses": {
      "PRIMARY": {
        "street1": "15 Exchange Place",
        "street2": "Unit 1100",
        "city": "Jersey City",
        "province": "NJ",
        "zipcode": "07302",
        "country": "USA"
      }
    },
    "phone": "+12025550149",
    "email": "trustee@example.com"
  },
  "disclosures": {
    "termsOfUse": {
      "agreed": true,
      "signedBy": "Justin Case",
      "signedWhen": "2026-09-08T19:00:00Z"
    },
    "customerAgreement": {
      "agreed": true,
      "signedBy": "Justin Case",
      "signedWhen": "2026-09-08T19:00:00Z"
    },
    "rule14b": {
      "agreed": true,
      "signedBy": "Justin Case",
      "signedWhen": "2026-09-08T19:00:00Z"
    }
  },
  "kyb": {
    "status": "KYB_APPROVED",
    "statusWhen": "2026-09-08T19:51:27.096759860Z",
    "statusBy": "SYSTEM",
    "reasons": [
      {
        "code": "D201",
        "description": "KYB has been auto-approved by the system for a no-KYB partner."
      }
    ]
  },
  "tax": {
    "status": "TAX_READY",
    "message": "Entity is ready for tax processing"
  },
  "status": "PENDING",
  "createdAt": "2026-09-08T19:51:27.097114180Z",
  "updatedAt": "2026-09-08T19:51:27.097114180Z",
  "createdBy": "7c0e3e79-59ae-475d-bf76-85ea82b363af",
  "updatedBy": "7c0e3e79-59ae-475d-bf76-85ea82b363af",
  "taxData": {
    "fatcaData": {
      "applicable": false,
      "applicableFrom": "2026-09-08T19:51:27.096792801Z",
      "setBy": "SYSTEM"
    },
    "data": {}
  }
}
```

> `SSN`**&#x20;comes back masked** (`****4589`), same convention as the Users API's `IDENTIFICATION_INFO`, and `identifications`/address-type keys come back uppercase (`SSN`, `PRIMARY`) even though the request used lowercase. `disclosures` echoes back exactly what was sent.
>
> **Who performs KYB depends on partner configuration, same as KYC.** This entity's `kyb.status` came back `KYB_APPROVED` immediately — `reasons[0].description` says why: `"KYB has been auto-approved by the system for a no-KYB partner."` A do-KYB partner would instead see `KYB_NOT_READY`/`KYB_PROCESSING_*` progress through the states in <Anchor target="_blank" href="#6-check-kyb-status">Check KYB status</Anchor>. Either way, **the coarse&#x20;**`status`**&#x20;field stayed&#x20;**`PENDING` even with `kyb.status: KYB_APPROVED` — don't assume the two move together, and don't gate on `status` when `kyb.status` is the one that reflects reality.

## Upload trust documents

A Certification of Trust (or a "short form" Trust Deed/Memorandum of Trust) — showing trustee names, the
trust's legal name, the trust agreement date, and jurisdiction — goes through the Physical Documents API,
using `type: TRUST_DOCUMENTS`:

```bash
curl -X POST https://bo-api.drivewealth.io/back-office/documents \
  -H "Authorization: Bearer $DW_BEARER_TOKEN" \
  -H "dw-client-app-key: $DW_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userID": "<the entityID from step 1>",
    "type": "TRUST_DOCUMENTS",
    "document": "data:image/jpeg;base64,<base64-encoded file>"
  }'
```

**Required:** `userID`, `type`, `document` (base64-encoded, data-URI prefixed). `side` (`FRONT`/`BACK`) is
optional — most trust documents are single-sided and can omit it.

> `userID`**&#x20;is documented as a User's id, not an entity's** — but `POST /documents` accepts the entity's `id` in this field.

### Response — 200

```json
{
  "id": "cb8c4bfb-14f5-40d6-ab46-41cc384ca428",
  "type": "TRUST_DOCUMENTS",
  "status": {
    "name": "NOT_SUBMITTED",
    "description": "Document has not been submitted for approval."
  },
  "active": true
}
```

`status.name` starts at `NOT_SUBMITTED` right after upload and moves through `PENDING` → `APPROVED` /
`REJECTED` once DriveWealth reviews it — this upload call alone doesn't submit it for review.

## Link trustees, grantors, and beneficiaries

Each individual connected to the trust is created as a normal User (`userType: INDIVIDUAL_TRADER`) with a `DIRECTOR_INFO` document pointing back at the entity via `institutionalID`. A single person can hold more than one role:

```bash
curl -X POST https://bo-api.drivewealth.io/back-office/users \
  -H "Authorization: Bearer $DW_BEARER_TOKEN" \
  -H "dw-client-app-key: $DW_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userType": "INDIVIDUAL_TRADER",
    "username": "justin.trustee08",
    "password": "my#1Account",
    "documents": [
      {
        "type": "BASIC_INFO",
        "data": {
          "firstName": "Justin",
          "lastName": "Case",
          "country": "USA",
          "phone": "12025550149",
          "emailAddress": "justin.case@example.com"
        }
      },
      {
        "type": "IDENTIFICATION_INFO",
        "data": {
          "value": "402724321",
          "type": "SSN",
          "citizenship": "USA"
        }
      },
      {
        "type": "PERSONAL_INFO",
        "data": {
          "birthDay": 14,
          "birthMonth": 6,
          "birthYear": 1965,
          "politicallyExposedNames": "NULL"
        }
      },
      {
        "type": "ADDRESS_INFO",
        "data": {
          "street1": "15 Exchange Place",
          "city": "Jersey City",
          "province": "NJ",
          "postalCode": "07302",
          "country": "USA"
        }
      },
      {
        "type": "DIRECTOR_INFO",
        "data": {
          "directorList": [
            {
              "institutionalID": "<the entity's id from step 1>",
              "title": "Trustee",
              "controlContact": true,
              "roles": ["TRUSTEE", "GRANTOR", "BENEFICIARY"]
            }
          ]
        }
      }
    ]
  }'
```

### Response — 200

```json
{
  "id": "bccfc3f3-9851-4bf9-99e3-861f98bd834e",
  "username": "justin.trustee08",
  "userType": {
    "name": "INDIVIDUAL_TRADER",
    "description": "Individual Trader"
  },
  "status": {
    "name": "APPROVED",
    "description": "User approved."
  },
  "parentIB": {
    "id": "80f9b672-120d-4b73-9cc9-42fb3262c4b9",
    "name": "DriveWealth"
  },
  "documents": [
    {
      "type": "ADDRESS_INFO",
      "data": {
        "street1": "15 Exchange Place",
        "city": "Jersey City",
        "province": "NJ",
        "postalCode": "07302",
        "country": "USA"
      },
      "description": "Physical address information"
    },
    {
      "type": "BASIC_INFO",
      "data": {
        "firstName": "Justin",
        "lastName": "Case",
        "displayName": "JCase",
        "emailAddress": "justin.case@example.com",
        "phone": "12025550149",
        "country": "USA",
        "language": "en_US"
      },
      "description": "Name, email, phone, etc."
    },
    {
      "type": "DIRECTOR_INFO",
      "data": {
        "directorList": [
          {
            "title": "Trustee",
            "controlContact": true,
            "institutionalID": "ded54b83-f6e4-4086-a745-f5366f376a57",
            "roles": ["TRUSTEE", "GRANTOR", "BENEFICIARY"]
          }
        ]
      },
      "description": "Director specific information for a user"
    },
    {
      "type": "IDENTIFICATION_INFO",
      "data": {
        "value": "****4321",
        "type": "SSN",
        "citizenship": "USA",
        "description": "Social Security Number"
      },
      "description": "ID Number and citizenship"
    },
    {
      "type": "PERSONAL_INFO",
      "data": {
        "birthdate": "1965-06-14",
        "politicallyExposedNames": "NULL"
      },
      "description": "Birth date, gender, marital status, etc."
    },
    {
      "type": "TAX_INFO",
      "data": {
        "usTaxpayer": true,
        "taxTreatyWithUS": false
      },
      "description": "Tax Information"
    }
  ],
  "wlpID": "DW",
  "referralCode": "748259",
  "createdWhen": "2026-09-08T19:55:52.922Z",
  "updatedWhen": "2026-09-08T19:55:52.922Z"
}
```

> Same no-KYC-partner pattern as the other User guides: `status: APPROVED` immediately, `TAX_INFO` is auto-added, `birthDay`/`birthMonth`/`birthYear` collapse into a single `birthdate`, `SSN` comes back masked (`****4321`), and a `displayName`/`language` get auto-populated on `BASIC_INFO`. The `DIRECTOR_INFO` document echoes back the `institutionalID` and all three roles you sent, matching the entity's `id` from step 1.

| Role          | Meaning                                                                |
| ------------- | ---------------------------------------------------------------------- |
| `TRUSTEE`     | Legally responsible for managing the assets in the account             |
| `GRANTOR`     | The individual who creates and funds the trust                         |
| `BENEFICIARY` | Benefits from the managed assets, without necessarily controlling them |

> **The trust must have at least one linked&#x20;**`BENEFICIARY`**&#x20;before you can open its Account.** Opening the Account (step 5) with only a `TRUSTEE`/`GRANTOR` linked fails.

## Link a bank account for Travel Rule

Opening a `CASH`-funded Account requires an active linked bank account with `bankAccountPurpose:
TRAVEL_RULE` first — skip this and `POST /accounts` fails with `A080`
(`"Account's user is missing an active bank account of purpose TRAVEL_RULE"`). This is a separate API (`LinkedBankAccountsAPI.json`, `POST /bank-accounts`):

```bash
curl -X POST https://bo-api.drivewealth.io/back-office/bank-accounts \
  -H "Authorization: Bearer $DW_BEARER_TOKEN" \
  -H "dw-client-app-key: $DW_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userID": "<the entityID from step 1>",
    "bankAccountNumber": "7442393174",
    "bankRoutingNumber": "110000000",
    "bankAccountNickname": "Trust Checking",
    "bankAccountType": "CHECKING",
    "bankAccountPurpose": "TRAVEL_RULE",
    "bankName": "Bank of America",
    "bankAddress": "222 Broadway, New York City, NY, 10038",
    "bankCountry": "USA",
    "beneficiaryDetails": {
      "accountHolderName": "Wise Family Trust",
      "accountHolderAddress": "15 Exchange Place, Unit 1100, Jersey City, NJ, 07302",
      "accountHolderCountry": "USA"
    }
  }'
```

> `bankName`**,&#x20;**`bankAddress`**,&#x20;**`bankCountry`**, and&#x20;**`beneficiaryDetails`**&#x20;are required in**<br />**practice** — omitting any one fails with `E032` naming that exact field.
>
> `userID`**&#x20;here is the entity's&#x20;**`id`**&#x20;again**, same pattern as steps 2 and 5.

### Response — 200

```json
{
  "id": "bank_4abd9b75-b398-420d-8b83-b92d4ecd263f",
  "userDetails": {
    "userID": "ded54b83-f6e4-4086-a745-f5366f376a57",
    "username": "ded54b83-f6e4-4086-a745-f5366f376a57",
    "firstName": "Wise Family Trust",
    "email": "trustee@example.com",
    "parentIB": {
      "id": "80f9b672-120d-4b73-9cc9-42fb3262c4b9",
      "name": "DriveWealth"
    },
    "wlpID": "DW"
  },
  "bankAccountDetails": {
    "bankAccountNickname": "Trust Checking",
    "bankAccountNumber": "****3174",
    "bankRoutingNumber": "110000000",
    "bankAccountType": "CHECKING",
    "bankName": "Bank of America",
    "bankAddress": {
      "addressLine1": "222 Broadway, New York City, NY, 10038",
      "country": "USA"
    }
  },
  "default": false,
  "status": "ACTIVE",
  "bankAccountPurpose": "TRAVEL_RULE",
  "beneficiaryDetails": {
    "accountHolderName": "Wise Family Trust",
    "accountHolderAddress": "15 Exchange Place, Unit 1100, Jersey City, NJ, 07302",
    "accountHolderCountry": "USA"
  },
  "created": "2026-09-08T19:56:55.249Z",
  "updated": "2026-09-08T19:56:55.249Z"
}
```

`bankAccountNumber` comes back masked (`****3174`), and `status: ACTIVE` confirms the account is ready to satisfy the Travel Rule requirement in the next step.

## Open the trust Account

```bash
curl -X POST https://bo-api.drivewealth.io/back-office/accounts \
  -H "Authorization: Bearer $DW_BEARER_TOKEN" \
  -H "dw-client-app-key: $DW_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userID": "<the entity'"'"'s id from step 1>",
    "accountType": "LIVE",
    "accountManagementType": "TRUST_SELF",
    "tradingType": "CASH",
    "accountFundingType": "CASH"
  }'
```

> `userID`**&#x20;here is the entity's&#x20;**`id`**, not an individual's.** Confirm this against current Accounts API
> behavior before relying on it in production.
>
> `accountFundingType`**&#x20;is required for partners that support both wallet and bulk funding types**.

`accountManagementType` for a trust entity is `TRUST_SELF`, `TRUST_ADVISORY`, or `TRUST_RIA_MANAGED` —
**not** the `BUSINESS_*` values, which are for corporations/LLCs/partnerships.

### Response — 200

```json
{
  "id": "ded54b83-f6e4-4086-a745-f5366f376a57.1788897462923",
  "accountNo": "DWRE002541",
  "accountType": {
    "name": "LIVE",
    "description": "Live Account"
  },
  "accountMgmtType": {
    "name": "TRUST_SELF",
    "description": "Self Directed Trust Account"
  },
  "accountHolderType": {
    "name": "I",
    "description": "An account that does not meet FINRA Rule 4215(c) or a proprietary trading account"
  },
  "accountFundingType": "CASH",
  "status": {
    "name": "OPEN",
    "description": "Open"
  },
  "tradingType": {
    "name": "CASH",
    "description": "Cash account"
  },
  "leverage": 1.00,
  "nickname": "Wise Family Trust's Self Directed Trust Account",
  "parentIB": {
    "id": "80f9b672-120d-4b73-9cc9-42fb3262c4b9",
    "name": "DriveWealth"
  },
  "taxProfile": {
    "taxStatusCode": "W-9",
    "taxRecipientCode": "TRUST"
  },
  "currencyID": "USD",
  "commissionID": "b3e985dd-9679-63dc-5dd5-9bd7982efecd",
  "beneficiaries": false,
  "userID": "ded54b83-f6e4-4086-a745-f5366f376a57",
  "restricted": false,
  "gfvRestricted": false,
  "goodFaithViolations": 0,
  "pdtRestricted": false,
  "patternDayTrader": false,
  "patternDayTrades": 0,
  "freeTradeBalance": 0,
  "gfvPdtExempt": false,
  "buyingPowerOverride": false,
  "bod": {},
  "sweepInd": true,
  "interestFree": false,
  "openedWhen": "2026-09-08T19:57:42Z",
  "ignoreMarketHoursForTest": false,
  "flaggedForACATS": false,
  "regType": "CUST"
}
```

## Check KYB status

There's no separate `kyb-status` endpoint like the Users API's `kyc-status` — `GET /entities/{entityId}`
carries everything, including a rolled-up `kycStatus` per linked director:

```bash
curl -X GET https://bo-api.drivewealth.io/back-office/entities/<entity id> \
  -H "Authorization: Bearer $DW_BEARER_TOKEN" \
  -H "dw-client-app-key: $DW_APP_KEY"
```

### Response — 200

*Pending — validate this call in sandbox and paste the actual response here.*

The response's `directors[]` array includes each linked individual's `kycStatus` directly — you don't need
a separate `GET /users/{userID}/kyc-status` call per director just to see where they stand.

`status` (coarse: `PENDING`/`APPROVED`/`REJECTED`/`REVOKED`/`CLOSED`) and `kyb.status` (granular) are the
same two-tier pattern as User KYC — **and the two don't move together.** A captured no-KYB-partner response
came back `kyb.status: KYB_APPROVED` with `kyb.reasons[0]` explaining `"KYB has been auto-approved by the
system for a no-KYB partner"`, while the entity's own `status` stayed `PENDING`. Don't gate on `status`;
`kyb.status` (plus `kyb.reasons[]` when present, each a `{code, description}` pair) is the one that reflects
reality. Whether you see this immediate approval or the full `KYB_NOT_READY` → … progression below depends
on whether your partner is configured do-KYB or no-KYB/verify-KYB — same distinction as User KYC, confirm
with DriveWealth which model you're on.

| `kyb.status`               | Meaning                                                                           |
| -------------------------- | --------------------------------------------------------------------------------- |
| `KYB_NOT_READY`            | Entity hasn't submitted all required data/documents yet                           |
| `KYB_READY`                | All required info submitted, queued for processing                                |
| `KYB_PROCESSING_DIRECTORS` | KYC in progress for the linked directors                                          |
| `KYB_PROCESSING_ENTITY`    | Director KYC cleared; entity-level verification in progress                       |
| `KYB_MANUAL_REVIEW`        | Escalated — can take up to a week per DriveWealth's guidance                      |
| `KYB_DOC_REQUIRED`         | A supporting document is missing                                                  |
| `KYB_INFO_REQUIRED`        | Submitted entity data needs correction                                            |
| `KYB_APPROVED`             | Terminal — cleared                                                                |
| `KYB_DENIED`               | Terminal — rejected; any Account already opened moves to a frozen `accountStatus` |

DriveWealth's own KYB documentation shows a `notes` array (e.g. `["Need more doc"]`) alongside `reasons[]`
on the `kyb` object — `EntityKybResponseModel` doesn't define it, so treat it as present-but-undocumented
rather than something to build strict parsing around.

Subscribe to `entity.created`/`entity.updated` on your SQS queue rather than polling this endpoint —<br />`entity.updated` carries `previous`/`current` KYB state so you can see exactly what changed.

## Requirements vary by entity origin

* **Foreign (non-US) trusts** complete a W-8 form via a DriveWealth-generated ComplyExchange URL instead of the standard US flow.
* **SMSF (**`subType: SMSF`**)** is an Australian retirement-fund structure — confirm with DriveWealth which
  additional fields or documents it requires beyond the standard trust flow before assuming this guide's
  US-trust example covers it.

## What's next

Once the entity clears KYB and its Account is open, funding and trading follow the same Accounts/Deposits
flows as an individual Account.

<br />