Online EFTPOS Integration Guide
API Endpoint
https://apitest.paymark.co.nzIntroduction
Hello from Online EFTPOS! This document describes what Online EFTPOS is, its features and how to integrate to the REST APIs to enable your customers to pay.
Online EFTPOS is NZ’s first Open Banking integrated product. Open Banking enables us to integrate directly with NZ banks and offer secure, trusted and innovative payment solutions. Your customers can pay from their NZ bank account and safely approve payment or consent requests in their banking app. No need to use physical cards or remember the card number, customers just need their mobile phone and bank app.

Integration Modes
Use Hosted Page for a quick and secure setup with minimal development effort, or Custom Page to embed the payment experience directly into your site for greater control and a seamless customer experience.
Choose the integration mode that best suits your needs.
Hosted Page is a secure Worldline-hosted payment page where customers are redirected during checkout to complete their payment.
After the payment is processed, you can choose how to handle the customer experience:
-
Redirect your customer back to your website via the
redirectUrl
supplied in the create payment intent request, or -
Allow Worldline to display a confirmation message on your behalf.

Custom Page integration allows you to embed the payment plugin directly within your website using an <iframe>
, without needing to redirect your customer away from your website. You simply render the pre-built form on your checkout page using the paymentId returned from the create payment intent API response. Your customer can then complete the payment seamlessly within your site.

Getting Started
To integrate with Online EFTPOS, follow these key steps:
-
Generate API Key and Secret
Generate your API key and secret from the Merchant Portal. -
Authenticate API Requests
Use your API credentials to authenticate requests via HTTP Bearer Authentication. -
Create a Payment Intent
Initiate a payment by calling the create payment intent API endpoint. -
Integrate using either:
-
Receive Payment Status
Confirm payment completion using webhook notifications or by querying the payment status. -
How to Make a Refund
Refund a payment through the API or directly in the merchant portal. -
Get Ready to Go Live
Complete the pre-Go Live checklist to ensure your integration is production-ready.
Note:
Refer to Environment URLs for sandbox and production URLs.
API Overview ¶
Our API provides a set of endpoints to enable secure and reliable payment processing. Below is a high-level summary of the key endpoints required for integration.
Open API Specification
Please refer to the Open API Sepcification file for a complete API definition including request schema definition.
Download Open API Specification (Swagger file)
Note:
-
Ensure your integration is configured to include the correct API version in the base URL.
-
Example v2 in
/oe/transactions/v2/payments/create-intent
.
Authentication
Endpoint | Method | Description |
---|---|---|
/bearer |
POST |
Obtain a Bearer Token using your API Key and Secret via Basic Auth (Client Credentials Grant) Generate the Key and Secret in the Merchant Portal |
Payments
Endpoint | Method | Description |
---|---|---|
/oe/transactions/v2/payments/create-intent |
POST |
Create a payment intent to register customer’s intent to pay |
/oe/transactions/v2/payments/{paymentId} |
GET |
Retrieve payment by paymentId |
Refunds
Endpoint | Method | Description |
---|---|---|
/oe/transactions/v2/refunds |
POST |
Create a refund against a payment |
/oe/transactions/v2/refunds/{refundId} |
GET |
Retrieve refund by refundId |
Generate API Key and Secret ¶
Go to the Integration page in the portal and generate your API key and secret. You will use these credentials to obtain a Bearer Token for making server-to-server calls from your website’s backend to our APIs.

