Real Time Payout Workflow

📘

Australia only

This guide is for platforms operating in Australia.

Overview

This integration guide will run you through how to use Zai to do real-time payouts to your users via the NPP.
To pay your users you only need their BSB and Account Number. Zai will look these details up on the NPP network and if their account is NPP enabled (~90% of accounts are enabled) we'll pay your users in real time. If your user’s bank account is not NPP enabled, we can pay them using our fallback direct entry payouts (funds will land within 3 business days).

Getting Started

Before you can run your NPP workflow, there are a few setup steps that need to be completed so that all of the pieces are available.

Prerequisites
You'll need to capture specific details from your users for you to be able to send funds via the NPP. The requirements for real time payouts can be ​found here​, but there's some flexibility with the specific data depending on your use case and the payment workflow (let’s chat about it).
The setup discussed in this guide makes use of a float to fund your payout. The float will require sufficient funds and periodic top-ups (​see inbound payments below​). Your funding bank account ​must allow PayID payments​, as the float is paid in by a customer reference number and PayID email address.

Before you start creating sub-wallets, ensure your platform is approved for use of stored value accounts and enabled for sub-wallets by contacting Zai's Account Management team. Or you can get in touch with us at [email protected].

Terminology used
The following terminology is used throughout this guide:

  • Platform​ refers to you as a Zai customer, or your website, application, marketplace etc.
  • User​ refers to your customer who has a User record in Zai.
  • Item​ is the mechanism for moving funds between users in the API.
  • Payin​ is money being paid into the Zai ecosystem from a bank account.
  • Payout​ is money being paid out of the Zai ecosystem to a bank account.
  • Float user is a User you may create, if required, to temporarily hold the balance of funds (float) you wish to split and transfer to multiple users' wallet accounts before you perform the payouts.
  • Callbacks are legacy implementations of webhooks.

API steps

Setup steps
We recommend that you create webhooks (callbacks) on the following objects to receive notifications from us of state and status changes.

  • Transactions
  • Items
  • Users
  • Batch Transactions
  • Accounts

To create a callback, you'd call ​POST/callbacks. More information on callbacks can be ​found here​. Also reference our Webhooks guide and best practices. POST /webhooks

Inbound payments (topping up your float - Pre-live only)
The following steps allow you to add funds to a user’s main wallet in our Pre-live environment. In the real world, you'd send us a payment and we'd match it to the wallet. For the purposes of testing, you can add funds to wallets as needed.

  1. Create a ​user​ for your float user.
    POST /users
  2. Get the ​wallet​ account ID for your float user.
    GET /users/:id/wallet_accounts
  3. Get the NPP reference details for the user (this is just so you can add money to the account in Pre-live).
    GET /wallet_accounts/:id/npp_details
  4. (Pre-live only) Fund a user’s wallet with NPP.
    PATCH /testing/wallet_accounts/process_npp_payin
{
  "crn": "Customer reference number - reference from wallet", 
  "payid": "PayID - pay_id from wallet",
  "amount": 10000 // Amount in cents
}
  1. Get the wallet account ID and balance for your float user.
    GET /users/:id/wallet_accounts

Outbound payments (paying your users)
The following steps provide the end-to-end flow that includes how to fund your user’s main wallet account as well as create and fund a sub-wallet.

  1. Create a user for your customer (who you want to pay) if they don’t exist already.
    POST /users
  2. Update the user for your customer if they already exist (if needed).
    PATCH /users/:id
  3. Add a ​bank account​ for your customer (you’ll need the bank account ID in step 10).
    POST /bank_accounts
  4. Set the bank account as the disbursement (or payout) account.
    PATCH /users/:id/disbursement_account
  5. Create an ​Item​ (use Type=2) to move money from your float user to your customer.
    POST /items
  6. Fund the Item with your float user’s wallet (use the ID you got in Step 5 on the Inbound payment steps)
    PATCH /items/:id/make_payment
  7. Check the Callback payload to see how your user’s wallet was funded.
    GET /callbacks/:id/responses
  8. (Sub-wallet account) Create sub-wallet(s) for the user's wallet account.
  9. (Sub-wallet account / Main wallet account) Fund transfers between the main wallet account and its sub-wallet (or between any sub-wallets that belong to the same wallet account). The source and destination accounts must be active and use the same currency.
  10. (Main wallet account) Create a ​withdraw​ request on the wallet to pay to your user’s nominated bank account (use the bank account ID from step 3)
    POST /wallet_accounts/:id/withdraw
    a. (Sub-wallet account) Create a withdraw request on the sub-wallet to pay to your user's nominated bank account (use the bank account ID from step 3). POST /sub_wallets/:id/withdraw
{
	"account_id": abc 123456789,
  "custom_descriptor": "See Design Considerations - Custom Descriptors",
  "amount": 10000 // Amount in cents 
}
  1. Check the Callback payload to see that the payout has been completed.
    GET /callbacks/:id/responses
  2. (Main wallet account) Check the wallet balance of your user to confirm funds have been sent.
    GET /wallet_accounts/:id
    a. (Sub-wallet account) Check the sub-wallet balance of your user to confirm funds have been sent. GET /sub_wallets/:id

Design considerations

User data design
When designing how this workflow will interface with your platform, we suggest storing a map of specific object IDs on your side in order to reduce the number of API calls required throughout the API workflow.

your_customer_idzai_user_idzai_bank_account_idzai_digital_wallet_id or zai_sub_wallet_idzai_user_npp_crn (for payins)
100010015b8f59b6-32c1-44a3-8f5b-b9e2c77bc265fb35b028-76fb-44df-86ac-822dccf1cd7ddcdfdb78-27e7-485d-90c0-11ffbf950d721000023456
10001002efe6f8c1-0a30-484a-b085-9d9d0539dbfc4355de7b-18c2-4892-b800-b7bbb6f0a9b3054cd04e-19f1-4938-908b-8e9e5c212f4d1000098653

Custom descriptors
For real time payouts, you have the option of customising the payment description seen by your customers.
It's an extra parameter on the ​withdraw call​ named ​custom_descriptor​. You can have a string of up to 200 alphanumeric characters. It will then be prefixed by the word "Payment ".
Eg. "Payment {for transaction ID 1234567812345678}".

/wallet_accounts/:id/withdraw?account_id=&amount=&custom_descriptor

Workflow summary
Once you’ve run through the API steps and implemented something like the above in your platform, the sequence of calls to run the payout workflow in production will be reduced.

This flow assumes that you have a callback (webhook) service running, that your user exists and that a bank account has been added, and set as a disbursement/payout account.

  1. Create an Item to move money from your float user to your customer.
    POST /items
  2. Fund the Item with your float user’s wallet (use the ID you got in Step 5 from the inbound payments section)
    PATCH /items/:id/make_payment
  3. (Main wallet account) Create a withdraw request on the wallet to pay to your user’s nominated bank account (use the bank account ID from step 3).
    POST /wallet_accounts/:id/withdraw
    a. (Sub-wallet account) Create a withdraw request on the sub-wallet to pay to your user's nominated bank account (use the bank account ID from step 3).