Making a Payment
Learn how to make a payment from a user's account
This guide is intended for developers using Akahu's enduring account connectivity. This guide is not relevant for those using one-off account connectivity.
Akahu's /payments
endpoint allows you to initiate payments from bank accounts that your users have connected via Akahu.
Akahu initiates online banking payments from a user's account using the bank's mobile banking infrastructure. As such, any restrictions that apply to the user's mobile banking payments (e.g. daily transaction limits) also apply to payments initiated through Akahu. See our Payment Limitations section to learn more about how this may affect you.
Akahu payments are designed to move money from your user's connected account to another party's bank account. To move money between a user's connected accounts, make a transfer instead.
Making payments will move actual money around! Once a payment has been initiated by Akahu, it cannot be reversed. It is recommended to make use of our Demo Bank connection or only pay using small amounts during development.
Prerequisites
Our payments endpoint is restricted to whitelisted apps. If you want to get your app approved for making payments, please contact us.
Before you can make a payment, you will need:
- To be able to make requests to the Akahu API (see here for instructions).
- An Akahu account with at least one bank account connected that can make online banking payments.
To determine if your account can make payments, make a GET
request to the /accounts
endpoint. Locate your account in the results and look for the attributes
property on the account. If your account attributes
includes PAYMENT_FROM
, you can initiate a payment from that account.
Making the request
To initiate a payment, make a POST
request to the /payments
endpoint, with the following details in the body. For more information about what can be put in the meta
field, see the following section on Payment PCR Fields:
To make tax payments to the IRD, use the special purpose
/payments/ird
endpoint instead.
{
"to": {
"account_number": "01-2345-6789012-34", // The NZ bank account number for the destination account
"name": "James Smith" // The name of the destination account holder. Limited to /[A-z0-9 \-_]/
},
"from": "acc_11111111111111111111", // The account ID that you want to pay from
"amount": "<number>", // How much you want to pay (in New Zealand dollars)
"meta": {
"source": {
// Statement details to be shown on the source account. Limited to /[A-z0-9 \-_]{0,12}/
"code": "<string>",
"reference": "<string>"
},
"destination": {
// Statement details to be shown on the destination account. Limited to /[A-z0-9 \-_]{0,12}/
"particulars": "<string>",
"code": "<string>",
"reference": "<string>"
}
}
}
The response will look like:
{
"success": true,
"item": {
"_id": "payment_1111111111111111111111111",
"status": "READY",
"sid": "akp1111111111",
"from": "acc_1111111111111111111111111",
"to": {
"name": "John Smith",
"account_number": "12-1234-1234567-12"
},
"amount": 9.5,
"created_at": "2020-04-20T01:55:41.674Z",
"updated_at": "2020-04-20T01:55:41.674Z",
"timeline": [
{
"status": "READY",
"time": "2020-04-20T01:55:41.674Z"
}
],
"final": false
}
}
Akahu initiates payments asynchronously. Receiving a success response from the
POST /payments
endpoint does not guarantee that the payment will complete successfully. Make sure you retain the returned payment_id
so that you can follow its progress and verify successful initiation.
Payment PCR fields
There are three text fields available when making online banking payments in New Zealand: particulars, code, and reference (PCR). The values of these fields can be specified independently for the payer and payee, and appear in the transaction line-item on their respective bank statements.
When making a payment using Akahu, an app can choose the values for these fields with some exceptions:
- The payer's particulars field is reserved for use by Akahu* and is not available for apps.
- The payee's particulars field is available for apps, however doing so will disable arrival tracking for the payment.
- The remaining fields (code and reference) are available for apps to use as they require.
Each PCR field may contain a maximum of 12 characters, using only the allowed set of alphanumeric characters, spaces ( ), underscores (_), and hyphens (-).
*Akahu includes a unique identifier (
sid
) in the payer's particulars field. Thesid
has the formatakpxxxxxxxxx
and can be found in the payment response (see example response above).
Payment restrictions
Akahu follows the principle of least privilege when it comes to making payments. Where possible, we will apply restrictions to payments initiated by your app to protect users against compromise of your Akahu API credentials.
If you are using payments and have not yet talked to us about this, we will review possible restrictions for your app during app accreditation.
Akahu may restrict payments by:
- Limiting the set of account numbers your app can pay to. Typically your app will only need to pay into your company account(s).
- Setting maximum payment amounts.
- Ensuring the data in payment "code" and "reference" fields conforms to a certain format.
If you attempt to create a payment that is not allowed by your app's restrictions, you will receive a 400
HTTP response with an error message.
Following payment progress
Akahu initiates payments asynchronously. This means that your app must track each payment as it is processed so that any issues can be handled appropriately. Generally a payment will complete within a few seconds of your request, however in some circumstances - such as payments that require manual approval - this may take up to 48 hours.
Akahu provides two ways to keep track payments:
- Polling
- Webhooks (recommended)
Polling
The simplest way to keep an up-to-date view of the payment is to make periodic GET
requests to the /payments/{_id}
endpoint, using the payment _id
returned when you created the payment. Polling will work fine for simple use-cases, however this approach is generally more brittle and less efficient.
Webhooks
We recommend that production applications subscribe to the PAYMENT
webhook to be notified of any payment status changes. Webhooks allow you to write simpler, more robust code to keep track of status changes to the payments that your app initiates. See our webhooks guide for more information on configuring your app to receive Akahu webhooks.
Payment lifecycle
A payment's status
property reflects which stage of of processing the payment is in. Most often, a payment will be created with a status
of READY
, then quickly progress to SENT
once Akahu has completed payment initiation. Other potential statuses can be seen in the diagram below:
Processing statuses
While a payment is still being processed by Akahu, it will have one of the statuses listed in the table below. A payment may move between these statuses as it is processed (e.g. READY
→ PENDING_APPROVAL
→ READY
).
Status | Description |
---|---|
READY | Payment is ready to be processed. |
PENDING_APPROVAL | Payment is ready to be processed, however user approval is required before it can be processed. See the Manual Payment Approval section for more details. |
PAUSED | Payment is not yet ready to be processed. This might happen if the payment requires review by Akahu for reasons such as fraud prevention, troubleshooting, or manual checks. |
Final statuses
Once Akahu has finalised the processing of a payment, it will be assigned one of the following statuses. Once a payment receives one of these statuses, it is considered immutable and will not progress any further. Additionally, the final
property on the payment will change to true
to indicate this state.
You can use the Demo Bank connection to test your app's handling of these various payment states to ensure that they are handled appropriately.
Status | Description | Success? |
---|---|---|
SENT | Payment has been initiated with the user's bank and we've received confirmation that it has been accepted. | ✅ |
DECLINED | Payment has been declined by the user's bank. Details are supplied in the status_text field. | ✖️ |
ERROR | Akahu has encountered an error (not your fault). Details may be supplied in the status_text field. | ✖️ |
CANCELLED | Payment was cancelled. Details may be supplied in the status_text field. | ✖️ |
If you are using polling to check for payment updates, watching for
final == true
is a good indicator of when to stop.
Manual payment approval
A payment may be assigned a status
of PENDING_APPROVAL
, indicating that manual approval is required from the user before Akahu can complete payment initiation. Manual approval of a payment may be required by either:
- The user's bank. For example, a multi-factor authentication (MFA) challenge.
- The user, if they have requested this1.
1Akahu is yet to implement this feature.
Approval flow
The manual approval flow is initiated when Akahu assigns the PENDING_APPROVAL
status to a payment. No specific action is required by your application during this process. The manual approval flow consists of the following:
- Akahu emails the user with a pre-authenticated link to view the payment in MyAkahu.
- The user follows the link, reviews the payment, and chooses to either:
- Cancel the payment.
- Complete the payment.
- If the approval was bank-initiated, the user may need to complete an MFA challenge (such as entering an SMS code) from within the MyAkahu user interface.
- Akahu will attempt to complete the payment.
Additional properties
While a payment has the PENDING_APPROVAL
status, the following additional properties will be available on the payment object returned by Akahu:
approval_type
will have a value of either"BANK"
- indicating that the bank is requiring the user's approval, or"USER"
- indicating that the user has requested that Akahu asks their approval before completing certain payments1.approval_url
a link to view and approve the payment in MyAkahu. Your app can prompt the user with this link to complete a payment approval. Unlike the link that Akahu emails to the user, this is not pre-authenticated, requiring that the user logs in to MyAkahu before they can complete the approval.
1Akahu is yet to implement this feature.
Cancellation
Akahu will automatically cancel payments that remain in PENDING_APPROVAL
for more than 48 hours. During this time, your app may also cancel the payment using the /payments/{id}/cancel
endpoint.
Handling errors
When initiating payments using Akahu, you may encounter one of the following types of errors:
- A validation error in response to your request to
POST /payments
. - The payment is assigned an error status due to an error that has occurred during processing.
Validation error
If your POST
request to the /payments
endpoint returns an error response with a 400
status code, this indicates that your request has failed our validation. Check the message
provided in the response body for an explanation of what's gone wrong and how to resolve it.
Payment processing error
If there is an issue processing a payment, it will be assigned a status of DECLINED
or ERROR
.
A DECLINED
payment has been rejected by either Akahu or the bank and may be caused by an issue such as insufficient funds or a transaction limit being exceeded. This type of error is unlikely to be resolved by retrying.
A payment with an ERROR
status indicates that Akahu encountered an issue during processing. In some cases (such as a bank API outage), this type of error may be resolved by retrying the payment. A single retry after a short delay should be sufficient to determine whether this is the case.
For further detail on the cause of a specific error, you can refer to the status_code
and status_text
as described below.
Status code and status text
When a payment is assigned a final status of ERROR
, DECLINED
, or CANCELLED
, two additional fields status_code
and status_text
will be available on the payment object. These two fields can be inspected to find out more information about the cause of the payment's status.
The status_code
field is safe for programmatic use and will contain one of the values listed in the table below. The status_text
field is a human-readable explanation of the cause, designed to be readable by both developers and end users.
Status | Status Code | Description |
---|---|---|
ERROR | INTERNAL_ERROR | Akahu encountered an internal error while processing the payment. |
BANK_ERROR | Akahu received an unexpected error response or encountered connectivity issues with the bank while processing the payment. | |
UNAVAILABLE | Akahu is unable to process the payment due to maintenance or updates that have impacted our integration with the initiating bank. | |
DECLINED | INSUFFICIENT_FUNDS | The specified bank account does not have sufficient funds to complete the payment. |
SINGLE_LIMIT_EXCEEDED | The payment amount exceeds the maximum single-payment limit that is enforced for this account by the bank. See Payment Limitations for a list of known limits for each bank. | |
DAILY_LIMIT_EXCEEDED | The payment would cause the cumulative daily payment limit for this account to be exceeded. See Payment Limitations for a list of known daily limits for each bank. | |
AKAHU_LIMIT_EXCEEDED | The payment amount exceeds the maximum value allowed by Akahu. Currently this is set at $100,000 for all payments. | |
AUTHENTICATION_FAILED | Akahu was unable to complete the payment because authentication with the user's bank was unsuccessful. | |
MFA_UNSUPPORTED | The bank required a multi-factor authorization method that is not supported by Akahu. | |
MFA_FAILED | The bank required multi-factor authorization for the payment, which was handled by the Manual Payment Approval process. However, the user was unable to complete the authorization (e.g. they entered an SMS code incorrectly too many times). | |
MULTISIG_UNSUPPORTED | The payment requires approval from multiple signatories, which is unsupported at this time. | |
AFTER_HOURS | The bank rejected the payment due to their payment system being offline for out-of-hours maintenance. | |
INVALID_ACCOUNT | The specified bank account can't be used to initiate payments1. | |
CANCELLED | USER_CANCELLED | The payment required approval via the Manual Payment Approval process, but approval was denied by the user. |
APP_CANCELLED | The payment required approval via the Manual Payment Approval process, but was subsequently cancelled by an API call to PUT /payments/{id}/cancel . | |
AKAHU_CANCELLED | The payment required approval via the Manual Payment Approval process, but no action was taken within 48 hours so it was cancelled by Akahu. |
1This condition is validated when the payment is submitted to the API and would cause a 400 error response, meaning that such a payment would never be created. Consequently, it is highly unlikely that a payment receives this status code.
Payment arrival tracking
If the to
bank account of a payment is connected to Akahu and has been shared with at least 1 app that requests the TRANSACTIONS
scope, Akahu is able to track the arrival of the payment in this account.
Payment arrival tracking is implemented by including a unique reference code (sid
) in the particulars
field that appears on the payee's bank statement*. When Akahu refreshes the transaction feed for the payee's bank account, we will search for a transaction with a particulars
field containing this code.
If there are connectivity issues or problems with the payee's transaction feed, payment arrival tracking may not be triggered. Because of this, we do not consider this to be a robust feature and make no guarantees about it's reliability. Payment arrival tracking is well suited to providing visual feedback about the status of a payment on a user interface, but should not be relied on for the functionality of your application.
When a payment arrival has been confirmed, the received_at
timestamp will be set on the payment, and a PAYMENT RECEIVED
webhook will be sent.
*Note: if an app specifies a value for
meta.destination.particulars
, this will overwrite Akahu's unique reference and we will no longer be able to perform arrival tracking. If you would like arrival tracking on your payments, make sure that they don't includemeta.destination.particulars
.
Payment limitations
Akahu imposes a limit of $100,000 on a single payment request, so any payment request for a higher amount will result in a DECLINED
status with a status_code
of AKAHU_LIMIT_EXCEEDED
.
This remainder of this section documents known limitations that our supported banks have in place on their mobile banking infrastructure. These limitations apply in turn to Akahu payments.
General recommendations
Payment functionality is more consistent across banks during business hours. We recommend scheduling any recurring payments during business hours where feasible, as Akahu is more likely to be able to provide reliable responses from the banks.
ANZ
ANZ places a default single payment limit of $10,000 on all accounts. We recommend breaking payments from ANZ bank accounts into multiple chunks of $10,000 or less to avoid this limit.
ASB
ASB places a default daily payment limit of $100,000 on outbound payments. This is a cumulative limit that applies across all payments made using Fastnet Classic, ASB Mobile, and Akahu in a single day. We recommend against using Akahu for use-cases that require a daily transaction volume of >$100,000 from a single account.
BNZ
BNZ places a daily payment limit of $50,000 on outbound payments.
Heartland Bank
Heartland Bank places a daily payment limit of $5,000 on outbound payments from YouChoose accounts.
Heartland Direct Call accounts can have a nominated account. There are no limits when paying to the nominated account, however when paying to other accounts a $2000 single payment limit is imposed.
Heartland Bank processes inter-bank payments overnight Monday to Friday. Inter-bank payments initiated from a Heartland account after 7pm are not included in the nightly batch and will be instead processed during the next overnight processing batch. Because of this, payments initiated from a Heartland bank account may take 24 hours or more to reach their destination. See Heartland's website for more information.
Rabobank
Payments from a Rabobank account will return an error if they are initiated outside of business hours. There is a daily payment limit of $25,000, which can be increased upon request from the user. The payee must either be a registered bill payee or an existing payee of the payer. Due to an API access agreement between Akahu and Rabobank, any Akahu customer must receive prior written approval from Rabobank before using this integration (please contact us to arrange Rabobank's approval on your behalf).
The Co-operative Bank
The Co-operative Bank generally responds with an MFA challenge for payments to a new payee that are greater than approximately $500 in value (although this threshold is sometimes less). Currently, such payments will fail with a status of DECLINED
. Akahu does not currently support Co-op payments that require completion of an MFA challenge, but we intend to do so in the future via the manual approval flow.
Payments to a "registered bill payee" do not require the user to complete an MFA challenge. If your app is initiating payments to a single destination account, we recommend that you consider registering as a bill payee to avoid MFA-related issues. Here is a description from Kiwibank on how to register as a bill payee.
TSB
TSB has a user-configurable payment amount threshold, above which TSB will require the user to complete an MFA challenge to complete payment initiation. For new TSB accounts, this threshold defaults to $0 (every payment will be challenged) and can be set to a maximum of $5000. Akahu does not currently support TSB payments that require completion of an MFA challenge, but we intend to do so in the future via the manual approval flow.
Payments to a "registered bill payee" do not require the user to complete an MFA challenge. If your app is initiating payments to a single destination account, we recommend that you consider registering as a bill payee to avoid MFA-related issues. Here is a description from Kiwibank on how to register as a bill payee.
Westpac
Westpac generally responds with an MFA challenge for payments to a new payee that are greater than approximately $500 in value (although this threshold is sometimes less). In such cases, the payment will be put into our manual approval flow for completion by the user.
Updated 3 months ago