Online EFTPOS Integration Guide

Introduction

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:

  1. Generate API Key and Secret
    Generate your API key and secret from the Merchant Portal.

  2. Authenticate API Requests
    Use your API credentials to authenticate requests via HTTP Bearer Authentication.

  3. Create a Payment Intent
    Initiate a payment by calling the create payment intent API endpoint.

  4. Integrate using either:

  5. Receive Payment Status
    Confirm payment completion using webhook notifications or by querying the payment status.

  6. How to Make a Refund
    Refund a payment through the API or directly in the merchant portal.

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

  1. 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.

  1. Request a Bearer Token
    Make a POST request to the token endpoint using the Basic Authorization Token in the Authorization header, and include grant_type=client_credentials in the request body.

Obtain Bearer Token

POST https://apitest.paymark.co.nz/bearer
Requestsexample 1
Headers
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64-encoded APIKey:APISecret>
Body
grant_type=client_credentials
Responses200
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

POST https://apitest.paymark.co.nz/oe/transactions/v2/payments/create-intent
Requestsexample 1
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"
  }
}
Responses201
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 the merchant.url used when the payment intent was created.

  • hasCustomButton (boolean):
    Set to true if you’re providing your own custom button to trigger the plugin’s submission (e.g., a “Next” or “Submit” button). If false, 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:

  1. payment_bank_selector – Triggered when the user interacts with the bank selector.
  2. payment_input – Triggered when the user enteres mobile number, will return if number is valid or not.
  3. 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 authorisation
    • AUTHORISED - The payment has been AUTHORISED
    • ERROR - An error has occured in the payment process
    • NEW - Plugin awaiting customer’s payment details
    • DECLINED - The payment was declined
    • EXPIRED - 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:

  1. Webhook Notification (Recommended):
    We send a callback to your notificationUrl with a signed JWT containing the payment details.

  2. 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

  1. 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"
    }
  ]
}
  1. Decode the JWT
    Extract the algorithm (alg) and key ID (kid)

  2. Select the Right Public Key
    Use the kid (Key ID) field in the JWT header to find the matching key in the JWKS. You’ll use that key to verify the signature.

  3. 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, or ERROR
  • 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, or EXPIRED).

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

GET https://apitest.paymark.co.nz/oe/transactions/v2/payments/2e1e8b06-e892-4474-9ada-4511bf37f4d0
Requestsexample 1
Headers
Content-Type: application/json
Authorization: Bearer <access_token>
Responses200
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.

URI Parameters
HideShow
paymentId
string (required) Example: 2e1e8b06-e892-4474-9ada-4511bf37f4d0

Make a Refund

You can refund a payment using one of two methods:

  1. Merchant Portal – For manual or customer-service driven refunds.
  2. 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 or REFUNDED (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

  1. Log in to the Merchant Portal
  2. Navigate to the Transactions page.
  3. Locate and select the payment you want to refund.
  4. Click Refund and confirm the amount and an optional description.
  5. 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.

POST https://apitest.paymark.co.nz/oe/transactions/v2/refunds
Requestsexample 1
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"
    }
  }
}
Responses201
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:

  1. Select any bank.
  2. Enter a valid New Zealand mobile number.
  3. 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