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

API Reference

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. The sid has the format akpxxxxxxxxx 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

API Reference

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:

Akahu's payment status flow diagram

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. READYPENDING_APPROVALREADY).

StatusDescription
READYPayment is ready to be processed.
PENDING_APPROVALPayment is ready to be processed, however user approval is required before it can be processed. See the Manual Payment Approval section for more details.
PAUSEDPayment 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.

StatusDescriptionSuccess?
SENTPayment has been initiated with the user's bank and we've received confirmation that it has been accepted.
DECLINEDPayment has been declined by the user's bank. Details are supplied in the status_text field.✖️
ERRORAkahu has encountered an error (not your fault). Details may be supplied in the status_text field.✖️
CANCELLEDPayment 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:

  1. Akahu emails the user with a pre-authenticated link to view the payment in MyAkahu.
  2. The user follows the link, reviews the payment, and chooses to either:
    • Cancel the payment.
    • Complete the payment.
  3. 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.
  4. 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.

StatusStatus CodeDescription
ERRORINTERNAL_ERRORAkahu encountered an internal error while processing the payment.
BANK_ERRORAkahu received an unexpected error response or encountered connectivity issues with the bank while processing the payment.
UNAVAILABLEAkahu is unable to process the payment due to maintenance or updates that have impacted our integration with the initiating bank.
DECLINEDINSUFFICIENT_FUNDSThe specified bank account does not have sufficient funds to complete the payment.
SINGLE_LIMIT_EXCEEDEDThe 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_EXCEEDEDThe 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_EXCEEDEDThe payment amount exceeds the maximum value allowed by Akahu. Currently this is set at $100,000 for all payments.
AUTHENTICATION_FAILEDAkahu was unable to complete the payment because authentication with the user's bank was unsuccessful.
MFA_UNSUPPORTEDThe bank required a multi-factor authorization method that is not supported by Akahu.
MFA_FAILEDThe 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_UNSUPPORTEDThe payment requires approval from multiple signatories, which is unsupported at this time.
AFTER_HOURSThe bank rejected the payment due to their payment system being offline for out-of-hours maintenance.
INVALID_ACCOUNTThe specified bank account can't be used to initiate payments1.
CANCELLEDUSER_CANCELLEDThe payment required approval via the Manual Payment Approval process, but approval was denied by the user.
APP_CANCELLEDThe payment required approval via the Manual Payment Approval process, but was subsequently cancelled by an API call to PUT /payments/{id}/cancel.
AKAHU_CANCELLEDThe 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 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 include meta.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.