API Workflow

In this example, the platform is configured to have the converted USD be automatically transferred to the platform's account. We'll also assume that this is an investment platform that allows "issuers" to source investments from end customers. Summary of all involved participants:

  • Platform (participant_code: PLAT01)
  • End Customer (participant_code: CUST01)
  • Issuer 1 (participant_code: ISSUR1)

Submit Customer

Example request - POST /participants/customers/new

{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"phone_number": "9545551234",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"state": "IL",
"zip": "12345",
"country": "United States",
"date_of_birth": "1985-09-02",
"citizenship": "United States",
"tax_id": "123456789",
"risk_rating": "low",
"kyc": "pass",
"kyc_timestamp": 1630623005000,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1630623005000,
"idv": "pass",
"liveness_check": "pass",
"signed_timestamp": 1630623005000,
"metadata": {},
"signed_agreements": [
     {
        "type": "fund_auto_convert",
        "region": "us",
        "signed_timestamp": 1712008721000
     }
 ]
}

If you fail to indicate that the end customer has agreed to the fund-specific terms, subsequent /fund API calls will fail.

Get quote - POST /fund/rfq

Example request

{
  "participant_code": "CUST01",
  "fund_asset": "USDC.ETH",
  "account_label": "ISSUR1"
}

Interpretation of this request - the end customer (CUST01) is funding their account using USDC as the asset and ETH as the blockchain network. And to be specific, the end customer is funding the account for the purposes of investing into the issuer 1's company. The platform uses the optional, free-form account_label field for reconciliation and reporting. The entirety of this fund event and related ledger movements will be tied to issuer 1.

Example response - POST /fund/rfq

{  
  "participant_code": "CUST01",  
  "fund_asset": "USDC.ETH",  
  "rate": "1",  
  "quoted_currency":"USD",  
  "expiry_timestamp":"",  
  "request_id":"5155f7c9-95cb-4556-ab89-c178943a7111",  
  "deposit_address": "0x3A45a60c635E6cD616B1C4510404Eba88116050C",  
  "account_label":"ISSUR1"  
}

End customer initiates on-chain deposit

The end customer is presented with an address on the platform's user interface. They use their Metamask wallet, for example, to trigger a withdrawal into the deposit_address for the amount of their choice. Let's say the deposit is for 1,000 USDC.

Deposit received

The transaction has received the proper amount of on-chain confirmations (for USDC in this case, it is 1) and Zero Hash initiates a series of movements:

Accounts for this example:

account_idaccount_owneraccount_groupaccount_labelaccount_typeasset
47a854fa-d0e4-405b-831b-f1a86bbf7988CUST01PLAT01ISSUR1availableUSDC.ETH
52c29f2d-8298-4e8c-84bc-7773960bee12CUST01PLAT01ISSUR1availableUSD
  1. Deposit:Using our account nomenclature, the movement would appear as:
account_owneraccount_groupaccount_labelaccount_typemovement_typeassetchange
CUST01PLAT01ISSUR1availabledepositUSDC.ETH+1,000
  1. Conversion:Automatically, Zero Hash will convert the USD to USDC. This technically creates a trade, which has a movement_type of final_settlement:
account_owneraccount_groupaccount_labelaccount_typemovement_typeassetchange
CUST01PLAT01ISSUR1availablefinal_settlementUSDC.ETH-1,000
CUST01PLAT01ISSUR1availablefinal_settlementUSD+1,000
  1. Transfer:Automatically, Zero Hash will transfer the USD from the end customer account to the platform's:
account_owneraccount_groupaccount_labelaccount_typemovement_typeassetchange
CUST01PLAT01ISSUR1availabletransferUSD-1,000
PLAT01PLAT01ISSUR1availabletransferUSD+1,000

Webhook Event Triggered

The platform can subscribe to a newly built webhook event for this product. It will be triggered at the completion of step 3 above (or step 2 if you are not configured for a subsequent transfer). For more information on webhook messages for Fund, check out webhook documentation.

Platform Queries REST Fund Endpoint

The platform can also retroactively query the GET /fund/transactions endpoint to view details of all particular fund event.

Example response - GET /fund/transactions

{
  "participant_code": "CUST01",
  "fund_asset": "USDC.ETH",
  "rate": "1",
  "quoted_currency":"USD",
  "deposit_address": "0x3A45a60c635E6cD616B1C4510404Eba88116050C",
  "quantity":"1000",
  "notional":"1000",
  "fund_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
  "fund_timestamp": "1550174574",
  "transaction_id": "0x72e399164e29bada83075cd44eacfc40c1656bc35bf38f0cf661bf00dfa3b2b2",
  "account_label":"ISSUR1"
}

Payout - Platform initiates a withdrawal request

The platform can then withdraw the USD using the POST /withdrawals/requests endpoint.

Example Request - POST /withdrawals/requests

{ 
  "withdrawal_account_id":"abc12",
  "participant_code":"PLAT01",
  "amount":"1000",
  "asset":"USD",
  "account_group":"PLAT01"
}

Reconciliation - platform queries REST movements endpoint

The platform can now query GET /movements?parent_link_id=5155f7c9-95cb-4556-ab89-c178943a7111 in order to view all related ledger movements to this fund event.

Example response - GET /movements?parent_link_id=

{
  "message": [
    {
      "movement_timestamp": 1550174570000,
      "account_id": "47a854fa-d0e4-405b-831b-f1a86bbf7988",
      "movement_id": "5d4d962d-dc37-4ddc-b0c5-b8980d1d4421",
      "movement_type": "deposit",
      "transfer_type": null,
      "deposit_reference_id": null,
      "withdrawal_request_id": null,
      "parent_link_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
      "trade_id": null,
      "change": "1000"
    },
    {
      "movement_timestamp": 1550174571000,
      "account_id": "47a854fa-d0e4-405b-831b-f1a86bbf7988",
      "movement_id": "3d4d962d-dc37-4ddc-b0c5-b8980d1d4422",
      "movement_type": "final_settlement",
      "transfer_type": null,
      "deposit_reference_id": null,
      "withdrawal_request_id": null,
      "parent_link_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
      "trade_id": null,
      "change": "-1000"
    },
    {
      "movement_timestamp": 1550174572000,
      "account_id": "52c29f2d-8298-4e8c-84bc-7773960bee12",
      "movement_id": "80818b7b-92ec-4882-a371-a59fb3f8bce0",
      "movement_type": "final_settlement",
      "transfer_type": null,
      "deposit_reference_id": null,
      "withdrawal_request_id": null,
      "parent_link_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
      "trade_id": null,
      "change": "1000"
    },
    {
      "movement_timestamp": 1550174573000,
      "account_id": "52c29f2d-8298-4e8c-84bc-7773960bee12",
      "movement_id": "80818b7b-92ec-4882-a371-a59fb3f8bce0",
      "movement_type": "transfer",
      "transfer_type": null,
      "deposit_reference_id": null,
      "withdrawal_request_id": null,
      "parent_link_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
      "trade_id": null,
    "change": "-1000"
    },
    {
      "movement_timestamp": 1550174574000,
      "account_id": "77c29f2d-8298-4e8c-84bc-7773960bee10",
      "movement_id": "80818b7b-92ec-4882-a371-a59fb3f8bce0",
      "movement_type": "transfer",
      "transfer_type": null,
      "deposit_reference_id": null,
      "withdrawal_request_id": null,
      "parent_link_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
      "trade_id": null,
      "change": "1000"
    }
  ]
}