Changelog

Welcome to the Changelog, your go-to resource for staying informed about the latest updates and improvements to our APIs.

TBD, 2026 - New Feature

Pay at Table: /poslink/v1/tabs endpoints

Added a new set of endpoints under /poslink/v1/tabs that let ePOS applications register tables (or open orders) with PosLink, list and inspect them, respond to terminal-initiated bill and payment requests, and close them once payment is complete.

Key endpoints (ePOS-facing):

  • POST /poslink/v1/tabs: open a tab. Body: { "tab_id", "tab_name", "currency" }. tab_id is an ePOS-chosen identifier; tab_name is the display label (e.g. "Patio 3") shown on the terminal's open-tabs screen; currency is the ISO 4217 code all payments on the tab must use.
  • GET /poslink/v1/tabs: paginated list of tabs. Query: statuses=OPEN,PAYING,PAUSED,COMPLETED,CLOSED (defaults to active statuses), after/before (opaque cursors), limit.
  • GET /poslink/v1/tabs/{tab_id}: full tab detail including line items, payment requests, and the bill file id.
  • DELETE /poslink/v1/tabs/{tab_id}: close a tab. PosLink also auto-closes tabs that have had no activity for 24 hours.

Terminal-initiated event stream (Server-Sent Events):

  • GET /poslink/v1/tabs/events: SSE stream for the linked store. Notifies the ePOS of SHOW_BILL_REQUEST, PAY_REQUEST, TAB_PAYMENT_STATUS_PROGRESS, TAB_PAYMENT_COMPLETED, TAB_PAUSED, TAB_RESUMED, TAB_COMPLETED, TAB_BILL_HIDDEN, and connection state changes triggered by terminals against any open tab.

ePOS response endpoints (in reply to events):

  • POST /poslink/v1/tabs/{tab_id}/bill: respond to a SHOW_BILL_REQUEST event with the bill total, plus an optional print_model or tab_item_data (application/json), or a pre-rendered bill image (multipart/form-data, maximum 200 KB per image and 220 KB per request; exceeding either returns 413 PAYLOAD_TOO_LARGE with code BILL_IMAGE_TOO_LARGE).
  • POST /poslink/v1/tabs/{tab_id}/errors: reject a terminal-initiated request with an error code.

Pay-at-Table response on existing payment endpoint:

  • POST /poslink/v3/payment-requests now accepts tab_id, payment_type (FULL or SPLIT) and payment_method (CARD or CASH) in the request body. Send them to settle a tab, fully or partially, in response to a PAY_REQUEST event; leave them out for regular payments. payment_type is required whenever tab_id is present. The payment is tagged against the tab and surfaces under GET /poslink/v1/tabs/{tab_id} as a PaymentRequestSummary.

Store-level enablement:

  • PUT /poslink/v1/stores/{store_id}/configs/PAT_ENABLED accepts { "value": "true" } to toggle PAT for the store. Store-wide capability flag; per-terminal opt-out is local to each terminal. Disabling is an entry-point gate only; in-progress sessions run to completion.

Action Required

No action required for existing integrations. Pay at Table is opt-in: partners that don't call the tab endpoints see no change.

For partners adopting PAT:

  1. Enable PAT at the store level via PUT /poslink/v1/stores/{store_id}/configs/PAT_ENABLED.
  2. Open a tab when a table is seated or an order is opened (POST /poslink/v1/tabs).
  3. Subscribe to /poslink/v1/tabs/events to receive terminal-initiated bill and payment requests.
  4. Respond to SHOW_BILL_REQUEST events with the bill, and to PAY_REQUEST events by creating a payment with tab_id and payment_type.
  5. Close the tab when fully paid (DELETE /poslink/v1/tabs/{tab_id}).

See the Pay at Table integration guide (Android) for the end-to-end flow and code samples. iOS and Windows guides ship alongside their respective SDK releases.

