PaymentRequest API

Overview

The PaymentRequest API allows you to request others to pay you either using one of our Payment Request UX Apps, which is our recommended orchestration, or if you find your use case does not suit any of our UX Apps you can build, optimise and maintain your own using our API.

Our PaymentRequest Apps use the PaymentRequest API to generate a checkout UX that you can easily integrate in your payment page to receive payments from your customers. Our PaymentRequest App will return a URL to invoke the PaymentRequest Checkout App of your choice to ensure optimum user experience for your customers and reduce your development time. For more information, see Payment Request App.

If none of our Payment Request Apps or configurations work for you use case, then you can integrate with our API alone to receive payments.

Whether you use our free UX Apps or build your own, you will need to understand our PaymentRequest API. The Azupay Rest API has an entity called PaymentRequest. It is used to create a PayID (and in some cases a BSB and Account Number) that your customers can send payments to. For more information on the PaymentRequest API specifications, see the PaymentRequest API Reference guide.

Receiving payments via the API

When you use the PaymentRequest API, we generate a distinct PaymentRequest for your transaction, and register a PayID specific to the PaymentRequest. There are different types of PayIDs that you can create, the details of which are described in the next section.

We can also create a BSB and an Account Number (i.e Virtual Account) that is specific to the PaymentRequest. A payment to the virtual account will credit the payment to the corresponding PaymentRequest similar to how a payment is credited to the PaymentRequest when it is paid to the associated PayID. Note that this feature is not available by default, please contact support to enable this.

Types of PayIDs

You can configure different types of PayIDs for your PaymentRequests, such as Dynamic PayID or Open Static PayID. The former is for accepting a single payment at a point in time and the latter is for accepting multiple payments over time to the same PayID. Let's discuss these in the most basic form first and then take a look at how you can tweak their behaviour with special features that are described later on in this guide.

Dynamic PayID

This type of PayID can only receive a single payment and is useful in situations where your customers make a one-off purchase of goods, or pay a single invoice. The main characteristics of this type of PayIDs are:

  • Can only receive a single payment.
  • Once completed, the PayID will be de-registered.

To create a Dynamic PayID, issue the following API call:

POST https://api.azupay.com.au/v1/paymentRequest
Authorization: SECR_MYBUSINESSID_nR2duCGXlqWSuYJF
Content-Type: application/json
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000001-1",
    "paymentAmount": 32.12,
    "paymentDescription": "Client invoice numner INV-0000001"
  }
}

This is a very simple request message. Now let's have a look at what you submitted:

  • clientId: your unique client identifier that we provide you during onboarding.
  • clientTransactionId: a unique identifier for your business that does not repeat. If you send the same clientTransactionId in another request the system will not create a new one, but will return the status of the existing one. This serves as a duplicate check in case your HTTP client retries the same message. So it is a good practice to use a globally unique identifier (GUID) or append an extra counter to your invoice identifier in case you need to recreate the PaymentRequest.
  • paymentAmount: the amount you expect to receive. By default your Azupay account will be configured to receive an exact amount. If a different amount is received, Azupay will return that payment immediately. You can ask for this configuration to be changed to receive under, overpayments or any amount.
  • paymentDescription: additional description that will show for your payer and appear in your Client Dashboard and reports.

Once you submit this request you will receive a response like the following.

HTTP/1.1 200 OK
Date: Wed, 21 Apr 2021 03:36:47 GMT
Content-Type: application/json
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000001-1",
    "paymentAmount": 32.12,
    "paymentDescription": "Client invoice numner INV-0000001",
    "payID": "[email protected]"
  },
  "PaymentRequestStatus": {
    "paymentRequestId": "a050551479f625c066b559da28fee33c",
    "status": "WAITING",
    "createdDateTime": "2021-04-21T03:36:45.115Z"
  }
}

You can see there are some additional fields on the PaymentRequest as well as a new entity called PaymentRequestStatus.

For the PaymentRequest:

  • payID: the unique PayID generated for this transaction. Note it uses a domain mybusiness.com. This domain is configured for your business during onboarding. As part of onboarding we validate you have ownership of the domain.

