Integrate Tap to Pay payments with your POS Android app using the Tyro Tap to Pay app.
- Your Web POS app running on Android
- Tyro Tap to Pay app installed on the merchant's device
- A valid Tyro POS client ID (provided by Tyro)
- The merchant opens your Web POS in the Android browser.
- The user taps Pay in your interface.
- Your POS opens a secure link that launches the Tap to Pay app.
- The Tap to Pay app presents the payment screen, ready for the customer to tap their card.
- The Tap to Pay app processes the payment and closes, returning focus to the Web POS.
- Your Web POS awaits the transaction result from either a webhook or polling, then displays the result.
A Web POS running in Chrome cannot receive native app callbacks directly. Transaction outcomes are delivered via webhooks or direct polling — see Receiving transaction results.
Only supported in production. These are the steps for a merchant to authorise a POS to receive transaction results for Tap to Pay:
- Your POS generates and sends the merchant the unique Tyro Integration Portal URL, for example
https://integrate.tyro.com/embedded-payments?posId=[client_id]&posReference=[pos_reference]. - The merchant signs into the Tyro Integration Portal.
- The merchant authorises the POS for every MID that will use Tap to Pay.
- Your POS receives or retrieves confirmation.
- Your POS can access transaction results from the authorised MID(s).
This is the same Integration Portal mechanism used for account authorisation on the SDK path — the merchant authorises your POS for a MID once, regardless of which integration model you're using.
https://auth.tyro.com/taptopay?action=<action>&type=<type>&data=<base64url-json>Parameters:
action— what to do:auth,transaction,postype— a qualifier:pair,request,infodata— base64url-encoded JSON payload (RFC 4648 §5, URL-safe, no padding)
Example (decoded for clarity):
action=transaction
type=request
data = Base64url({
"type": "PURCHASE",
"amount": 2999,
"reference": "ORDER-12345",
"posInfo": {
"name": "WebPOS Terminal",
"vendor": "Acme Inc",
"version": "2.1.0",
"siteReference": "SITE-001"
}
})Use this once to establish trust between your Web POS and the Tap to Pay app.
https://auth.tyro.com/taptopay?action=auth&type=pair&data=Base64url({"posClientId":"YOUR-POS-CLIENT-ID"})Payload:
{
"posClientId": "YOUR-POS-CLIENT-ID"
}or you can also pass the default POSInfo at this time
{
"posClientId": "YOUR-POS-CLIENT-ID",
"posInfo": {
"name": "My WebPOS Name",
"vendor": "My Company",
"version": "1.0.0",
"siteReference": "LOCATION-001"
}
}What happens:
- Tap to Pay shows a login screen.
- The merchant logs in with their Tyro account and configure the merchant ID (MID) and location as required.
- Trust is established; future transactions run without login prompts.
NOTE Additional calls to Pair are ignored and simple close the Tap to Pay app and return to the last foregrounded app.
Use this to process payments.
https://auth.tyro.com/taptopay?action=transaction&type=request&data=Base64url({...})Payload:
{
"type": "PURCHASE",
"amount": 5000,
"reference": "ORDER-67890",
"posInfo": {
"name": "My WebPOS",
"vendor": "My Company",
"version": "1.0.0",
"siteReference": "LOCATION-001"
}
}Fields:
type—"PURCHASE"or"REFUND"amount— amount in cents (e.g. 5000 = $50.00)reference— unique order/transaction IDposInfo— terminal information (optional if already set during Pairing or Register POS info)
Result:
- Tap to Pay opens, and the merchant taps the customer's card.
- The transaction completes or fails.
- The user returns to your Web POS (or stays in Tap to Pay if they close it).
- Your backend receives the transaction result via Tyro's payment notification API.
Set the terminal details in Tap to Pay.
https://auth.tyro.com/taptopay?action=pos&type=info&data=Base64url({...})Payload:
{
"name": "Register 3",
"vendor": "Acme POS v2.1",
"version": "2.1.0",
"siteReference": "STORE-456"
}function toBase64Url(obj) {
const json = JSON.stringify(obj);
const bytes = new TextEncoder().encode(json);
let binary = String.fromCharCode(...bytes);
return btoa(binary)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}function launchPayment(amountCents, reference) {
const payload = {
type: "PURCHASE",
amount: amountCents,
reference: reference,
posInfo: {
name: "WebPOS Terminal",
vendor: "My Company",
version: "1.0.0",
siteReference: "SITE-001"
}
};
const data = toBase64Url(payload);
const url = `https://auth.tyro.com/taptopay?action=transaction&type=request&data=${data}`;
// Open in new tab or same window (depends on your UX)
window.location.href = url;
// OR: window.open(url, '_blank');
}
// Call from your Pay button
document.getElementById('payButton').addEventListener('click', () => {
launchPayment(2999, 'ORDER-12345');
});function pairPos(posClientId, posInfo) {
const payload = { posClientId: posClientId, posInfo: posInfo };
const data = toBase64Url(payload);
const url = `https://auth.tyro.com/taptopay?action=auth&type=pair&data=${data}`;
window.location.href = url;
}Since a Web POS doesn't get direct callbacks, here's how to handle results:
- Your Web POS opens the Tap to Pay deeplink when Paying on device.
- The card holder completes the transaction in Tap to Pay.
- Tap to Pay submits the transaction to Tyro.
- (Optional) Tyro sends a payment notification to your backend via webhook; If webhook are configured.
- Your backend updates the order status.
- Your Web POS polls or listens for webhooks from your backend.
Your backend receives the full transaction status and detail via Tyro's payment notification API — see the Tap to Pay notification events reference.
1. Pairing is a mandatory first on a new device. Before processing transactions, run the pairing flow once. This establishes trust and allows faster transactions later.
**2. (Optional) Set the POS info during pairing or register POS info
3. Validate amounts. Ensure the amount is in cents (e.g. $25.99 = 2599):
const dollars = 25.99;
const cents = Math.round(dollars * 100); // 25994. Use unique references. Always include a unique reference (e.g. order ID) so you can resolve transactions results:
const reference = `MY_UNIQUE_TRNASACTION_REQUEST_ID`;5. Include POS info. If no default is set and no posInfo is passed with a transaction request, then Tap to Pay will be reject the transaction:
const posInfo = {
name: `Register ${terminalId}`,
vendor: "My POS Software",
version: appVersion,
siteReference: locationId
};6. Handle a missing Tap to Pay app. If Tap to Pay isn't installed, the user is taking to a 404 page.
7. No action needed for deep link verification. Tap to Pay links are verified via Android App Links (Digital Asset Links), which prevents unauthorised apps from intercepting requests — just use the correct domain, auth.tyro.com.
All external testing uses the same Tap to Pay app, via https://auth.tyro.com/taptopay?.... Environments, test cards and simulator mode are covered in Testing.
Solution: the user needs to install Tyro Tap to Pay from the Play Store.
Possible causes:
- Base64url encoding is incorrect (ensure no padding, and use
-and_). - The JSON isn't valid (check for missing commas or quotes).
- Required fields are missing.
Debug tip: decode your data parameter to verify the JSON:
function decodeBase64Url(str) {
// Add padding if needed
const padded = str + '='.repeat((4 - str.length % 4) % 4);
const bytes = Uint8Array.from(atob(padded.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}- Ensure you've run the pairing flow with the correct POS client ID.
- Verify the POS client ID matches what Tyro assigned to your account.
Possible causes: network connection lost during authorisation, NFC reader unavailable or malfunctioning, or the card removed during read.
Solution: retry the transaction.
Expected behaviour: a Web POS doesn't receive the result directly. Your backend receives it via Tyro's payment notification API.
HTTPS only. All Tyro Tap to Pay links use https://auth.tyro.com. Never use http://.
App link verification. The auth.tyro.com domain is verified via Digital Asset Links, which prevents man-in-the-middle attacks and rogue apps intercepting payment intents. You don't need to do anything — just use the correct domain.
POS client ID. Treat your posClientId like an API key. Don't hard-code it in client-side code if possible; retrieve it from your backend.
User privacy. Transaction data is sent to Tap to Pay, which handles it securely. Your Web POS shouldn't log or store sensitive details.
Contact Tyro to receive your unique posClientId for production use, and to have your account set up in UAT with test credentials. Work with Tyro's integration team to configure payment notification webhooks for your backend, set up transaction reconciliation, and enable any advanced features such as refunds or digital receipts.
https://auth.tyro.com/taptopay?action=auth&type=pair&data=eyJwb3NDaWVudElkIjoiTVktUE9TLUlEIn0Decoded data: {"posClientId":"MY-POS-ID"}
https://auth.tyro.com/taptopay?action=transaction&type=request&data=eyJ0eXBlIjoiUFVSQ0hBU0UiLCJhbW91bnQiOjI5OTksInJlZmVyZW5jZSI6Ik9SREVSLTI0NjciLCJwb3NJbmZvIjp7Im5hbWUiOiJXZWJQT1MiLCJ2ZW5kb3IiOiJNeUNvIiwidmVyc2lvbiI6IjEuMC4wIiwic2l0ZVJlZmVyZW5jZSI6IlNJVEUtMDAxIn19Decoded data:
{
"type": "PURCHASE",
"amount": 2999,
"reference": "ORDER-2467",
"posInfo": {
"name": "WebPOS",
"vendor": "MyCo",
"version": "1.0.0",
"siteReference": "SITE-001"
}
}