The Unified ePOS SDK v1.6.0 (Android, iOS, Windows) wraps these endpoints in a callback-based `PosLinkTabsApi`. Most partners should integrate via the SDK rather than calling the REST endpoints directly. The SDK handles the SSE stream lifecycle, reconnection with exponential backoff, and tab id ↔ terminal-side id mapping.

Nov 11, 2026 - Enhancement

More error responses documented

The reference now documents these error responses, with example bodies:

  • POST /poslink/v3/payment-requests, 409: IDEMPOTENCY_KEY_REUSED when the Idempotency-Key was already used with a different body, and LOCAL_PAYMENT_REQUEST_MISMATCH when local_payment_request_id or the Idempotency-Key belongs to another payment.
  • POST /poslink/v3/payment-requests, 422: INVALID_TAB_REQUEST when the request is not valid for a tab, for example transaction_type REFUND sent with a tab_id, with the rejected field in invalid_params; and LOCAL_PAYMENT_REQUEST_INVALID when local_payment_request_id is sent for a refund or a payment on a tab.
  • POST /poslink/v1/epos/register, 409: STORE_CREDENTIALS_REMOVED when the partner's credentials for the store have been removed.
  • The /poslink/v1/tabs/{tab_id} endpoints, 404: TAB_NOT_FOUND when no tab exists for the given tab_id.

The Errors section of the reference also lists every error code documented for each status, with its example.

Action Required

None.

Nov 10, 2026 - Bug Fix

V2 Refunds: No 202 Response

The API reference listed a 202 "Refund is being processed asynchronously" response for POST /poslink/v2/refunds. This endpoint never returns 202. It has been removed from the reference.

A refund can still come back without a final result:

  • 201 with status PENDING
  • 400 with code UNKNOWN, which can mean a refund with the same Idempotency-Key is still being processed

There is no endpoint to fetch a refund later. In both cases, repeat the same request with the same Idempotency-Key and body. The repeated request returns the stored refund instead of creating a new one.

Action Required

Always send an Idempotency-Key on POST /poslink/v2/refunds, and handle PENDING and 400 UNKNOWN by repeating the request with the same key. Without a key, every request creates a new refund.

No API behaviour changed. This entry corrects the documentation only.

See Refunds in the API reference and Make a refund.

Nov 9, 2026 - New Feature

Terminal Names: GET /poslink/v2/stores/{store_id}/terminals

Added a new version of the terminal listing that returns each terminal's actual name, and its device model in a separate field.

What changes from V1:

  • terminal_name now returns the name of the terminal, which can contain emojis. In V1 this field returns the device model.
  • device_model is a new field that returns the device model, for example PAX_A77.

Action Required

No action required for existing integrations: GET /poslink/v1/stores/{store_id}/terminals does not change. To show terminal names, move to V2. If you read the device model from terminal_name, read device_model instead.

Sep 3, 2026 - Bug Fix

V2 Refunds: Which Identifier Goes in transaction_id

The May 21, 2026 deprecation notice below was misleading about POST /poslink/v2/refunds. It read as though V2 takes a different identifier from V1. It does not.

The request field is named transaction_id, but the value it expects is the gateway_payment_id of the original payment, the same identifier V1 refunds took. The field name and the identifier name simply differ.

Send the gateway_payment_id of the original payment, delivered when that payment completes on its status stream (GET /poslink/v3/payment-requests/{payment-request-id}):

{
  "transaction_id": "39e3bacdd5d38d9ce611cf88afbcc86df829a9a5641880b3",
  "amount": 1500
}

Do not send the deprecated transaction_id from the V1 payment request response. Despite the matching field name it is a different identifier and the refund will fail with 404 TRANSACTION_NOT_FOUND.

Action Required

None if your refunds are working today. If you see 404 TRANSACTION_NOT_FOUND, check you are sending the gateway_payment_id of the original payment.

No API behaviour changed. This entry corrects the documentation only.

See Refunds in the API reference and Make a refund.

Aug 17, 2026 - New Feature

Receipt Text Endpoint