The returned PaymentRequestStatus gives information about the newly created PaymentRequest. These are the fields:

  • paymentRequestId: an identifier generated by Azupay. Used to reference the object in subsequent operations such as getPaymentRequest and refundPaymentRequest. It is a good idea to store this identifier in your database so that you can enquire about the status later. You can also use it as a search parameter in the Client Dashboard
  • status: the status. Given you have just created it, its status is WAITING as in waiting for your customer to complete the payment. See the PayID Statuses at bottom of this page for more information about the status.

At this point the customer would have to go to their banking app and complete the payment to the PayID.

Open Static PayID

This is a different type of PayID that supports your customers to make multiple payments over time. It can be useful in situations like a customer wallet where you create a PayID for each customer and they use the same PayID repeatedly over time to top-up their account with you.

A few different rules apply for Open Static PayIDs:

  • The request must have the multiPayment field set to true
  • The status of these will always be WAITING.
  • The PayID description that your customers see will contain what was provided in the paymentDescription field.
  • Notification webhooks will contain a parentPaymentRequestId that corresponds to the paymentRequestId for this Multiple Payment PayID PaymentRequest.

An Open Static PayID does not have an amount set, but you can set an amount to support a slightly different user experience with the Recycled Static PayID. See Open Static PayID Amount Limits heading below to see the impact of setting an amount.

📘

Open Static PayIDs require a webhook to keep you updated on statuses

With Open Static PayIDs, the only way to learn about new incoming payments made to them is via a webhook endpoint or manually checking your Client Dashboard, so we recommend you provide the paymentNotification in the request. See the webhooks for Multiple Payment PayID's section for more details.

Recycled Static PayID

The PayID can be used repeatedly by creating new PaymentRequests using the same PayID string but specifying whatever you need for the new payment (e.g. different set amount and different description).
When this is done the payer can pay to the same PayID they saved in their own bank payee list and subsequent payments will see description and target amount you set for the new PaymentRequest.

Virtual Account

A virtual account is an alternate way to collect payments from your customers. Our PaymentRequest API can create a BSB and Account Number that your customers can pay to. If you request this to be enabled (contact support if you want to use this feature), you don't have to change anything when you call the PaymentRequest API but you will receive the following additional fields in the API response:

  • virtualBsb: The BSB that can be used to pay for this payment request.
  • virtualAccountNumber: The Account Number that can be used to pay for this payment request.
  • paidViaVirtualAccount: It will be true if this payment request was paid using the virtualBsb and virtualAccountNumber instead of the payID.

For more information on the PaymentRequest API specifications, see the PaymentRequest API Reference guide.

🚧

PayID has many efficiencies you will miss if your customers use BSB and Account Number payments

Australia is familiar with BSB and Account Number payments, so your customers may feel more comfortable with them, but PayID is the future and massively reduces payment errors. Azupay strongly believes you will have a better experience, as will your customers, by adopting PayID. You will also reduce your manual processing if you do not enable BSB and Account Number payments.

Due to the inefficiencies of BSB and Account Number payments compared to our PayID only solutions, there are additional fees if you do enable BSB and Account Number payments.

Features

The following are features that you can apply to PaymentRequests:

Customising the PayID

By default, Azupay will generate the PayID for you. You can also optionally supply a PayID you would like to register. If available, it will be used. Simply supply the value in the request body as follows:

POST https://api.azupay.com.au/v1/paymentRequest
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000001-1",
    "paymentAmount": 32.12,
    "paymentDescription": "Client invoice numner INV-0000001",
    "payID": "[email protected]"
  }
}

Note that the domain portion of the PayID, in this case '@somewhere.com' must be a domain that you own. We will verify ownership of this domain during onboarding.

Time limiting

You can apply time based limits on your PaymentRequests by specifying a point in time in the future via paymentExpiryDatetime field. This field will be set automatically by Azupay if no value is supplied for the Dynamic PayID PaymentRequest based on your default value.

