Pay by Link is Token.io's flexible solution for fast, secure account-to-account payments. Merchants, banks, and third-party providers can generate unique payment links to share with customers via email, SMS, messaging apps, or QR codes. These links pre-fill recipient account details, making payments easier and reducing manual errors. Customers can pay remotely or in person, with a seamless experience on Token.io's hosted payment pages.
- Flexible Payment Links: Generate links with or without pre-filled amount and reference. The payer can enter missing details if needed.
- Reusable Payment Links: Generate links with maximum usage count, per-payment amount limits and total limits.
- Custom Branding: Landing pages can be customised with your own logo, colours, field labels and error descriptions.
- Bespoke Validity: Set how long a link is valid for or leave open-ended.
- Status Tracking: Easily check if a link is active, expired, cancelled or unavailable due to restriction limits.
- API-First: All features are available via Token.io's API. See the Token Open Banking API.
- Create a Payment Link: A unique link is generated by the requester.
- Share the Link: The PSU / Merchant shares the link via SMS, email, chat, or invoice.
- Customer Pays: The receiver clicks the link and authenticates in their own banking app.
- Receive Payment Updates: The payment moves instantly, account-to-account, with no need for card details or sort codes. The payer is immediately notified on the confirmation page once the payment is completed. After this, the third-party provider or merchant receives a real-time notification (such as a webhook or API callback) confirming the payment status.
1. Peer-to-Peer (P2P) Payments
Pay by Link enables individuals to transfer money directly between accounts without the need to share sort codes or IBANs.
Common use cases include:
- Splitting bills: Share a payment link to quickly settle expenses such as dinner, rent, or group activities.
- Personal reimbursements: Repay friends or family securely without exchanging bank details.
- Gifting: Send money instantly through a secure and personalised payment link.
- One-off transfers: Provide a simple alternative to manually entering account details.
2. Online Orders Without a Checkout
An eCommerce store empowers small online stores to sell directly through chat or social media using Pay by Link, eliminating the need for a full e-commerce checkout.
Example flow:
- eCommerce store: Creates a Pay by Link for each order, including the item, price, and expiry time. The link opens a secure, branded payment page.
- Seller: Shares the payment link with the customer and receives instant confirmation once payment is complete.
- Customer: Clicks the link, pays using their preferred bank, and receives immediate order confirmation.
3. In-Store Reusable Link for Merchants
A small business owner selling goods uses Pay by Link to collect in-person payments.
Example flow:
- Business owner generates a reuseable payment link and displays it as a QR code at the checkout counter.
- Customers scan the code using their mobile device, review or enter the payment amount, and confirm payment through their mobile banking app.
- Business owner receives instant notification once the payment is successfully processed.
- QR code image can be generated via a dedicated endpoint
GET /qr-codeif required - QR code is returned in 240x240px as an embedded string format (SVG)
More can be found in the QR code API spec.
In Pay by Link, link status indicates whether a payment link is currently usable and, if not, why it’s no longer available. Links can be active, expired, or canceled, and they may also become unavailable when a configured usage limit or amount limit has been reached. These statuses help customers understand the current state of a link and guide when a new link needs to be created.
| Status | Name |
|---|---|
LINK_ACTIVE | The payment link is active. |
LINK_EXPIRED | The payment link has expired. |
LINK_CANCELED | The payment link has been canceled. |
USAGE_LIMIT_REACHED | Maximum usage count reached. |
AMOUNT_LIMIT_REACHED | Total amount limit reached. |
For Payment Links to align with existing payments functionality, an enhancement has been added to manage the generation of a unique refId for each payment under a given link.
Unlike in POST /v2/payments where the refid has a limit of 18 character, for Payment Links this will now be limited to 13 characters. This client-provided value will be treated as the base refId for all payments initiated from that link. For each individual payment created from the Payment Link, Token will generate a unique refId by appending an incrementing suffix to the base value.
For example:
- TPP provided base refId: ORDER-ABC
- First payment created: ORDER-ABC-1
- Second payment created: ORDER-ABC-2
- Third payment created: ORDER-ABC-3, and so on.
To support this behaviour and ensure compatibility across payment rails:
- The client-provided base
refIdis limited to 13 characters - Allowed characters are alphanumeric characters and hyphens (-)
- Token will append a hyphen delimiter plus 4-character incrementing suffix, and incremented using IDs generated using Base62 i.e. -1 --> -ZZZZ
- The final
refId, including the suffix added by Token, will have a maximum length of 18 characters.
PLEASE NOTE: That the refId value must be globally unique across both the Payments v2 and Pay by Link endpoints.
For example:
- Creating a payment via Payments v2 with refId = ORDER-123-1
- And later creating a Payment Link with a base refId = ORDER-123-1 would result in a collision and is not supported. Distinct base refId should be used for each flow to avoid this.
The suffix uses a Base62 character set (0-9, A-Z, a-z) and can grow from 1 to 4 characters in length as required. This approach was chosen to maximise the number of unique payment references that can be generated from a single Payment Link while keeping the overall reference concise and human-readable.
Using Base62 encoding provides a significantly larger number of unique combinations than a numeric-only sequence for the same character length. A 4-character Base62 suffix supports over 14.7 million unique values, allowing a single Payment Link to be reused a very large number of times before the available reference space is exhausted.
The variable-length format also ensures that shorter suffixes are used initially, helping to keep payment references as compact as possible while still supporting future growth.
| Number of payment under a link | RefId suffix Range | Number of Characters |
|---|---|---|
| 0 – 61 | 0 – z | 1 |
| 62 – 3,843 | 10 – zz | 2 |
| 3,844 – 238,327 | 100 – zzz | 3 |
| 238,328 – 14,776,335 | 1000 – zzzz | 4 |
| Number of payment under a link | RefId suffix |
|---|---|
| 1 | 1 |
| 9 | 9 |
| 10 | A |
| 35 | Z |
| 36 | a |
| 61 | z |
| 62 | 10 |
| 63 | 11 |
| 3,843 | zz |
| 3,844 | 100 |
| 238,327 | zzz |
| 238,328 | 1000 |
| 10,000,000 | FXsk * |
| 14,776,335 | zzzz |
- Please check note in Link Configuration Parameter regarding "max_usage"
A reusable payment links can support multiple payments with configurable controls, including: per-payment amount limits, cumulative total link limits, and maximum usage/expiry behaviours. The platform exposes visibility of link configuration and status via the GET/payment-links API - supporting tracking, reporting, and compliance needs for TPPs.
| Parameters | Description | Request |
|---|---|---|
| Maximum usage count | Defines how many times the reusable link can be used e.g. "100". 'Usage' is defined as a redirection to the bank. | |
| Point to note - The current maximum number of payments for a single payment link is 10,000,000 payments. This will be the case when "max_usage" is not specified when creating the link. | "max_usage_count": 100 | |
| Per-payment limit | Defines the maximum payment limit per payment on a specific link e.g. £500. Currency is dictated by the payment template. | "per_payment_amount_limit": "500.00" |
| Total amount per link | Define the total amount of money receivable by a single link e.g. £1000. Currency is dictated by the payment template. | "totalAmountLimit": "1000.00" |
| Link expiry | Defines a time where a specific link will expire e.g. 2025-02-27T10:28:07.160Z | "expires_at": "2025-02-27T10:28:07.160Z" |