Added GET /poslink/v3/payment-requests/{payment-request-id}/receipt-text, which returns a JSON response with a receipt_text field containing the plain-text receipt for a SUCCESSFUL payment request or refund.

What the receipt includes:

  • Store name and address
  • UTC transaction date/time
  • Amount, tip, and total
  • Card details, AID, MID, TID, approval code, response code, entry mode, verification method, card type, and card issuing country
  • DCC details, where applicable
  • Receipt references (gateway reference and merchant reference)

Optional fields are omitted when absent, so no blank labels are printed.

Required scopes (one of the following):

  • payment_requests/id
  • default_access (deprecated; included for backward compatibility with existing integrations)

Action Required

No action required for existing integrations. The endpoint is additive and opt-in: call it after a payment request reaches SUCCESSFUL if you want a ready-to-print text receipt instead of composing one from the payment metadata yourself.

Jul 22, 2026 - Enhancement

V3 Payment Request Stream

GET /poslink/v3/payment-requests/{payment-request-id} supersedes the V2 endpoint for Transaction Updates over Server-Sent Events. Unlike V2, it also streams refunds and returns the raw status_reason rather than collapsing unrecognised reasons to EXPIRED.

New status_reason values on V3 (all reported as EXPIRED on V2):

  • TERMINAL_UNREACHABLE: the terminal could not be reached to deliver the push notification
  • NOTIFICATION_EXPIRED: the push notification expired before the terminal received it
  • SUPERSEDED_BY_NEW_TRANSACTION: a newer payment request was started on the same terminal
  • TRANSACTION_ALREADY_IN_PROGRESS: the terminal is already processing a transaction
  • UNSUPPORTED_CURRENCY: the terminal does not support the requested currency
  • FEATURE_NOT_ACTIVATED_UNREFERENCED_REFUNDS: unreferenced refunds are not activated for the terminal

Action Required

  1. Move Transaction Update subscriptions from GET /poslink/v2/payment-requests/{payment-request-id} to V3.
  2. Handle the status_reason values above, and keep tolerating unrecognised values, more may be added over time.

Cancelling a payment request is unaffected and remains on PATCH /poslink/v2/payment-requests/{payment-request-id}.


Jul 22, 2026 - Breaking Change

V1 Payment Requests List and V1 Refunds Removed

GET /poslink/v1/payment-requests and POST /poslink/v1/refunds have been removed.

Action Required

  1. Move from GET /poslink/v1/payment-requests to GET /poslink/v2/payment-requests, which also returns refunds alongside payments and adds type and date-range filters.
  2. Move from POST /poslink/v1/refunds to POST /poslink/v2/refunds, deprecated since May 21, 2026 (see below) and now fully removed.

May 21, 2026 - Deprecation

V1 Refunds Endpoint Deprecated

The V1 refunds endpoint POST /poslink/v1/refunds is now deprecated in favour of the new V2 refunds endpoint (POST /poslink/v2/refunds).

Action Required

Migrate your refund integrations from V1 to V2:

  1. Switch from POST /poslink/v1/refunds to POST /poslink/v2/refunds.
  2. Move the original payment's gateway_payment_id into the V2 request field named transaction_id. The field name differs from V1, the identifier you send does not.
  3. Update your response handling for the richer V2 payload (issuer_result, dcc, and the REFUND/REVERSAL transaction types).
  4. Do not send terminal_id in the request body unless you authenticate with client credentials (M2M). V1 had no such field; V2 added it, and sending it with a user token is rejected with 403 FORBIDDEN on every attempt. POSLink refunds are referenced online refunds - the terminal is derived from the original payment, so omitting terminal_id loses nothing.

Corrected Sep 3, 2026. Step 2 previously read "Identify the original transaction using transaction_id instead of gateway_payment_id", which wrongly implied V2 takes a different identifier. V2 takes the same gateway_payment_id as V1, in a field named transaction_id. See the Sep 3, 2026 correction above.

The V1 refunds endpoint remains available during a transition period but will be removed in a future release. Migrate to V2 as soon as possible to avoid disruption.