Amount limiting

You can apply limits to the amount paid to a PaymentRequest. Azupay will keep track of total amounts paid to date even if there are multiple partial payments, multiple partial refunds and whether payments are sent to a PayID or a BSB and Account Number. Example amount limiting configurations are as follows:

Dynamic PayID amount limits

Set the amount you expect to receive. Note that the Azupay system defaults to expecting a single perfect payment, in the Dynamic PayID topic above, the API call did not specify the multiPayment field so our platform will default to only allow your payers to send a single payment that exactly matches the specified payment amount.

Open Static PayID amount limits

We use the term Static PayID to refer to PayIDs we create for you that remain over time to be used repeatedly. Different behaviours for these series of payment experiences can be created by setting an amount.

To recap from Open Static PayID topic above, multiPayment = TRUE will create an Open Static PayID

  1. No amount: For this payment request, we will accept any number of payments, of any amount, any time and the PayID will remain open. This is the Open Static PayID.
  2. Set amount: For this payment request, we will accept any number of payments, of any amount up to the specified amount. If the payment is overpaid on the last transaction, we will return the difference. Once the target amount is received we will deregister the PayID, which will prevent duplicate payments or further attempts to incorrectly overpay the amount.

Updating a PayID

You can change the conditions that apply to a PayID created previously by submitting a new PaymentRequest with the same payID but different clientTransactionId. This will cause the API to expire any existing PaymentRequest and create the new one.

For example, if you usually create a single PayID per client, something like [email protected]. You would create a first PaymentRequest like the one below:

POST https://api.azupay.com.au/v1/paymentRequest
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000001",
    "paymentAmount": 40.00,
    "paymentDescription": "Monthly invoice INV-0000001 for client 12345",
    "payID": "[email protected]",
    "paymentExpiryDatetime": "<last day of September>"
  }
}

Now if its end of the month, your client hasn't paid for invoice INV-0000001 and you have generated a new invoice INV-0000002 with the remaining balance you can submit a new PaymentRequest that would reflect the latest state of their account. Something like this:

POST https://api.azupay.com.au/v1/paymentRequest
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000002",
    "paymentAmount": 80.00,
    "paymentDescription": "Monthly invoice INV-0000002 for client 12345",
    "payID": "[email protected]",
    "paymentExpiryDatetime": "<last day of October>"
  }
}

Note that the clientTransactionId has a different value. Now your client would have to pay $80 instead of $40 and would see an updated description for the PayID when they look it up on their online banking app. The new PaymentRequest will also have a new paymentRequestId, this will be returned to you in the response of the second call.

This is the functionality that supports our Recycled Static PayID.

Incorrect payments

Sometimes your customer might submit a payment with an incorrect amount. Depending on whether it's to a Dynamic, Open Static or Recycled Static PayID, the behaviour will vary.

Where it's to a Dynamic Payment PayID, Azupay will return the funds back immediately since our system is expecting a single exact match amount only. If you are using our PayID Checkout App our UX will handle error messaging to the payer elegantly and encourage them to pay the correct amount.

Where it's to a Recycled Static PayID (it has been limited by amount), any underpaid amount will be retained. If an overpaid amount is sent the target amount will retained and any surplus will be refunded. If you are using our PayID Checkout App our UX will display a success message and also inform the payer that they were refunded the surplus amount.

Handling incorrect payments when not using our UX Apps

In the case of an overpayment to a Dynamic PayID, if you are not using our UX, it is critical you notify the customer of such errors so that they can submit the payment again. In the case of an overpayment to a Recycled Static PayID you should notify the customer the surplus has been refunded otherwise they may expect a credit note from you.

In cases when the target amount has not been reached the PayID will remain in WAITING and the PaymentRequestStatus object will be enriched with information about the payment attempts. When you enquire about the PaymentRequest you will get a result like the following:

