Onboarding SDK + Fund SDK

Instantly fund an account anytime, anywhere - end to end integration guide for the Account Funding product

See core product page here

Setup

In this guide, the Platform is setup to use the zerohash Onboarding SDK (KYC as a Service) with the zerohash Account Funding SDK. Both SDKs are hosted on web-sdk.zerohash.com

Flow

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 the Platform is a CFD brokerage offering stablecoins as a funding mechanism. Summary of all involved participants:

  • Platform (participant_code: PLAT01)
  • End Customer (participant_code: CUST01)

Webhook configuration

Platforms should be listening to the following webhooks:

Onboarding

Retrieve Account Funding JWT token

In order to successfully invoke the Access Token, you'll need to supply a participant_code for the End Customer (see endpoint API Reference here). Please note that this customer must be in an approved status for this call to succeed. Please note: the correct permission to pass here is participant-profile.

The Customer will then be prompted to fill out their onboarding details.

Receive Webhook event

Once the Customer has successfully completed the onboarding flow, the Platform will receive a series of webhooks, most typically like:

{  
  "participant_code": "CUST01",  
  "participant_status": "submitted",  
  "timestamp": 1670958435349  
}

Then a few seconds later, the Customer receives approval:

{  
  "participant_code": "CUST01",  
  "participant_status": "approved",  
  "timestamp": 1670958435375  
}

The participant_code should be used in the next SDK flow:

Initialize Account Funding Flow

Retrieve Account Funding JWT token

In order to successfully invoke the Access Token, you'll need to supply a participant_code for the End Customer (see full instructions here). This customer must be in an approved status for this call to succeed. Please note: the correct permission to pass here is fwc.

You may also include an optional reference_id value when generating the token. This ID will be tied to all future webhook calls and Account Funding events within the GET /fund/transactions response.

Presetting Deposit Amounts
You can preset a deposit amount using the deposit_amount and denominated_currency parameters in the client auth token request. This removes the ability for the user to select a deposit amount during the Fund SDK flow and lands the user on the Review screen after selecting the asset they wish to send.

Note: this feature is only available for use with the Auth + Fund SDK flow when Classic Transfer is NOT enabled. Additionally, this value will not be evaluated against Platform-configured periodic transaction limits or Travel Rule limits. Exceeding these limits may cause a transaction failure.

Invoke the Account Funding SDK

See SDK guide for technical instructions.

Accept T&Cs

The T&Cs landing page is the first screen that provides an introduction to how the Account Funding experience will work. This screen displays the zerohash User Agreement, Privacy Policy, Regulatory Disclosures, and captures explicit consent for the terms of this product.

Select an asset and network

Allow the customer to select an asset and network. zerohash supports all major crypto and stablecoins across 19+ networks:

Transaction pending

After the customer selects the asset and network, they're then given the deposit instructions (rate, fees if applicable, and the deposit address). At this point, the customer should be navigating to their mobile phone or a different tab on their browser to an external wallet (ie, Coinbase, Robinhood, Metamask, Phantom, etc.) and initiating a transfer from there to the address shown on the screenshot above:

Transaction confirmed

After the blockchain transaction is confirmed on-chain, the frontend will automatically transition to a confirmed state. The customer will be shown a receipt with important data points including amount received, status, and fees (if applicable).

Deposit outcomes and webhooks

Platforms should be listening to the following webhooks for deposit outcomes:

ScenarioOutcomeAccount Funding Webhook
Deposit received; Fund Event has completed successfully.Funds immediately converted to fiat and creditedAccount Funding webhook with status_reason_code = DEPOSIT_PROCESSED

Deposit/Withdraw webhook with state = completed
Large deposit received; Pending settlement. Stablecoin deposits over $500k* can be subject to longer processing times to complete conversion to fiat.Funds temporarily held while processing is completed

Account Funding webhook with status_reason_code = DEPOSIT_PENDING_SETTLEMENT

Deposit/Withdraw webhook with
state = pending_approval

Deposit received; Above maximum configured amount
OR
below minimum configured amount
Funds are not converted and are credited to the sender's participant account. The sender can recover funds from the zerohash branded secondary portal.Account Funding webhook with status_reason_code = AMOUNT_ABOVE_MAXIMUM
OR
status_reason_code = AMOUNT_BELOW_MINIMUM

Deposit/Withdraw webhook with state = completed
Deposit received; Asset not supportedFunds are not converted and are credited to the sender's participant account. The sender can recover funds from the zerohash branded secondary portal.Account Funding webhook with status_reason_code = ASSET_NOT_SUPPORTED

Deposit/Withdraw webhook with state = completed
Deposit received; Stablecoin depeggedFunds are not converted and are credited to the sender's participant account. The sender can recover funds from the zerohash branded secondary portal.Account Funding webhook with status_reason_code = ASSET_DEPEGGED

