PayUI Tokenisation
PayUI supports secure payment instrument tokenisation, enabling you to store customer payment instruments for future transactions while maintaining PCI compliance. This guide explains how to create and manage tokenised payment instruments during the payment flow, with customer consent.
Overview
Tokenisation allows you to capture customer’s payment details. PayUI captures the customer’s payment instrument information, creates a customer record and payment instrument on your behalf, and returns resource identifiers you can use for subsequent transactions.
Tokenisation occurs transparently within the PayUI iframe — your application never handles raw card data, reducing PCI scope while still giving you the ability to process future recurring or customer-initiated transactions.
How It Works
When you include customerRequest in your Payment Request with paymentInstrument: create, PayUI will:
- Collect payment instruments details from the customer in the secure iframe
- Capture the payment instrument and process the transaction
- Return the transaction and customer and payment instrument identifiers in
customerResultin the transaction response
The customer and payment instrument are created only when paymentInstrument: create is explicitly provided.
Integration Steps
Step 1: Create Payment Request with CustomerRequest
Include customerRequest in your Payment Request creation call when you want to tokenise the customer’s card.
Endpoint: POST /paymentrequests
Request with New Customer (tokenisation):
{ "reference": "ORDER-2026-001", "payment": { "amount": 5000, "currencyCode": "AUD", "description": "Subscription - Premium Plan" }, "paymentMethods": ["card", "google_pay", "apple_pay"], "transactionRequest": { "category": { "frequency": "single", "captureType": "auto" } }, "customerRequest": { "paymentInstrument": "create", "name": "Jane Doe", "email": "jane.doe@example.com" }}Request without paymentInstrument action (no tokenisation):
If the paymentInstrument is omitted, no payment instrument is created:
{ "reference": "ORDER-2026-002", "payment": { "amount": 2500, "currencyCode": "AUD", "description": "One-time purchase" }, "paymentMethods": ["card"], "transactionRequest": { "category": { "frequency": "single", "captureType": "auto" } }, "customerRequest": { "name": "Jane Doe", "email": "jane.doe@example.com" }}Response (excerpt):
{ "id": "zWIEEs6BBU2A3GUQ8gD3Ag", "reference": "ORDER-2026-001", "createdDateTime": "2026-02-09T10:15:00Z", "paymentRequestStatus": "created"}Step 2: Generate One-Time Token
Generate a one-time token as normal for PayUI integration:
Endpoint: POST /tokens
{ "scope": "payui", "paymentRequestId": "zWIEEs6BBU2A3GUQ8gD3Ag"}Step 3: Initialise PayUI
Initialise PayUI with the one-time token. The tokenisation happens automatically when the customer completes payment:
const config = { token: "your-one-time-token", containerId: "payment-container", version: "1.0.0"};
const payUI = GPAUNZ.PayUI.initialise(config);
payUI.on('process', (payload) => { if (payload.result.status === 'approved') { console.log('Payment approved. Transaction ID:', payload.transactionId); }});Step 4: Retrieve Tokenisation Result
After a transaction, retrieve the customerResult containing the customer and payment instrument identifiers.
Webhooks (Recommended)
If subsrcribed to the payment_requests webhooks, listen for payment request webhooks to capture the final state with customerResult:
{ "id": "zWIEEs6BBU2A3GUQ8gD3Ag", "eventType": "payment_requests", "created" : "2026-01-27T06:26:02Z", "version": "1.0.0", "payload" : { "id": "szh-Ib8xP0S_sJZn8xD8yQ", "reference": "ORDER-723-669-1900", "createdDateTime": "2026-01-27T06:25:59Z", "updatedDateTime": "2026-01-27T06:26:43Z", "expiryDateTime": "2026-01-29T06:25:59Z", "paymentRequestStatus": "completed", "transactionResult": { "id": "Iank9maLpkuwlQWGJ4rYcw", "location": "https://api.gpaunz.com/transactions/Iank9maLpkuwlQWGJ4rYcw" }, "customerResult": { "id": "Iank9maLpkuwlQWGJ4rYcw", "location": "https://api.gpaunz.com/customers/Iank9maLpkuwlQWGJ4rYcw", "paymentInstrumentId": "JMFEgR2z5EGL7GF7lAcFxA", "paymentInstrumentLocation": "https://api.gpaunz.com/customers/Iank9maLpkuwlQWGJ4rYcw/paymentinstruments/JMFEgR2z5EGL7GF7lAcFxA" }, "payment": { "description": "i'm a description", "amount": 100, "currencyCode": "AUD" }, "paymentMethods": [ "card" ], "result": { "mode": "sandbox", "status": "ok" } }}Store the customerResult.id and customerResult.paymentInstrumentId in your database to use for future transactions.
Tokenisation Flow (Sequence Diagram)
This diagram illustrates the complete tokenisation flow from Payment Request creation through to customer and payment instrument creation:
sequenceDiagram
autonumber
participant FrontEnd
participant Merchant Server
participant Single API
participant PayUI
FrontEnd->>Merchant Server: Request payment page
Merchant Server->>Single API: POST /paymentrequests
Single API-->>Merchant Server: Payment Request ID
Merchant Server->>Single API: POST /tokens (scope=payui and paymentrequestid)
Single API-->>Merchant Server: One-Time Token (OTT)
Merchant Server-->>FrontEnd: Render page with token
FrontEnd->>PayUI: Load payui.js
FrontEnd->>PayUI: GPAUNZ.PayUI.initialise(OTT)
PayUI-->>FrontEnd: Render iframe + emit 'initialise'
FrontEnd->>FrontEnd: User enters card details
PayUI-->>FrontEnd: Emit 'surchargeUpdate' (if enabled)
FrontEnd->>PayUI: User clicks Pay Now
PayUI->>Single API: POST /customers<br/>(name, email from customerRequest)
PayUI->>Single API: POST /customers/{id}/paymentinstruments<br/>(card token from PayUI)
Single API->>PayUI: Return customer and payment instrument
PayUI->>Single API: Create transaction with customer and payment instrument
Single API-->>PayUI: Transaction Result and <br/> PaymentRequest state change
Single API-->>FrontEnd: Emit 'process' event
FrontEnd->>FrontEnd: Display Processing Result
Single API-->>Merchant Server: Transaction Webhook
Single API-->>Merchant Server: Payment Request Webhook
CustomerRequest Properties
The customerRequest object controls tokenisation behaviour:
| Property | Type | Required | Description |
|---|---|---|---|
paymentInstrument | string | No | Set to "create" to create a payment instrument. If omitted, no payment instrument is created. |
name | string | No | Customer name. Cannot be used with id. Optional when creating a new customer. |
email | string | No | Customer email. Cannot be used with id. Optional when creating a new customer. |
CustomerResult Properties
When tokenisation succeeds, customerResult is populated in the Payment Request response:
| Property | Type | Description |
|---|---|---|
id | string | The unique customer identifier. |
location | string | The full URL to the customer resource. |
paymentInstrumentId | string | The unique payment instrument identifier. |
paymentInstrumentLocation | string | The full URL to the payment instrument resource. |
Validation Rules
PayUI validates customerRequest to ensure data consistency:
Identity Rules
- Creating a new customer:
When creating a new customer, you can providenameoremail, both optional but recommended. The name can be completed from the PayUi form or else it will be defaulted to VALUED CARDHOLDER.
Payment Instrument Creation
-
Explicit opt-in required:
Payment instruments are only created whenpaymentInstrument: createis explicitly included incustomerRequest. -
Without
paymentInstrument: create:
If you omitpaymentInstrumentor set it to any other value, no payment instrument will be created.
Example Validation Errors
Validation errors
| Code | Message | Reason |
|---|---|---|
| V10214 | payment_request_customer_id_invalid | the provided customer id is invalid |
| V10215 | payment_request_customer_email_invalid | The email is either invalid format (valid email, lenght) or was provided in conjuction with id |
| V10216 | payment_request_customer_name_invalid | The customer name is either an invalid format or was provided in conjuction with id |
| V10219 | payment_request_customer_paymentinstrument_invalid | payment instrument action is one of the allowed values |
Using Tokenised Payment Instruments
Once you have stored the customer ID and payment instrument ID, you can use them for future transactions via the standard Transactions API:
Endpoint: POST /transactions
{ "reference": "RECURRING-2026-001", "category": { "origin": "internet", "frequency": "recurring", "captureType": "auto" }, "payment": { "amount": 5000, "currencyCode": "AUD", "instrument": { "customer": { "id": "e945e8vh0a9szsxig9pohvs9i3lrmw", "paymentInstrumentId": "JMFEgR2z5EGL7GF7lAcFxA", "cvn": "123" } } }}Note: Including
cvnfor recurring transactions may improve approval rates and is recommended when available.
Managing Tokenised Instruments
You can manage customer and payment instrument records using the standard API endpoints:
- Retrieve a customer:
GET /customers/{customerId} - Update a customer:
PUT /customers/{customerId} - List payment instruments:
GET /customers/{customerId}/paymentinstruments - Retrieve a payment instrument:
GET /customers/{customerId}/paymentinstruments/{paymentInstrumentId} - Update a payment instrument:
PUT /customers/{customerId}/paymentinstruments/{paymentInstrumentId} - Delete a payment instrument:
DELETE /customers/{customerId}/paymentinstruments/{paymentInstrumentId}
For complete documentation on customer and payment instrument management, see the API reference.
Apple Pay Long-Lived Token with Agreement Details
When tokenising an Apple Pay payment instrument, you can include agreementDetails in the Payment Request to establish a long-lived token. This is suitable for subscriptions, or recurring billing, where the customer agrees upfront to ongoing charges.
The agreementDetails object defines the terms of the recurring arrangement, including billing frequency, duration, and a management URL where the customer can view or cancel the agreement. Apple Pay uses these details to generate a long-lived payment token tied to the agreement, allowing you to process future charges without requiring customer interaction each time.
Apple Pay and Google Pay can be used for tokenisation without providing agreementDetails. The agreement details are not mandatory and are only needed when you want to set up a long-lived token for automatic, repeat charges. If you simply want to tokenise the payment instrument for future merchant-initiated transactions, include apple_pay or google_pay in paymentMethods alongside customerRequest with paymentInstrument: create and category.frequncy as recurring, as shown in the examples above.
AgreementDetails Properties
| Property | Type | Required | Description |
|---|---|---|---|
frequency | string | No | Billing frequency. Must be one of: daily, monthly, annual when provided. |
frequencyCount | integer | No | Number of billing cycles. Must be greater than 0 when provided. |
description | string | Yes | A description of the recurring arrangement shown to the customer. Maximum 140 characters. |
startDate | string | No | Start date in yyyy-MM-dd format. Defaults to today if not provided. |
endDate | string | No | End date in yyyy-MM-dd format. |
amount | integer | No | The recurring charge amount in the lowest denomination (e.g. cents). Defaults to 0 if not provided. |
managementURL | string | Yes | A URL where the customer can manage or cancel the agreement. |
billingAgreement | string | No | A customer-facing summary of the billing terms. Maximum 140 characters. |
Example: Payment Request with Agreement Details
{ "reference": "SUB-2026-001", "payment": { "amount": 4000, "currencyCode": "AUD", "description": "Monthly Subscription" }, "paymentMethods": ["apple_pay"], "transactionRequest": { "category": { "frequency": "single", "captureType": "auto" } }, "customerRequest": { "paymentInstrument": "create", "name": "Jane Doe", "email": "jane.doe@example.com" }, "agreementDetails": { "frequency": "monthly", "frequencyCount": 12, "description": "Monthly Subscription", "startDate": "2026-05-10", "endDate": "2026-10-10", "amount": 4000, "managementURL": "https://merchant.example.com/manage", "billingAgreement": "You will be charged each month until you cancel." }}Best Practices
Testing
Test tokenisation in the sandbox environment:
- Create a Payment Request with
customerRequestincludingpaymentInstrument: create - Complete the payment using sandbox test card numbers
- Verify
customerResultis populated with customer and payment instrument IDs - Test subsequent transactions using the tokenised payment instrument
For sandbox card numbers and testing scenarios, see Testing Introduction.
Troubleshooting
customerResult is null or missing when trying to tokenise
- Verify
paymentInstrument: createwas included incustomerRequest
Payment instrument not created
- Ensure
paymentInstrument: createis explicitly included incustomerRequest - Omitting this field or using any other value will prevent payment instrument creation
Subsequent transactions fail with tokenised instrument
- Verify the
customerIdandpaymentInstrumentIdare correct - Check that
frequency: recurringis set for recurring transactions - Include
cvnwhen available to improve approval rates