"PaymentRequest": {...}
"PaymentRequestStatus": {
  ...
  "failedPaymentAttempts": [
    {
      "attemptDateTime": "2021-06-02T23:35:12.940Z",
      "attemptAmount": 30,
      "attemptFailureReason": "Incorrect Payment Amount"
    }
  ],
  "status": "WAITING"
}

With this information you can advise your customer to retry the payment with the correct amount.

Payment request actions

This section provides information on the different actions you can perform on the payment request after you create them.

Payment status

Given that the payment is initiated from the payer bank app, you need to verify the status of the payment either using a GET /v1/paymentRequest call. You could also use a webhook notification to receive updates on the status that will be explained further in this document.

To enquire about the status of a PaymentRequest you can perform GET call using the paymentRequestId that was returned in the PaymentRequestStatus. The request will look like this:

GET https://api.azupay.com.au/v1/paymentRequest?id=a050551479f625c066b559da28fee33c
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json

The status will be in WAITING until completed by the payer, when the status will become COMPLETE. Note that an Open Static PayID never reaches COMPLETE status, rather the individual payments received against it reach this status.

{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000001-1",
    "paymentAmount": 32.12,
    "paymentDescription": "Client invoice numner INV-0000001",
    "payID": "[email protected]",
    "paymentExpiryDatetime": "2021-04-21T03:51:45.256Z"
  },
  "PaymentRequestStatus": {
    "paymentRequestId": "a050551479f625c066b559da28fee33c",
    "createdDateTime": "2021-04-21T03:36:45.115Z",
    "payerPaymentDescription": "paying for my goods and services",
    "status": "COMPLETE",
    "amountReceived": 32.12,
    "completedDatetime": "2021-04-22T05:07:54.025Z"
  }
}

There are additional fields returned besides the new status:

  • amountReceived: usually should be the same as the paymentAmount
  • completedDatetime: the timestamp when the payment was received by Azupay.

Refunds

Full refunds

Once you have received a payment, and it is in COMPLETE status you can do a full refund by performing an API call like the following, again using the paymentRequestId:

POST https://api.azupay.com.au/v1/paymentRequest/refund?id=a050551479f625c066b559da28fee33c
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json

You will get a response like the following

{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    "clientTransactionId": "INV-0000001-1",
    "paymentAmount": 32.12,
    "paymentDescription": "Client invoice numner INV-0000001",
    "payID": "[email protected]",
    "paymentExpiryDatetime": "2021-04-21T03:51:45.256Z"
  },
  "PaymentRequestStatus": {
    "paymentRequestId": "a050551479f625c066b559da28fee33c",
    "createdDateTime": "2021-04-21T03:36:45.115Z",
    "payerPaymentDescription": "paying for my goods and services",
    "amountReceived": 32.12,
    "completedDatetime": "2021-04-22T05:07:54.025Z",
    "status": "RETURN_IN_PROGRESS",
    "refundInformation": {
      "availableBalance": "0.00",
      "requests": [
        {
          "refundTrigger": "REFUND_API",
          "createdDateTime": "2021-04-25T23:52:56.189Z",
          "nppTransactionId": "AZTPAU22XXXN20230419100000000000020",
          "status": "IN_PROGRESS",
          "amount": "501.00"
        }
      ]
    }
  }
}

The status of the PaymentRequest will go into RETURN_IN_PROGRESS which means it has been initiated but not completed yet.

After some time, and assuming you have enough liquidity with Azupay to perform the refund, you can enquire about the status for the PaymentRequest and see a change on the status to RETURN_COMPLETE indicating the refund has completed successfully. You will also receive a returnCompletedDatetime.

{
  "PaymentRequest": {
    ...
  },
  "PaymentRequestStatus": {
     ...
    "status": "RETURN_COMPLETE",
    "returnCompletedDatetime": "2021-04-25T23:52:58.189Z",
    "refundInformation": {
      "availableBalance": "0.00",
      "requests": [
        {
          "refundTrigger": "REFUND_API",
          "createdDateTime": "2021-04-25T23:52:56.189Z",
          "completedDateTime": "2021-04-25T23:52:58.189Z",
          "nppTransactionId": "AZTPAU22XXXN20230419100000000000020",
          "status": "COMPLETE",
          "amount": "501.00"
        }
      ]
    }    
  }
}