May 21, 2026 - New Feature

V2 Refunds Endpoint

Added POST /poslink/v2/refunds for refunding a previously processed transaction. The original payment is identified by its gateway_payment_id, sent in a request field named transaction_id, and the response carries richer settlement data than V1.

Key Features:

  • Refund by the original payment's gateway_payment_id, with optional partial amounts via the amount field (smallest currency unit)
  • Optional Idempotency-Key header to safely retry requests without creating duplicate refunds
  • Response includes the issuer authorisation result (issuer_result) and Dynamic Currency Conversion details (dcc) when applicable
  • Supports both REFUND and REVERSAL transaction types

See Refunds in the API reference.

Nov 14, 2025 - Added Real-Time Payment Status API with SSE Support

Added new API method GET payment-request V2
, which provides real-time updates of payment status over the Server-Sent Events (SSE) protocol.

June 18, 2025 - Deprecation

Starting June 19, 2025, the field `source_reference_id` will be deprecated and replaced by `merchant_reference`.

Affected APIs

Why This Change?

The source_reference_id is currently used across various internal and external systems inside Teya, which has led to inconsistencies and confusion across services.

To provide a clear, unified reference for merchants and developers, we are consolidating this field under a single standard: merchant_reference

Example Response Before and After

Before (Past Response)

{
  "payment_request_id": "xxx",
  "source_reference_id": "some_ref_123"
}
For a transitional period, both fields may appear in responses, but `source_reference_id` will return Null

Action Required

Please update your ePOS integration to:

  1. Stop using source_reference_id in your logic and data pipelines.
  2. Start using merchant_reference instead.
The `source_reference_id` field will be fully removed on **September 19, 2025** (3 months from the announcement).

June 11, 2025 - Added

Idempotency-Key Header Support

Added support for the Idempotency-Key header for the Create Payment Request endpoint.

Please see section Send a payment request


May 15, 2025 - Changed

Technical Change Description

Effective May 15, 2025, POSLink will improve the metadata experience by changing the source of the data when a transaction is approved. This will ensure metadata becomes available to partners in under 3 seconds, enhancing the responsiveness of the Get a Payment Request API.

As part of this update, the structure of the metadata field in the API response will be slightly adjusted.

API Response Changes

Current API Response

{
  "payment_request_id": "bee17dec-01dd-4ee5-a17d-ec01dd2ee5ca",
  "requested_amount": {
    "currency": "GBP",
    "amount": 70,
    "tip": 0
  },
  "status": "SUCCESSFUL",
  "transaction_type": "SALE",
  "created_at": "2022-06-15T16:24:120Z",
  "updated_at": "2022-06-15T16:26:120Z",
  "source_reference_id": "423897430",
  "transaction_id": "te3c89aa-d84f-4916-b88b-7e6a051765fa",
  "gateway_payment_id": "39e3bacdd5d38d9ce611cf88afbcc86df829a9a5641880b3",
  "terminal_id": "70dc65ba-1c13-492a-82a0-15821e5f63ba",
  "store_id": "f04fe1ce-e7bd-4c5b-b873-b156643c0bc3",
  "metadata": {
    "payment_method_details": {
      "card": {
        "last4": "1234",
        "issuing_country": "GB",
        "brand": "MASTERCARD",
        "type": "CREDIT"
      },
      "entry_mode": "CONTACTLESS",
      "verification_method": "OFFLINE_PIN",
      "application_id": "A0000000041010",
      "mid": "5006544",
      "response_code": "00",
      "authorisation_code": "A8RLR8"
    }
  }
}

Summary of Changes

Deprecated Fields
• issuing_country (UK, HUN, HRV)
• type (CREDIT / DEBIT)
New Fields
• bin (e.g. 518637)
• application_name (e.g. Debit MasterCard)

Partner Impact

Each partner is encouraged to review and analyse their current integration to assess whether any adjustments are necessary to support the updated metadata structure.

Deprecated Fields