Deposit/Withdraw webhook with state = completed
Deposit received; Platform not enabled
OR
End Customer not approved
Funds are held and not creditedAccount Funding webhook with status_reason_code = PLATFORM_NOT_ENABLED
OR
status_reason_code = QUARANTINED_DEPOSIT

Deposit/Withdraw webhook with state = quarantined

*To enable large stablecoin deposits over $500k, contact your zerohash Relationship Manager.

Query Account Funding transactions

It may be helpful (or likely required) to display crypto or stablecoin deposits in the Transaction History (or like page) on your application. You can use the GET /fund/transactions endpoint to query all completed Account Funding events. View the code recipe for additional assistance.

Customer receives email

zerohash is required to ensure that each Customer receives an email receipt for all transactions. zerohash will handle this and send an email in the following scenarios (same scenarios as webhooks):

  • Success
  • Failure - Platform not enabled
  • Failure - Customer not approved
  • Failure - Deposit above maximum
  • Failure - Deposit below minimum
  • Failure - Asset not supported
  • Failure - Stablecoin depegged

Deposit returns

🚧

IMPORTANT: You cannot rely on the deposit’s source address as the return destination. Blockchain transactions are not inherently bidirectional, and returning funds to the sender address may result in loss of funds or failed deliveries.

Some Platforms may choose to pair their zerohash integration with their own transaction monitoring tools. In situations where zerohash accepts a deposit, but the Platform’s monitoring logic flags and rejects it, the Platform may opt to return the deposit by using the POST /withdrawals/requests endpoint.

The required flow is to always request and confirm a return address directly from the customer before initiating the return.

Please speak to a zerohash sales engineer for guidance if interested in this flow.

Reconciliation

If you're using this product in tandem with our Buy/Sell product, see Account Funding + Buy/Sell Reconciliation.

Platform settlement

zerohash will, one time per day, send a fiat settlement wire to the Platform where the amount represents the sum of all converted deposits from the prior trading session. Here is the settlement schedule:

SessionStartEndExpected Settlement Time*
MondayMonday 9:00a ESTTuesday 8:59:59a ESTTuesday EOD
TuesdayTuesday 9:00a ESTWednesday 8:59:59a ESTWednesday EOD
WednesdayWednesday 9:00a ESTThursday 8:59:59a ESTThursday EOD
ThursdayThursday 9:00a ESTFriday 8:59:59a ESTFriday EOD
FridayFriday 9:00a ESTMonday 8:59:59a ESTMonday EOD

During US holidays, Platforms should expect their settlements to arrive by EOD on the next business day. For example, for the August 30th 2024 session, the settlement will arrive by Tuesday EOD (because Monday was Labor Day)

Tracking the settlement amount

The recommended way to track the impending settlement amount is to query the GET /accounts/account_id endpoint. In order to retrieve the correct account_id to use in that call, use the following query parameters when hitting the GET /accounts endpoint:

  • participant_code: [your platform code]
  • account_group: [your platform code]
  • account_label: general
  • account_type: available
  • asset: [fiat currency code, typically "USD"]

Use the account_id in the response to query associated accounts. Example response:

{
    "message": [
        {
            "asset": "USD"
            "account_owner": "PLAT01",
            "account_type": "available",
            "account_group": "PLAT01",
            "account_label": "general",
            "balance": "25000",
            "account_id": "af063ca6-836f-4677-8ebf-edbe1d049938",
            "last_update": 1727214271011
        }
    ]
}

Note that the balance will refresh to 0 each time zerohash initiates the daily settlement wire.

Retroactively querying settlements in the past

Platform settlements are technically a withdrawal. In order to query settlements from the past, use the GET /withdrawals/requests endpoint. The response will show all withdrawals made from the Platform's account.

In order to filter for withdrawals made from the Platform account only, query GET /withdrawals/requests using the participant_code query parameter, where the value is the Platform's platform code:

Example GET /withdrawals/requests?participant_code=PLAT01 response:

{
    "message": [
        {
            "id": "152b8276-0585-45ec-bf62-85e134b3ff43",
            "withdrawal_account_id": 346030,
            "participant_code": "PLAT01",
            "account_group": "PLAT01",
            "account_label": null,
            "requestor_participant_code": "PLAT01",
            "asset": "USDC.SOL",
            "requested_amount": "25000",
            "settled_amount": "25000",
            "gas_price": null,
            "status": "SETTLED",
            "on_chain_status": "",
            "client_withdrawal_request_id": null,
            "requested_timestamp": 1727921516403,
            "transaction_id": "HND48J83HGR55LLP",
            "input_data": null,
            "fee_amount": "",
            "quoted_fee_amount": null,
            "quoted_fee_notional": null,
            "trade_id": null,
            "quoted_fee_asset": null,
            "withdrawal_fee": "",
            "parent_link_id": null,
            "parent_link_id_source": null
        }
    ]
}

Did this page help you?