Because your funds are transferred back to your business regularly, there could be a scenario when you don't
have enough funds to perform the refund. In this case the status of would be RETURN_PENDING_LIQUIDITY and the API will retry the refunds again every 15 minutes until there is enough funds to perform the refund.

Partial refunds

To do a partial refund you would submit a similar request than for full refund but adding a refundAmount query parameter to the request.

Say you have a completed PaymentRequest for $100 and you do a partial refund of $25 using a POST like the
following.

POST https://{{api-host}}/v1/paymentRequest/refund?id=a050551479f625c066b559da28fee33c&refundAmount=25
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json

Once the refund is completed, when you enquire on the PaymentRequest you will see a response like the one below.

{
  "PaymentRequest": {
    ...
  },
  "PaymentRequestStatus": {
    ...,
    "refundInformation": {
      "availableBalance": "75.00",
      "requests": [
        {
          "refundTrigger": "REFUND_API",
          "nppTransactionId": "AZTPAU22XXXN20230419100000000000020",
          "createdDateTime": "2021-04-22T06:40:25.198Z",
          "completedDatetime": "2021-04-23T05:42:09.373Z",
          "status": "COMPLETE",
          "amount": "25.00"
        }
      ]
    },
    "status": "RETURN_COMPLETE",
    "returnCompletedDatetime": "2021-04-23T05:42:09.373Z",
  }
}

The latest entry in the refundInformation object will contain the information about the partial refund.

👍

Multiple Partial Refund Behaviour

We support multiple partial refunds up to the total amount received. Our system will prevent you from refunding more than you have received. Even if you attempt multiple partial refunds and even if your customer sends back partial payments in between, we will keep track of the balance and ensure you never send back more than you've received.

Deleting a PayID

When you delete a PaymentRequest the associated PayID will be de-registered from the NPP platform, which means your customers can no longer pay to it. You use the paymentRequestId in a simple HTTP DELETE operation.

DELETE https://api.azupay.com.au/v1/paymentRequest?id=a050551479f625c066b559da28fee33c
Authorization: SECR_MYBUSINESSID_myapikey

📘

When can I delete a Payment Request?

Note: you can only delete a PaymentRequest that is in WAITING status.

Additional Information

Advanced PayID customisation

Custom description

By default, when you create a PayID, the description that the payer sees on their banking application looks something like the following:

The entire description is a concatenation of your organisation name (My business full legal name), the amount ($32.12) and payment description (INV-0000001).

Given the Open Static PayIDs do not have an amount, the description will just omit amount, but
the rest will be the same. It will look something like the following:

You can customise the payment description when creating the PaymentRequest like the following:

{
  "PaymentRequest": {
    ...
    "paymentAmount": 32.12,
    "paymentDescription": "Invoice INV-0000001",
    ...
  },
  ...
}

Note that the organisation name at the beginning corresponds to the full legal name that was provided during on-boarding. Sometimes your customers may not recognise your company's full legal name and it will be more appropriate to use your trading name.
The next section shows how you can customise the organisation name for a particular PayID domain.

🚧

It is a requirement that the organisation name reflects the name your business is known by in the market

We default to using your legal name and will need to review any other organisation names you want to use to ensure they are reflect your business correctly.

Custom brand or organisation name

You can assign a custom Organisation or Merchant name specific domains that would reflect in the payment description either as you onboard or by using our payIdDomains API endpoint. The endpoint to update domains is not enabled by default, and you would need to specifically request it to be included when signing the commercial agreement with Azupay.

You can start by enquiring about the domains that are configured in your account.

GET https://api.azupay.com.au/v1/config/payIdDomains
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json

Then you will get a list like the following:

[
  {
    "domain": "mybusiness.com"
  }
]

Now, if you want the organisation name to be My Business Brand for all payIDs with domain mybusiness.com then you can send the following request.