Issuing Country and Card Type
• These fields will be deprecated and return null in the API response
• They will be removed from POSLink on May 31, 2025
• Action Required: Partners should update their integrations to remove any dependency on these deprecated fields.

New Fields

Card Bin, APN (Application Preferred Name)

• A new field, card bin and application preferred name will be included in the API response.
• This provides the first 6-8 digits of the card number and card application related.
• Action Required: Partners will have to update their ePOS system if they wish to include the new fields (Card Bin & Application Preferred Name).

Merchant Impact

This change is expected to have a positive impact for merchants. For setups where the merchant's system relies on metadata to print receipts, this data will now be available in less than 3 seconds after the transaction is approved. This helps to:

  • Reduce delays in receipt printing
  • Avoid cancelled or duplicate requests due to missing metadata

No action is required from merchants to benefit from this improvement.


Oct 17, 2024 - Added

Add validation on Store ID and Terminal ID

POSLink is introducing a new validation to ensure that the Terminal ID belongs to the given Store ID in Create a Payment Request. If the Terminal ID provided doesn't belong to the Store ID, POSLink will reject this request with the below response:

HTTP 403 Forbidden
{
  "code": "TERMINAL_NOT_REGISTERED_WITH_STORE",
  "description": "Terminal is not registered with the store provided in the request"
}
This validation will take effect starting **November 26, 2024, at 03:00 AM**.

May 7, 2024 - Changed

Major documentation updated

Introduction to the 4 Stages of Integration:

  1. Stage 1 - Design
  2. Stage 2 - Develop
  3. Stage 3 - Test
  4. Stage 4 - Get Certified

In addition to the above information, the following pages have been added:

  • FAQ (Frequently Asked Questions)
  • Integration Check List
  • Template for Teya Terminal Setup
The page "Request a Test Terminal" was removed

April 1, 2024 - Changed

URL Updates

URL updated in all documentation from:

Old URLs

https://identity.cloud.saltpay.co/
https://api.cloud.saltpay.co/pos-link/

February 14, 2024 - Changed

API Response Updates

  • Response of Retrieve a payment request updated to include mid, in the metadata object, for all successful transactions.
  • The status query parameter for the Retrieve a list of payment requests is now optional. If you omit the status query parameter, the returned list will include all payment requests.

November 07, 2023

Added

  • Added optional query parameters: start_date_time and end_date_time to the Retrieve a list of payment requests endpoint.
  • Released an updated version of the cancel flow, allowing transactions to be canceled up until a card is presented to the terminal.

Deprecated

  • Deprecated version 1 of the cancel flow in favour of version 2.

September 28, 2023

Added

  • Transaction Metadata - SUCCESSFUL response of Retrieve a payment request updated to include additional transaction metadata fields. This addition is intended to support various use cases, including consolidated receipt printing.

Changed

  • Removed deprecation notice on gateway_payment_id which will replace transaction_id now marked for deprecation. (Deprecation date for this change is yet to be confirmed. We are committed to communicating this update well in advance to our valued partners, ensuring a seamless transition).

Impacted endpoints:

  • Response of Retrieve a payment request
  • Response of Retrieve a list of payment requests
  • Request and Response of Create a new refund request

September 04, 2023

Added

  • Returning terminal_id in the following responses:
    • Response of Retrieve a payment request
    • Response of Retrieve a list of payment requests

Changed

  • Added transaction_id as a replacement to gateway_payment_id which has been marked for deprecation (Deprecation date for this change is yet to be confirmed).

Impacted endpoints:

  • Response of Retrieve a payment request
  • Response of Retrieve a list of payment requests
  • Request and Response of Create a new refund request

Either value may be used interchangeably until deprecation of gateway_payment_id has been finalised.

  • Create a payment request response updated to include additional transaction fields

Removed

  • success field in Cancel a payment request has been marked for deprecation. This can be inferred from status field. (Deprecation date for this change is yet to be confirmed).

March 13, 2023 - Initial Release

Initial release

The initial release of POSLink API documentation.