Authentication ¶
All requests to our API must be authenticated using a Bearer Token provided in the Authorization
HTTP header. This token-based mechanism allows you to access and use our APIs. Our server will validate this token before continuing to process your request.
To obtain a Bearer Token you must exchange your API Key and Secret with our authorisation server. These credentials can be generated from the Integration page in the Merchant Portal.
Step-by-Step Process
- Generate a Basic Authorization Token
Concatenate your API Key and API Secret with a colon (:
) separator:
APIKey:APISecret
Then, base64 encode this string. This becomes your Basic Authorization Token.
- Request a Bearer Token
Make aPOST
request to the token endpoint using the Basic Authorization Token in theAuthorization
header, and includegrant_type=client_credentials
in the request body.
Obtain Bearer Token ¶
Headers
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64-encoded APIKey:APISecret>
Body
grant_type=client_credentials
Headers
Content-Type: application/json
Body
access_token: `eyJhbGci...`
token_type: `Bearer`
expires_in: 3600
POST/bearer
Obtain a Bearer Token using your API Key and Secret.
Using the Bearer Token ¶
Once you’ve obtained a Bearer Token, you can use it to authenticate all API requests by including it in the Authorization
header:
Authorization: Bearer <access_token>
Token Usage Guidelines
-
Reuse the same token for all requests until it expires.
-
Do not request a new token for every API call. This can lead to rate limiting or unnecessary load on the authorisation server.
-
The token’s lifetime is indicated in the
expires_in
field (seconds). -
Once expired, simply repeat the token request process to obtain a new token using the same API Key and Secret.
-
A token can be used for all merchant accounts under the account in which the credentials were generated. See Merchant Account Hierarchy for information on organisaction structures. E.g. credentials generated at a Root Parent can be used for all Parent and Child accounts under it.
Token Expiry
If you use an expired token, the API will return a 401 Unauthorized response. In that case, generate a new token and retry the request.
Create Payment Intents ¶
First step in the payment flow is to create a payment intent. A payment intent captures the details for the payment and indicates to us that you have a customer who is wanting to pay for some goods or service.
The create payment intent call must be made by your back-end server, supplying the Bearer Token you obtained in the previous step. This is to ensure that the payment intent details are created in a secure manner and free from tampering through the front-end.
The key information to send in the create payment intent request will be the amount
you are wanting to charge your customer, your merchantId
, and also the reference
and description
(optional) for the payment.
Create Payment Intent ¶
Headers
Content-Type: application/json
Authorization: Bearer <access_token>
Body
{
"merchantTransactionId": "98102214-20f5-4fb9-a699-6574ca6771cb",
"integrationMode": "CUSTOM",
"merchant": {
"url": "https://icecreamshop.demo.paymark.co.nz/open-checkout",
"redirectUrl": "https://icecreamshop.demo.paymark.co.nz/open-checkout/redirect",
"notificationUrl": "https://icecreamshop.demo.paymark.co.nz/open-checkout/notification"
},
"oepayment": {
"amount": 1500,
"currency": "NZD",
"reference": "icecream0131"
},
"risk": {},
"userAgentInfo": {
"userAgent": "Mozilla/5.0",
"userIpAddress": "192.168.1.1",
"userAgentType": "DESKTOP",
"latitude": -36.8485,
"longitude": 174.7633
},
"customerType": "CONSUMER",
"serviceType": "ECOMMERCE_GOODS",
"deliveryAddress": {
"addressType": "DELIVERY_TO",
"addressLine": [
"88 Shortland Street",
"CBD"
],
"streetName": "Shortland St.",
"buildingNumber": "18",
"postCode": "1010",
"townName": "Auckland",
"countrySubDivision": "Auckland",
"country": "NZ"
}
}
Headers
Content-Type: application/json
Body
{
"paymentId": "54f501aa-b130-4ec1-9f07-cb5d8dc8438a",
"merchantTransactionId": "98102214-20f5-4fb9-a699-6574ca6771cb"
}
POST/oe/transactions/v2/payments/create-intent
Create a payment intent to register a customer’s intent to pay.
Sample Responses ¶
Integration Mode – Custom
{
"paymentId": "54f501aa-b130-4ec1-9f07-cb5d8dc8438a",
"merchantTransactionId": "98102214-20f5-4fb9-a699-6574ca6771cb"
}
Integration Mode – Hosted
{
"paymentId": "54f501aa-b130-4ec1-9f07-cb5d8dc8438a",
"merchantTransactionId": "98102214-20f5-4fb9-a699-6574ca6771cb"
"paymentUrl": "https://hosted.demo.worldline.co.nz/?paymentId=54f501aa-b130-4ec1-9f07-cb5d8dc8438a"
}
Field Definition ¶
Field | Type | Required | Validation | Description |
---|---|---|---|---|
merchantTransactionId | String | Y | UUID | Merchant supplied ID for idempotency |
integrationMode | Enum | Y | Values: CUSTOM , HOSTED |
Field indicating how payment request will be presented to the end customer |
merchant.url | String | Y | Valid URL | Merchant’s base URL. Used to validate where the plugin will be embedded for Custom Page integration |
merchant.redirectUrl | String | N | Valid URL | Only for Hosted Page integration. Merchant’s URL to return customer to upon payment completion |
merchant.notificationUrl | String | Y | Valid URL | Merchant’s URL where notification callback will be sent to |
merchant.merchantId | String | Y | Regex: ^\d{9}$ |
Unique 9 digit number assigned to merchant during onboarding |
oepayment.amount | Integer | Y | amount must be greater than 0 | Payment amount in cents |
oepayment.currency | Enum | Y | Values:NZD |
Currency of the payment amount |
oepayment.reference | String | Y | Regex: ^[A-Za-z0-9 -]{0,100}$ |
Reference of transaction on customer’s statement Only first 12 characters will be displayed. |
oepayment.description | String | N | Regex: ^[A-Za-z0-9 -.,]{0,100}$ |
Optional internal merchant description of the transaction |
risk.userAgentInfo.userAgent | String | Y | Regex: ^[\S ]{1,8192}$ |
The raw user agent string of the client making the request. Typically identifies the browser, operating system, and device type |
risk.userAgentInfo.userIpAddress | String | Y | Regex: ^([0-1]?\d?\d | 2[0-4]\d |
risk.userAgentInfo.userAgentType | Enum | N | Values: DESKTOP , MOBILE , TABLET , POS_TERMINAL , EMBEDDED_DEVICE , BOT , SMART_TV , GAME_CONSOLE , WEARABLE , UNKNOWN |
A high-level classification of the device type inferred from the user agent |
risk.userAgentInfo.latitude | Decimal | N | The approximate geographic latitude of the user/device at the time of the request, if available | |
risk.userAgentInfo.longitude | Decimal | N | UUID | The approximate geographic longitude of the user/device at the time of the request, if available |
risk.customerType | Enum | N | Values: NEW , REGULAR , ANONYMOUS , BUSINESS |
Indicates the general classification of the customer |
risk.serviceType | Enum | N | Values: ECOMMERCE_GOODS , ECOMMERCE_SERVICE , OTHER |
Describes the category of service or product associated with the payment |
risk.deliveryAddress.addressType | Enum | N | Values: DELIVERY_TO |
Identifies the nature of the postal address |
risk.deliveryAddress.addressLine | List |
N | Regex: ^[A-Za-z0-9 ,.-]{1,50}$ |
The full, free-form address line provided for delivery. May contain street, building, and unit details |
risk.deliveryAddress.streetName | String | N | Regex: ^[A-Za-z0-9 -.]{1,500}$" |
Name of a street or thoroughfare component of the delivery address |
risk.deliveryAddress.buildingNumber | String | N | Regex: ^[A-Za-z0-9 #]{1,20}$ |
The building number or unit number in the delivery address |
risk.deliveryAddress.postCode | String | N | Regex: ^[0-9]{4}$ |
The postal or ZIP code of the delivery address |
risk.deliveryAddress.townName | String | N | Regex: ^[A-Za-z0-9 ,.-]{1,50}$ |
The town or city name for the delivery address |
risk.deliveryAddress.countrySubDivision | String | N | Regex: ^[A-Za-z0-9 .-]{1,50}$ |
The state, province, or region within the country for the delivery address |
risk.deliveryAddress.country | String | N | Regex: ^[A-Z]{2}$ |
The 2-letter ISO country code (e.g., NZ) for the delivery address |
Note:
-
Risk fields should always be populated in the request if you have these details for the customer’s payment.
-
These are used by the banks for fraud mitigation.
Idempotency ¶
Create payment intent request is idempotent through the merchantTransactionId supplied in the request. This allows you to replay the request in the event of an unexpected error from our server. A successful response will return a 201 with a paymentId.
Processed Payment Statuses ¶
Status | Description |
---|---|
AUTHORISED | Approved successfully |
DECLINED | Customer declined in bank app or rejected by bank |
EXPIRED | No action from customer within the timeframe allowed |
ERROR | Bank or Worldline unable to process |
Hosted Page Integration ¶
When using the Hosted Page integration, you will only need to redirect your customer to the paymentUrl
received in the response of the create payment intent request.
There, they will be able to complete the payment.
Upon completing the payment the customer will be redirected back to your website through the redirectUrl
supplied in the create payment intent request.
Please refer to Receive Payment Status for how to retrieve the processed payment’s details.
Custom Page Integration ¶
For Custom Page integration you will need to embed the payment plugin in your checkout page.
To render the plugin, you’ll need to use the paymentId
returned from the create payment intent API response. The plugin is loaded into your page via a script tag and mounted to a container element of your choosing.
Embed the Plugin
This section outlines how to embed the plugin, initialise it, and handle key lifecycle events to guide your customer through the payment process.
Update Content Security Policy (CSP)
Ensure seamless integration of the embedded plugin by including the following mandatory Content Security Policy directive in your payment page:
Content-Security-Policy: frame-src *;
Add Target Div and Add JavaScript
Place the following HTML where you want the plugin to render (e.g., checkout form, modal, or sidebar):
<!-- Primary Embed Container (Required) -->
<div id="plugin-container" class="plugin-embed">
<!-- Plugin will load here dynamically -->
</div>
Add the following HTML if you wish to use your own custom Next button:
<button id="nextBtn">Next</button>
Include the plugin script:
<script src="https://open.demo.worldline.co.nz/plugin.js"></script>
Initialise Plugin
Initialize the plugin using a paymentId from the URL and bind the Next button:
Required fields:
-
elementId
(string
):
The ID of the HTML element that will be replaced by the plugin UI. -
paymentId
(string
):
The unique ID returned when creating the payment intent. -
merchantUrl
(string
):
The merchant’s URL - this should match themerchant.url
used when the payment intent was created. -
hasCustomButton
(boolean
):
Set totrue
if you’re providing your own custom button to trigger the plugin’s submission (e.g., a “Next” or “Submit” button). Iffalse
, the plugin will render its own default button.
<script>
window.addEventListener("load", () => {
const nextBtn = document.getElementById("nextBtn");
const divContainer = document.getElementById("divId");
const urlParams = new URLSearchParams(window.location.search);
const paymentId = urlParams.get("paymentId");
const merchantUrl = urlParams.get("merchantUrl");
// ✅ Initialize plugin
window.plugin.init({
elementId: "divId",
paymentId: paymentId,
merchantUrl: merchantUrl,
hasCustomButton: true,
});
// ✅ Submit handler
nextBtn.addEventListener("click", (e) => {
window.plugin.submit(e);
});
});
</script>

Plugin API Reference
Below is a detailed breakdown of the plugin methods and supported configuration parameters.
Always ensure window.plugin
is available before calling any methods.
Method | Description | Example Usage |
---|---|---|
init(config) |
Initializes and embeds the plugin. Accepts config object with parameters listed below. | See Initialise Plugin |
submit(event) |
Triggers payment submission from parent window to plugin. Used when supplying own Next button | See Initialise Plugin |
updatePaymentId(paymentId) |
Updates the plugin by injecting a new paymentId . Use to restart or change transaction in the case of an update to customer cart. |
plugin.updatePaymentId('new-id'); |
getPayment() |
Returns the most recent payment data received from the iframe. | const data = plugin.getPayment(); |
getPaymentStatus() |
Returns the latest known status of the payment. Useful for real-time UI updates. | const status = plugin.getPaymentStatus(); |
Supported init(config)
Parameters
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
elementId |
String | Y | The ID of the element where the plugin will be embedded. | |
paymentId |
String | Y | The paymentId recevied in the response of the create payment intent request. | |
merchantUrl |
String | Y | The URL of the your website where the plugin is embedded — used for verification. | |
hasCustomButton |
Boolean | N | false |
If true, the plugin will not render its own button and you must add your own button and use the submit(event) function |
renderTiles |
Boolean | N | false |
Controls the visibility and layout of bank selection tiles. |
Events
If you’re using the Custom Page integration, your system can listen for payment lifecycle events emitted directly by the plugin. These events notify your application in real time when the payment reaches key states, including when a payment is processed. These notifications allow you to dynamically update the UI to create an optimal customer experience.
Plugin event listening is only available for a Custom Page integration. If you are using a Hosted Page integration, you must use webhook notifications or poll the API.
Considerations
-
Events are useful for internal logic and feedback loops but are not a substitute for verifying the processed payment outcome via webhook notification or polling
-
Ensure your event handlers are resilient to retries, deduplicated, and error-tolerant.
Event Types The plugin emits the following events:
- payment_bank_selector – Triggered when the user interacts with the bank selector.
- payment_input – Triggered when the user enteres mobile number, will return if number is valid or not.
- payment_status – Provides the current status of the payment. The data.status field will contain one of the following:
SUBMITTED
- The payment has been submitted to the customer’s bank app for authorisationAUTHORISED
- The payment has been AUTHORISEDERROR
- An error has occured in the payment processNEW
- Plugin awaiting customer’s payment detailsDECLINED
- The payment was declinedEXPIRED
- The payment expired
Implementation Example (React)
import { useEffect } from "react";
import { useRouter } from "next/router";
import {
PaymentEvent,
PaymentEventType,
PaymentStatus,
} from "./types"; // adjust the import path as needed
const PaymentListener = ({
setPaymentSessionStarted,
setPaymentSubmitted,
setShowPaymentButton,
setShowRestartButton,
setPaymentFailed,
}) => {
const router = useRouter();
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
const message = event.data as PaymentEvent;
if (!message?.event) return;
switch (message.event) {
case PaymentEventType.paymentStatus:
switch (message.data.status) {
case "SUBMITTED":
setPaymentSessionStarted(true);
setPaymentSubmitted(true);
break;
case "AUTHORISED":
if (message.data?.type === "REDIRECT" && message.data.redirectUrl) {
router.push(message.data.redirectUrl);
}
break;
case "EXPIRED":
setShowPaymentButton(false);
setShowRestartButton(true);
break;
case "DECLINED":
case "ERROR":
setPaymentFailed(true);
break;
}
break;
case PaymentEventType.paymentBankSelector:
// Handle bank selector logic here if needed
break;
case PaymentEventType.paymentInput:
// Handle input interaction if needed
break;
default:
break;
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, []);
return null;
};
Receive Payment Status ¶
When a payment reaches a processed state (e.g. AUTHORISED
, DECLINED
, ERROR
, EXPIRED
), your system can be notified or you can retrieve the processed status using the following methods:
-
Webhook Notification (Recommended):
We send a callback to your notificationUrl with a signed JWT containing the payment details. -
GET oe/transactions/v2/payment/{paymentId}:
You can poll our API to check the current status of the payment by its ID.
We recommend webhook notifications as the primary and most secure way to receive real-time status updates, with the other two methods serving as fallbacks or for specific platform needs.
Webhook Notification
This is the main mechanism to rely on for receiving updates about the status of a payment.
Once a payment is processed, we will send an HTTP callback (webhook) to the notificationUrl
you provided when creating the payment intent.
This callback contains a JSON Web Token (JWT) in the body, which includes a claim with the details of the payment (e.g., paymentId, status, transactionTime, etc).
The JWT is digitally signed using our private key to ensure the integrity and authenticity of the callback. You must verify the signature of the JWT using our published JSON Web Key Set (JWKS).
This helps ensure:
-
The message is authentic (sent by Worldline).
-
The contents have not been tampered with.
-
The JWT is valid (not expired, and matches the expected claims).
Download Notification JWT Sample
How to Verify the JWT
- Fetch the JWKS
We publish our public keys at the following endpoint:
https://apitest.paymark.nz/worldlinejwks/OETransaction
Sample response:
{
"keys": [
{
"crv": "P-521",
"kid": "5322fb2d-0580-4122-b23b-5e3055bac347",
"kty": "EC",
"x": "AXbhzIBbyax0GicdVl_HAaJi-b9nkkMDhGmtObXXwx48D_Evnt3G7BVgeU-98L8f1o3u4Olxc-kN-PlrwzH-T5ee",
"y": "AIj6gTTj0Qo9i5f2CA583hjwfjyf6YeZXyWXCY8M_T_hGsQiwGYybB_nC30QN1fgYaePpWY3-iTsgCjQ4B71K6YI"
}
]
}
-
Decode the JWT
Extract the algorithm (alg
) and key ID (kid
) -
Select the Right Public Key
Use thekid
(Key ID) field in the JWT header to find the matching key in the JWKS. You’ll use that key to verify the signature. -
Verify the Signature
Use a JWT library that supports the algorithm. Supply:
-
The raw JWT.
-
The public key from the JWKS.
-
Optionally: expected claims (iss, aud, etc.).
Polling
Polling should only be performed:
-
As a fallback if your notification server is down or delayed as part of your clean up process.
-
For manual status checks, retries, or debugging.
If you decide to poll the API for processed payment status, we recommend the following best practices:
-
Start polling only after the payment has been created and you are awaiting a processed payment.
-
Poll using our recommended strategy else, with exponential backoff or fixed intervals — e.g. every 10 seconds initially, gradually increasing to 20-30 seconds.
-
Stop polling once a final status is received:
AUTHORISED
,DECLINED
,EXPIRED
, orERROR
-
Timeout gracefully after a max polling duration (e.g., 2-5 minutes) to avoid indefinite loops.
-
Respect API rate limits — high-frequency polling could lead to throttling or errors.
Polling should be used sparingly. When possible, rely on webhook notifications as your primary integration path.
Recommended Polling Strategy
To efficiently check for a processed payment status without overloading the system, we recommend the following polling intervals:
-
Start polling 60 seconds after the payment is created.
-
Poll every 10 seconds for the next 60 seconds.
-
Then, poll every 20 seconds for the next 60 seconds.
-
Then, poll every 30 seconds for the next 120 seconds.
-
After that, poll every 45 seconds until a processed payment status is received (
AUTHORISED
,DECLINED
,ERROR
, orEXPIRED
).
Polling via GET /oe/transactions/v2/payments/{paymentId}
You can actively retrieve the latest status of a payment by making a GET request to the payment endpoint using its paymentId
.
Retrieve Payment by paymentId ¶
Headers
Content-Type: application/json
Authorization: Bearer <access_token>
Headers
Content-Type: application/json
Body
{
"merchantTransactionId": "7949fa62-1f2d-40bf-891e-69235491660f",
"paymentId": "2e1e8b06-e892-4474-9ada-4511bf37f4d0",
"integrationMode": "CUSTOM",
"transactionType": "REGULAR",
"status": "AUTHORISED",
"transactionTime": "2025-04-17T02:34:13.833Z",
"lastModifiedTime": "2025-04-17T02:34:20.34Z",
"createdBy": "OEMERCHANT",
"merchant": {
"url": "https://www.bagelandcapers.co.nz/",
"redirectUrl": "https://www.bagelandcapers.co.nz/redirect",
"notificationUrl": "https://bagelandcapers.co.nz/notification",
"merchantId": "300700390"
},
"oepayment": {
"amount": 1500,
"currency": "NZD",
"reference": "PO003288",
"description": "Cat treats"
},
"risk": {
"userAgentInfo": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
"userIpAddress": "114.36.198.162"
}
}
}
GET/oe/transactions/v2/payments/{paymentId}
Retrieve the latest status for a specific payment intent.
- paymentId
string
(required) Example: 2e1e8b06-e892-4474-9ada-4511bf37f4d0
Make a Refund ¶
You can refund a payment using one of two methods:
- Merchant Portal – For manual or customer-service driven refunds.
- Refund API – For programmatic refunds as part of your integration flow.
When issuing a refund, note the following:
-
Refunds are only allowed on payments that have an
AUTHORISED
orREFUNDED
(if payment has been partially refunded) status. -
You can perform full or partial refunds by specifying the amount.
-
The refund request is processed immediately, and the response includes the final result.
-
Refunds will settle overnight into your customers account.
Merchant Portal
The merchant portal provides an easy-to-use interface for initiating refunds without requiring code.
How to Refund
- Log in to the Merchant Portal
- Navigate to the Transactions page.
- Locate and select the payment you want to refund.
- Click Refund and confirm the amount and an optional description.
- Submit the request.
Features:
-
Refund status is tracked in the Merchant Portal.
-
Ideal for manual workflows, customer support, or when you don’t want to handle refunds programmatically.
Refund API
Create Refund ¶
To automate refunds, you can create a refund via the API. This process mirrors how payments are initiated.
Headers
Content-Type: application/json
Authorization: Bearer <access_token>
Body
{
"merchantTransactionId": "bd31893d-bc1a-4a08-9162-b04db9acd709",
"merchant": {
"merchantId": "300700390"
},
"oerefund": {
"refundAmount": 1000,
"description": "",
"originalPaymentId": "bf591254-223b-4c20-9f4a-85eedba4c52d"
},
"risk": {
"userAgentInfo": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
"userIpAddress": "114.36.198.162"
}
}
}
Headers
Content-Type: application/json
Body
{
"merchantTransactionId": "bd31893d-bc1a-4a08-9162-b04db9acd709",
"refundId": "ec456e84-991f-4843-be4f-6989a4c762e6",
"transactionTime": "2025-04-17T02:34:13.833Z",
"lastModifiedTime": "2025-04-17T02:34:20.34Z",
"createdBy": "capers@fluffy.com",
"status": "REFUNDED",
"merchant": {
"merchantId": "300700390"
},
"oerefund": {
"refundAmount": 1000,
"description": "Expired treats",
"originalPaymentId": "bf591254-223b-4c20-9f4a-85eedba4c52d"
},
"risk": {
"userAgentInfo": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
"userIpAddress": "114.36.198.162"
}
}
}
POST/oe/transactions/v2/refunds
Field Definition ¶
Field | Type | Required | Validation | Description |
---|---|---|---|---|
merchantTransactionId | String | Y | UUID | Merchant supplied ID for idempotency |
merchant.merchantId | String | Y | Regex: ^\d{9}$ |
Unique 9 digit number assigned to merchant during onboarding |
oerefund.refundAmount | Integer | Y | amount must be greater than 0 | The amount to be refunded in cents. Must not exceed the original payment amount, taking into consideration any previous partial refunds made against the same payment |
oerefund.description | String | N | Regex: ^[A-Za-z0-9 -.,]{0,100}$ |
Optional internal merchant description of the transaction |
oerefund.originalPaymentId | String | Y | UUID | The paymentId of the payment being refunded |
risk.userAgentInfo.userAgent | String | Y | Regex: ^[\S ]{1,8192}$ |
The raw user agent string of the client making the request. Typically identifies the browser, operating system, and device type |
risk.userAgentInfo.userIpAddress | String | Y | Regex: ^([0-1]?\d?\d|2[0-4]\d|25[0-5])(\.([0-1]?\d?\d|2[0-4]\d|25[0-5])){3}$ |
The public IP address of the end user or device initiating the request. Used for geolocation and fraud analysis |
Idempotency ¶
The create refund request is idempotent through the use of the merchantTransactionId
supplied in the request.
This allows you to replay the create refund request in the event of an unexpected error from our server.
A successful response will return a 201 with the refund response as per the example above.
Processed Refunds Statuses ¶
Status | Description |
---|---|
REFUNDED | Approved successfully |
DECLINED | Rejected by bank |
ERROR | Bank or Worldline unable to process |
Note:
Always configure the correct API version and environment in your integration.
Test Scenarios ¶
Payments ¶
To simulate the payment flow during testing:
- Select any bank.
- Enter a valid New Zealand mobile number.
- Click the Next button.
Use the table below to test different processed payment statuses by submitting the corresponding payment amounts.
Payment Status | ANZ | ASB | BNZ | WESTPAC | COOP |
---|---|---|---|---|---|
AUTHORISED | $3.00 or more | $2.00 or more | $2.30 or more | $1.20 or more | $1.20 or more |
DECLINED | $2.00 | $1.17 | $1.17 | $1.02 | |
EXPIRED | $1.20 | $2.00 | $1.18 | ||
ERROR | $2.20 | $1.40 | $2.10 | $1.08 | $1.04 |
Note:
In Production, your customers will have up to 7 minutes (varies by bank) to action the payment request in their bank app after they click on Next
button.
Refunds ¶
To test successful refunds for any bank, please specify a refund amount that is less than $1.00 or more than $2.00.
Environment URLs ¶
Refer to the table below for configuring your systems to use the desired environments.
URL | Sandbox | Production |
---|---|---|
Merchant Portal | https://portal.demo.worldline.co.nz/ |
https://portal.worldline.co.nz/ |
API | https://apitest.paymark.co.nz/ |
https://api.paymark.nz/ |
Plugin | https://open.demo.worldline.co.nz/plugin.js |
https://open.worldline.co.nz/plugin.js |
JWKS Endpoint | https://apitest.paymark.nz/worldlinejwks/OETransaction |
https://api.paymark.nz/worldlinejwks/OETransaction |
Hosted Page | https://hosted.demo.worldline.co.nz/ |
https://hosted.worldline.co.nz/ |
Merchant Portal Overview ¶
The Merchant Portal is your central dashboard for managing day-to-day payment operations, team access, and account settings. It’s designed to give you visibility and control over transactions, user permissions, and business reporting — all in one place.
Whether you’re a single-store merchant or part of a larger, multi-level organisation, the portal supports flexible account structures and access levels to match your business needs.
User Roles and Access Control
Access to data in the portal is controlled through role-based access control (RBAC). Give your team members the right role so they have the access they need.
Choose the level of access required for individual members based on the hierarchy table below. You may need a more privileged role with less restrictions to change your current role.
Admin Roles
Role | Description | Restrictions |
---|---|---|
Merchant Org Admin | Full access to all portal pages and features. This role is automatically assigned to the portal user created during account registration |
No restrictions - full access |
Merchant Admin | Full access to the Transactions, Users, My Account, and Reporting pages. Can manage most portal functions except those on the Integration page |
Cannot access the Integration page or manage API keys |
View Only Role
Role | Description | Restrictions |
---|---|---|
Merchant Viewer | Read-only access to the Transactions and Reporting pages. Limited access with ability to perform selected non-administrative tasks |
Cannot access the Integration page, make refunds, or manage other users’ information |
Merchant Account Hierarchy
Connect and manage your accounts with support for up to three levels of hierarchy.
If your organisation requires multiple levels of account management — for example, a head office overseeing regional offices, which in turn manage individual stores — a three-level structure may be suitable.
To set up a multi-level account structure, please consult with our sales team.
Hierarchy Levels
Type | Description | Restrictions |
---|---|---|
Root Parent (Top-Level) | Acts as the primary account for the organisation. Can access and manage all linked accounts below it (including Parent and Child accounts). Used for grouping and oversight across the entire account structure. Transactions should generally not be processed directly through this account |
Created during onboarding. Only one Root Parent Account per organisation |
Parent (Mid-Level) | Used for managing a subset of Child accounts, such as regional groups. Can access and manage its linked Child accounts. Not required in all account structures. Transactions should not be processed through this account in a three-level setup |
Must be linked to a Root Parent Account |
Child (Child-Level) | Represents an individual merchant store. This is where transactions are processed. Can operate under either a Root Parent Account (in 2-tier setups) or a Parent Account (in 3-tier setups) |
Must be linked to a Parent or Root Parent Account, depending on the structure. |
Note:
-
A 2-level hierarchy involves a Root Parent (Top-Level) Account and one or more Child-Level Accounts directly beneath it.
-
A 3-level hierarchy introduces Parent (Mid-Level) Accounts to group and manage multiple Child (Child-Level) Accounts.
Creating a New Account To create a new merchant account, please contact our Sales or Support team. They’ll guide you through the setup process and ensure your account is configured correctly.
Updating an Existing Account To update an existing account, reach out to our Support team with the field name(s) and the new information you’d like applied. They’ll assist you with making the necessary changes.
Portal Pages and Functions
Use the navigation menu to access key sections of the merchant portal. Each page provides specific capabilities based on user roles.
Navigation Menu
Page | Description | Role Restrictions |
---|---|---|
Integration | Manage API credentials for system integration | Not accessible to Merchant Admin and Merchant Viewer |
Transactions | View or search transactions, or make a refund | Merchant Viewer can view but cannot refund |
Users | Create, view, or manage portal user accounts | Not accessible to Merchant Viewer |
My Account | View your Online EFTPOS account details | Not accessible to Merchant Viewer |
My Profile | View or update your portal user settings, including password reset | No restrictions |
Reporting | Generate and download transaction or settlement history reports | No restrictions |
Go Live ¶
Go-Live Checklist
Below checklist is designed to assist in preparing your production integration to be ready for use by your customers. Perform these checks as your Go Live readiness check
-
Production Account Configured
-
Integration Completed
reference
field (max 12 characters) is unique to serve as an additional identifier to distinguish individual payments within your system.
-
Payment Status Handling
-
Refund Support
-
Testing Complete
AUTHORISED
,DECLINED
,EXPIRED
,ERROR
).
-
Ready for Production
Generated by aglio on 12 Jun 2025