POST https://api.azupay.com.au/v1/config/payIdDomains
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json

[
  {
    "domain": "mybusiness.com",
    "merchantName": "My Business Brand"
  }
]

Now when your payment description will look like this:

📘

Merchant Name not set?

If you have a domain configured without merchantName the payID description for that domain will default to the full legal business name used during on-boarding.

Webhooks

We strongly recommend you receive an http call whenever a payment is received and you can do so by passing additional parameters for the endpoint and secret header when creating the PaymentRequest.

POST https://api.azupay.com.au/v1/paymentRequest
Authorization: SECR_MYBUSINESSID_myapikey
Content-Type: application/json
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    ...
    "paymentNotification": {
      "paymentNotificationEndpointUrl": "https://mybusiness.free.beeceptor.com",
      "paymentNotificationAuthorizationHeaderValue": "my-secret-header"
    }
  }
}

When the payment is completed, you will receive a request like the following:

POST https://mybusiness.free.beeceptor.com
Authorization: my-secret-header
Content-Type: application/json;charset=utf-8
{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    ...
  },
  "PaymentRequestStatus": {
    ...
    "status": "COMPLETE"
  }
}

The contents of the PaymentRequestStatus and PaymentRequest objects are the same as if you were doing a API call to enquire about the PaymentRequest. Notice that the Authorization header is the one you configured in your initial request.

❗️

Authorization header security recommendation

Given your business will probably fulfill a product upon this invocation, for security reasons it is recommended that you use an Authorization header value which is unique per transaction and is a mix of upper and lower alphabetic, numeric and symbol characters.

Now you can use the clientTransactionId or paymentRequestId to match against your records.

👍

Configuring what events to receive via webhook

You can configure which events to receive from the payment lifecycle by going to the Client Dashboard.

Webhooks for Static PayID's

When a customer performs a payment to a Static PayID, the webhook message will contain a message like the following:

{
  "PaymentRequest": {
    "clientId": "MYBUSINESSID",
    ...
  },
  "PaymentRequestStatus": {
    ...,
    "parentPaymentRequestId": "a39c360044a4e399fad93a1c5c9419a5"
    "status": "COMPLETE"
  }
}

Notice there is a parentPaymentRequestId. This corresponds to the paymentRequestId of the original
Static PayID PaymentRequest.

PayID statuses

The following is a state diagram for our PayIDs.

StatusDescriptionDynamic PayIDStatic PayID (multipayment = TRUE)
WAITINGThe PayID has been created and is awaiting a payment from your customer. If you created this paymentRequest by setting multiPayment to true then it will remain in WAITING until it's deleted. A Static PayID in WAITING state will expire at the time specified in the paymentExpiryDatetime field.YesYes
COMPLETEThe PayID has been paid.YesNo
RETURN_IN_PROGRESSA payment was made to this PayID and either it's been rejected because it was the incorrect amount or a refund has been requested via API or our Azupay dashboard and the return payment has not yet been completed.YesNo
RETURN_PENDING_LIQUIDITYA payment can only be refunded if there is sufficient liquidity in your Azupay account. Azupay will keep retrying the return of these funds until there is sufficient liquidity from other payments.YesNo
RETURN_COMPLETEA refund was requested and successfully completed.YesNo
RETURN_FAILEDA refund failed due to an unknown error with Azupay. Azupay will retry the return automaticallyYesNo
RETURN_REJECTEDA refund failed due to problems with the destination account. Azupay will not retryYesNo
EXPIREDThe payment was not paid and is past its expiry time or it has been superseded by a new PaymentRequest with the same PayIDYesN

Test Bank

When testing in our sandbox environment, you can finalize payments to a PayID by utilizing our Test Bank utility. This tool replicates the actions your customers would take in their banking app to successfully complete the payment process.

Simply input the PayID or the BSB and Account Number you wish to make a payment to and proceed with the payment transaction.

API Key

In the example API calls above, we will assume you already have an API Key (e.g.SECR_MYBUSINESSID_nR2duCGXlqWSuYJF) with Azupay.