Endpoint: POST v2/payment-links
- Create a payment link by providing payment template information and any link config
Example Request:
{
"linkConfig": {
"maxUsageCount": 1000,
"perPaymentAmountLimit": "500.00",
"totalAmountLimit": "20000.00"
},
"paymentTemplate": {
"refId": "{{C_REFID}}",
"amount": {
"currency": "GBP"
},
"creditor": {
"name": "Dana Creditor",
"accountNumber": "543512",
"sortCode": "123312"
},
"localInstrument": "FASTER_PAYMENTS"
}
}Example Response:
{
"paymentLink": {
"id": "pl-019d4862-21dd-77ad-851c-b615fd587e3e",
"status": "LINK_ACTIVE",
"createdAt": "2026-04-01T09:31:23.997748Z",
"paymentTemplate": {
"id": "pt-019d4862-21db-71ac-a6a2-45f3870dacfd",
"amount": {
"currency": "GBP"
},
"localInstrument": "FASTER_PAYMENTS",
"creditor": {
"name": "Dana Creditor",
"sortCode": "123312",
"accountNumber": "543512"
},
"refId": "1775035882"
},
"linkConfig": {
"maxUsageCount": 1000,
"perPaymentAmountLimit": "500.00",
"totalAmountLimit": "20000.00"
},
"url": "https://app.sandbox.token.io/pay-by-link/pl-019d4862-21dd-77ad-851c-b615fd587e3e",
"currentUsage": {
"remainingCount": 1000,
"remainingAmount": "20000.00"
},
"memberId": "m:R7mNpQ2wXcBv4Ls123y8FhKn3EgU:9aWmKpZx"
}
}Endpoint: GET /v2/payment-links/{id}
- Get a payment link based on the ID
Endpoint: GET /v2/payment-links
- Supports query parameters below as part of the GET request. NOTE: At least one filter must be provided.
| Query Parameter | Description |
|---|---|
paymentLinkId | Filter by a specific payment link ID |
status | Filter by payment link status |
createdAfter | Return links created after this timestamp |
createdBefore | Return links created before this timestamp |
expiresAfter | Return links expiring after this timestamp |
expiresBefore | Return links expiring before this timestamp |
externalPsuReference | Filter by the external PSU reference |
onBehalfOfId | Filter by the acting entity ID (where applicable) |
Example Response:
{
"paymentLink": {
"id": "pl-019d4560-aa5e-7f96-9c50-c9c86b521f54",
"status": "LINK_ACTIVE",
"createdAt": "2026-03-31T19:30:56.223122Z",
"paymentTemplate": {
"id": "pt-019d4560-aa5b-754c-a96a-fd1c6d743b43",
"amount": {
"currency": "EUR"
},
"localInstrument": "FASTER_PAYMENTS",
"creditor": {
"name": "Dana Creditor",
"sortCode": "123312",
"accountNumber": "543512"
},
"refId": "1774985456",
"risk": {}
},
"linkConfig": {
"maxUsageCount": 1000,
"perPaymentAmountLimit": "500.00",
"totalAmountLimit": "20000.00"
},
"url": "https://app.sandbox.token.io/pay-by-link/pl-019d4560-aa5e-7f96-9c50-c9c86b521f54",
"currentUsage": {
"remainingCount": 1000,
"remainingAmount": "20000.00"
},
"memberId": "m:R7mNpQ2wXcBv4LsJdTy8FhKn3EgU:9aWmKpZx"
}
}To get a list of payments that have been initiated from a given link, you can do so by using the following request
Endpoint: GET /v2/payments?paymentLinkId={paymentLinkId}
This will return a list of payment attributed to a link.
Endpoint: DELETE /v2/payment-links/{id}
- Cancel an active payment link
PLEASE NOTE: The ability to cancel a link is dependent on the status of the payment link. To highlight this, the response from the endpoint will differ accordingly.
Possible outcomes
- If the link already has
LINK_CANCELEDorLINK_ACTIVE- the response will be a200 OK - If the link has a different status - the response will be a
409 Conflictwith an additional error message to highlight the reason why it can not be cancelled.
{
"paymentLink": {
"id": "pl-019d4560-aa5e-7f96-9c50-c9c86b521f54",
"status": "LINK_CANCELED",
"createdAt": "2026-03-31T19:30:56.223122Z",
"paymentTemplate": {
"id": "pt-019d4560-aa5b-754c-a96a-fd1c6d743b43",
"amount": {
"currency": "EUR"
},
"localInstrument": "FASTER_PAYMENTS",
"creditor": {
"name": "Dana Creditor",
"sortCode": "123312",
"accountNumber": "543512"
},
"refId": "1774985456",
"risk": {}
},
"linkConfig": {
"maxUsageCount": 1000,
"perPaymentAmountLimit": "500.00",
"totalAmountLimit": "20000.00"
},
"url": "https://app.sandbox.token.io/pay-by-link/pl-019d4560-aa5e-7f96-9c50-c9c86b521f54",
"currentUsage": {
"remainingCount": 1000,
"remainingAmount": "20000.00"
},
"memberId": "m:R7mNpQ2wXcBv4LsJdTy8FhKn3EgU:9aWmKpZx"
}
}- Logo: Upload your company logo to appear on the Pay by Link payment page. The logo can be inherited from your existing WAV2 configuration or uploaded specifically for Pay by Link. Supported formats include PNG, JPG, and JPEG, with size and dimension guidelines to ensure optimal display.
- Logo Alt Text: Add descriptive alt text for your logo to improve accessibility for users with screen readers.
- Primary Colour: Set your brand’s primary colour, which will be used for key UI elements (such as buttons and highlights) on the payment page.
- Favicon: Upload a custom favicon to appear in the browser tab when customers open your payment link.
- Custom Field Names: Change the labels for key fields such as “Amount” and “Reference” to match your business terminology (e.g., “Total,” “Order Number,” etc.).
- Header Text: Customise the welcome or header message displayed at the top of the payment page (e.g., “Welcome to [Your Brand] Pay by Link”).
- Instructional Text: Add or edit instructional or informational text to guide your customers through the payment process.
- PDF Download Option: Enable or disable the option for customers to download a PDF receipt of their payment directly from the confirmation page.
- Alt Text for Images: Ensure all uploaded images (logos, favicons) have descriptive alt text for accessibility.
These customisation options are managed directly from the Pay by Link configuration section in your Dashboard, allowing you to update branding, text, and features without any code changes.
- Review the API reference for integration details.
- For more on integrating with other Token.io features, visit our developer documentation.
If you have any feedback about the developer documentation, please contact devdocs@token.io