Multiple Tenant Accounts
Power Multiple Tenant Accounts - Integration Guide
Introduction
This guide provides a comprehensive overview of integrating joint accounts within the Zero Hash platform, aligning with the latest API specifications and account structures.
Use Cases
- Early Wealth Building via Crypto Gifting: Parents or guardians can gift Bitcoin or other cryptocurrencies to a child at birth. Crypto assets held in a UTMA account can appreciate over time and be sold when the child reaches the age of majority. The proceeds can be used for major life expenses such as college tuition, a vehicle purchase, or a down payment on a first home.
- Estate Planning or Wealth Management: Individuals can open a Trust account to hold and manage investments on behalf of beneficiaries. Cryptocurrencies placed in a revocable or irrevocable trust can grow over time while remaining protected under the terms of the trust.
- Married Couples: Spouses may open a joint brokerage account—such as a Joint Tenants with Right of Survivorship (JTWROS) or Community Property account—to manage shared investments. This allows both partners equal access to the account and ensures that, upon the death of one spouse, the surviving spouse automatically inherits the assets without going through probate.
Account Types
Zero Hash supports various account types, each with specific tenant configurations and authorization models:
Account Types | Definition |
---|---|
Uniform Transfers to Minors Act (UTMA) | Custodial accounts for minors, managed by a custodian until the minor reaches the age of majority |
Trust | Managed by a trustee for the benefit of beneficiaries |
Joint Tenants in Common (JTIC) | Multiple individuals with potentially unequal ownership; upon death, the deceased's share passes to their estate |
Joint Tenants with Right of Survivorship (JTWROS) | Equal ownership among individuals; upon death, the deceased's share automatically transfers to surviving tenants |
Community Property | Assets held jointly by a married couple, each owning a 50% interes |
Each account type has predefined tenant roles and authorization levels, ensuring compliance and proper access control.
Tenant Types
Joint accounts have multiple tenants with associated authorizations, as described below:
Tenant Types | Definition |
---|---|
Individual | A natural person who is granted authorizations to access the account |
UTMA Beneficiary | The minor child for whom the custodial account is helf under the Uniform Transfers to Minors Act. The beneficiary is the legal owner of the funds, but has no control over the account until reaching the age of majority (18 or 21) |
UTMA Custodian | The legally authorized adult who manages a UTMA account on behalf of the minor beneficiary |
Trustee | The person or institution legally responsible for managing the trust’s assets |
Trust Beneficiary | The individual or entity entitled to receive distributions or benefits from the Trust |
Tenant Designations
Each multiple tenant account must have one Primary Participant, and at least one Secondary Participant.
Tenant Designations | Definition |
---|---|
Primary | The primary participant associated with the account creation |
Secondary | The secondary participant(s) associated with the account |
Tenant Authorizations
Tenant authorizations define the level of access and control over an account. These authorizations are assigned based on the account type and tenant configuration.
Authorization | Permissions |
---|---|
Full Trading | The ability to withdrawal funds, trade, and access statements & receipts |
Limited Trading | The ability to trade and access statements & receipts. Cannot withdrawal funds |
View Only | The ability to access statements & receipts. Cannot withdrawal funds or trade |
Authorization Matrix
The below matrix represents the default authorizations for each Account Type and Tenant Type. Tenant authorizations can be updated after account creation.
Steps for Setting Up Multiple Tenant Accounts and Tenants
- Create the primary and secondary participants using
POST /participants/customers/new
- Create an account using
POST /accounts/new
- Assign the primary articipant
participant_code
: the primary participant's participant code - Set account type by
type
: the AccountTypeEnum - Add the additional tenant(s) by
tenants
: the secondary participant(s)' participant codes
- Assign the primary articipant
Example: UTMA Account Purchases Crypto
High Level Flow
- Create a custodian
- Query the custodian
- Create the minor
- Query the minor
- Establish the UTMA account
- Query the UTMA account
- Get a quote
- Execute a quote
- Query the trade
- View the UTMA account balance
Initial Setup
The Platform will need to onboard its business to the Zero Hash platform. They then need to add additional users, create API keys, and whitelist IP addresses. See instructions here.
1. Create the Custodian
Once API keys are created and approved, the Platform can begin to integrate to the API. For the following examples, we’ll assume the Platform's platform code is PLAT01.
The Platform submits the Custodian via POST /participants/customers/new:
{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone_number": "+12345834789",
"date_of_birth": "1985-09-02",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"zip": "12345",
"jurisdiction_code": "US-IL",
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501282,
"signed_agreements": [{
"type": "user_agreement",
"region": "us",
"signed_timestamp": 1603378501286
}],
}
Note: The Custodian will be agreeing to the Zero Hash User Agreement and associated terms. The platform indicates to Zero Hash that they accepted the terms by sending a value in the signed_agreement
object as shown above.
type
: the type of user agreement being signed. For Remittances, the Sender is signing the standard user agreement, so a value ofuser_agreement
is expected.signed_timestamp
: is the timestamp that the Sender accepted the terms and conditions.region
: represents the Zero Hash entity that the Sender is entering into a contract with. The only acceptable value right now isUS
.
POST /participants/customers/new response:
{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"country": "United States",
"state": "IL",
"jurisdiction_code": "US-IL",
"city": "Chicago",
"zip": "12345",
"date_of_birth": "1985-09-02",
"id_number_type": "unknown",
"id_number": "",
"non_us_other_type": "",
"id_issuing_authority": "",
"signed_timestamp": -62135596800000,
"risk_rating": "",
"metadata": {},
"platform_code": "PLAT01",
"participant_code": "CUSTD1", <-- Custodian Participant Code
"tax_id": "",
"citizenship": "",
"citizenship_code": "",
"kyc": "unknown",
"kyc_timestamp": null,
"onboarded_location": "US-IL",
"sanction_screening": "pass",
"sanction_screening_timestamp": null,
"liveness_check": "unknown",
"phone_number": "+12345834789",
"employment_status": "unknown",
"industry": "unknown",
"source_of_funds": "unknown",
"signed_agreements": [{
"region": "us",
"signed_timestamp": 1603378501,
"type": "user_agreement"
}]
}
Note: The response contains a participant_code
for the Custodian. This uniquely identifies the Custodian indefinitely and should be use in subsequent API calls where applicable. We’ll use CUSTD1 as the participant_code
throughout the examples.
3. Create the Minor
The Platform submits the Custodian via POST /participants/customers/minor
:
{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone_number": "+12345834789",
"date_of_birth": "1985-09-02",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"zip": "12345",
"jurisdiction_code": "US-IL",
"partial": true,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501282
}],
}
Note: The Minor will not need to agree to Zero Hash User Agreement and associated terms, but they are subject to KYC.
POST /participants/customers/minor response:
{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone_number": "+12345834789",
"date_of_birth": "1985-09-02",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"zip": "12345",
"jurisdiction_code": "US-IL",
"partial": true,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501282,
"platform_code": "PLAT01",
"participant_code": "MINOR1", <-- Minor Participant Code
}
Note: The response contains a participant_code
for the Minor. This uniquely identifies the Minor indefinitely and should be use in subsequent API calls where applicable. We’ll use MINOR1 as the participant_code
throughout the examples.
5. Create the UTMA account
The Platform will create the UTMA account via a POST /accounts/new
call:
{
"message": {
"type": "utma",
"participant_code": "MINOR1",
"tenants":"CUSTD1"
"prefunded": true,
"account_label": "general",
"tier": "pro"
}
}
Example response:
{
"type": "utma",
"participant_code": "MINOR1",
"tenants":"CUSTD1"
"prefunded": true,
"account_label": "general",
"tier": "pro",
"multi_tenant_account_id": "d72d68f3-55ae-4c26-aebc-4298c56f10f1"
}
When the UTMA account is created and the minor is associated as the primary
participant_code
, the minor will automatically inherit the UTMA Beneficiary authorizations, which is View Only. The Custodian will automatically inherit the UTMA Custodian authorizations, which is Full Trading
7. Get a Quote
The UTMA account is ready fro trading. Start by getting a quote via POST /liquidity/rfq using the Custodian's participant code
{
"participant_code" :'CUSTD1',
"multi_tenant_account_id": "d72d68f3-55ae-4c26-aebc-4298c56f10f1",
"side": "buy",
"underlying": "BTC",
"quoted_currency": "USD",
"total": 1000
}
Example response:
{
"message": {
"request_id": "d72d68f3-55ae-4c26-aebc-4298c56f10f1",
"participant_code": "PLAT01",
"multi_tenant_account_id": "d72d68f3-55ae-4c26-aebc-4298c56f10f1",
"quoted_currency": "USD",
"side": "buy",
"quantity": "0.0091",
"price": "109776",
"quote_id": "c2efaa66-a06f-40e7-8da4-35f525c80847",
"expire_ts": 1714527280072,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "CUSTD1",
"account_group": "PLAT01",
"account_label": "general"
},
"parent_link_id": "",
"parent_link_id_source": 0,
"underlying": "BTC",
"asset_cost_notional": "1000",
"spread_notional": "2",
"spread_bps": "200"
}
}
You can monetize this purchase by assessing a disclosed spread. Contact your Zero Hash rep to make the configuration
8. Execute a Quote
To execute a quote, we need to pass the active quote_id
that was obtained from the POST /liquidity/rfq endpoint, as a parameter into the POST /liquidity/execute endpoint:
{
"quote_id": "c2efaa66-a06f-40e7-8da4-35f525c80847"
}
Example response:
{
"message": {
"request_id": "39b54e0f-6af1-4d79-a7b5-a9cf036794f9",
"quote": {
"request_id": "d72d68f3-55ae-4c26-aebc-4298c56f10f1",
"participant_code": "PLAT01",
"quoted_currency": "USD",
"side": "buy",
"quantity": "0.0091",
"price": "109776",
"quote_id": "c2efaa66-a06f-40e7-8da4-35f525c80847",
"expire_ts": 1714527280072,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "CUSTD1",
"account_group": "PLAT01",
"account_label": "general"
},
"parent_link_id": "",
"parent_link_id_source": 0,
"underlying": "BTC",
"asset_cost_notional": "1000",
"spread_notional": "2",
"spread_bps": "200",
"transaction_timestamp": 1714527260659
},
"trade_id": "041fb0aa-5382-49c3-9a6a-aff473221c8d",
"status": "Completed",
"trade_ids_list": [
"041fb0aa-5382-49c3-9a6a-aff473221c8d"
]
}
}
Note: The .0091 BTC is ledgered to the Minor's account (MINOR1)
9. Query the Trade
The Platform can query trades retroactively via GET /trades or GET /trades/{trade_id}:
10. View the UTMA Account Balance
In order to query current balances, call the GET /accounts endpoint with the following parameters:
participant_code
: MINOR1account_group
: PLAT01account_label
: generalasset
: BTC
Example request: GET /accounts?participant_code=MINOR1&account_group=PLAT01&account_label=general&asset=BTC
Updated 2 days ago