What is Slice Pay? #
Slice Pay is a payment solution that allows your customers to split their travel purchases into flexible installment plans.
Instead of paying the full amount upfront, customers can make a deposit and pay the remainder in scheduled installments
leading up to their departure date.
๐ก Perfect for Travel
Slice Pay is specifically designed for the travel industry, helping customers manage their cash flow while
securing their bookings early.
Our Lay By Plans #
Slice Pay offers flexible lay-by plans that automatically adjust based on the customer's departure date and purchase amount.
The system intelligently creates a payment schedule that works for both the customer and your business.
๐๏ธ Flexible Scheduling
Payments are automatically scheduled based on departure dates
๐ฐ Deposit Protection
Secure bookings with minimal upfront deposits
๐ฑ Customer Dashboard
Customers can manage their payment plans through our portal
About our API #
The Slice Pay API is designed to be simple and developer-friendly. It follows fundamental Web principles and returns
HTML responses that can be easily parsed and integrated into your existing workflow.
HTML Responses
Returns structured HTML that's easy to parse and integrate
๐ก๏ธ Secure by Design
Built with security best practices and proper authentication
๐ Form-Based
Uses standard HTTP form submission for compatibility
Specification Keywords #
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
RFC 2119.
Authentication #
Slice Pay uses agent-based authentication through secure Agent IDs. Each agent receives a unique identifier
that MUST be included in all API requests.
Your personal agent identifier generated by Slice Pay. This acts as your API key.
๐ Security Notice
Your Agent ID is confidential and MUST be treated like a password. Anyone with this key can generate
payment links on your behalf. Never expose it in client-side code or public repositories.
Example: agentId=agent-bypass-5kyp4y
๐ก Getting Your Agent ID
Contact the Slice Pay team to receive your unique Agent ID for both staging and production environments.
Environments #
Slice Pay provides separate environments for testing and production use. Always develop and test using
the staging environment before deploying to production.
๐งช Staging Environment
For testing and development
https://api.staging.slicepay.travel
Use this environment for all development, testing, and integration work
๐ Production Environment
For live transactions
https://api.slicepay.travel
Only use this environment for live customer transactions
๐ Environment Guidelines
- Always test thoroughly in staging before going live
- Use separate Agent IDs for staging and production
- Monitor your integration in staging for any API changes
- Keep your production Agent ID secure and rotate it periodically
Staging #
๐ Regular Flow URL
https://api.staging.slicepay.travel/api/test
Embedded Flow URL
https://api.staging.slicepay.travel/api/test/embedded
๐ With Example Test Agent ID
https://api.staging.slicepay.travel/api/test?agentId=agent-bypass-5kyp4y
โ๏ธ With All OPTIONAL Fields
https://api.staging.slicepay.travel/api/test?agentId=agent-bypass-5kyp4y&bookingNotificationUrl=https://example.com/test-callback&redirectUrlSucceeded=https://example.com/succeeded
How do I get set up in staging? #
- Provide us with an email for booking successful notifications (email notifications)
- Provide us with the domains to allowlist for webhook endpoints and redirect URLs
We will process these details and have you set up within 1 business day. You can contact us via support@slicepay.travel or directly to the Slice Pay developer you are working with.
๐ Required Information
- Email Address: This will receive test notifications when customers successfully complete deposit payments in staging
- Domain(s): All domains that will host your webhook endpoints and redirect URLs MUST be pre-authorized for security purposes
Production #
๐ Regular Flow URL
https://api.slicepay.travel/api/create-link
Embedded Flow URL
https://api.slicepay.travel/api/create-link/embedded
๐ With Your Agent ID
https://api.slicepay.travel/api/create-link?agentId=your-production-agent-id
โ๏ธ With All OPTIONAL Fields
https://api.slicepay.travel/api/create-link?agentId=your-production-agent-id&bookingNotificationUrl=https://yourdomain.com/webhook&redirectUrlSucceeded=https://yourdomain.com/success
How do I get set up in production? #
- Provide us with an email for deposit confirmation notifications
- Provide us with the domains to allowlist for
bookingNotificationUrl and redirectUrlSucceeded endpoints
We will process these details and have you set up within 1 business day. You can contact us via support@slicepay.travel or directly to the Slice Pay developer you are working with.
๐ Required Information
- Email Address: This will receive notifications when customers successfully complete deposit payments
- Domain(s): All domains that will host your
bookingNotificationUrl webhook endpoints and redirectUrlSucceeded redirect URLs MUST be pre-authorized for security purposes
Webhook Notifications #
Learn how Slice Pay sends webhook notifications to your system when payments are processed successfully.
The bookingNotificationUrl parameter allows you to receive real-time notifications when a customer successfully completes a deposit payment through Slice Pay.
โ
Use Cases
- Update booking status in your system
- Send confirmation emails to customers
- Trigger fulfillment processes
- Update inventory or availability
- Generate receipts or invoices
๐ Requirements
- HTTPS endpoint required
- Domain MUST be pre-authorized
- MUST return HTTP 200 status
- Handle duplicate requests
- Process requests quickly
How It Works #
We'll perform a POST request with the following headers:
Content-Type: application/x-www-form-urlencoded
Accept: text/html
X-Request-ID: [unique-id]
The X-Request-ID is a unique random ID generated for each request. Use this as a deduplication ID in case of retries initiated by our systems.
We'll pass the following parameters in the request body in NO specific order:
- agentId - The original agentId that created the link
- bookingReference - The original bookingReference this payment is related to
- salePrice - The original salePrice in cents sent through Create Link API
- currency - The original currency sent through Create Link API
Example Request Body:
bookingReference=12345&agentId=agent-123&salePrice=1000¤cy=AUD
The destination server MUST ALWAYS return the HTTP status code 200 to acknowledge successful receipt of the webhook.
โ ๏ธ Important
Our webhook call represents a fact (an event that a payment has been received), therefore it's not expected to be rejected for any reason. Any response other than HTTP 200 will be considered a failure, and our system MAY retry the webhook delivery with the same parameters.
Implementation Example #
const express = require('express');
const app = express();
// Middleware to parse form data
app.use(express.urlencoded({ extended: true }));
app.post('/webhook/slicepay-notification', (req, res) => {
try {
// Extract webhook data
const { agentId, bookingReference, salePrice, currency } = req.body;
const requestId = req.headers['x-request-id'];
console.log('Received Slice Pay webhook:', {
requestId,
agentId,
bookingReference,
salePrice,
currency
});
// Check for duplicate requests using X-Request-ID
if (isDuplicateRequest(requestId)) {
console.log('Duplicate request detected, ignoring');
return res.status(200).send('OK');
}
// Process the payment notification
// Update your database, send emails, etc.
updateBookingStatus(bookingReference, 'payment_received');
sendConfirmationEmail(bookingReference);
// Always return 200 for successful processing
res.status(200).send('OK');
} catch (error) {
console.error('Webhook processing error:', error);
// Still return 200 to prevent retries for processing errors
res.status(200).send('Error processed');
}
});
function isDuplicateRequest(requestId) {
// Implement your deduplication logic here
// You might store processed request IDs in a cache or database
return false;
}
function updateBookingStatus(bookingReference, status) {
// Update your booking system
console.log(`Updating booking ${bookingReference} to ${status}`);
}
function sendConfirmationEmail(bookingReference) {
// Send confirmation email to customer
console.log(`Sending confirmation email for booking ${bookingReference}`);
}
Best Practices #
โ
Do
- Always return HTTP 200 for successful processing
- Implement deduplication using X-Request-ID
- Process webhooks quickly (under 30 seconds)
- Log all webhook events for debugging
- Validate the request parameters
- Use HTTPS for your webhook endpoint
โ Don't
- Return non-200 status codes for processing errors
- Process the same webhook multiple times
- Perform long-running operations synchronously
- Ignore the X-Request-ID header
- Expose sensitive information in logs
- Use HTTP (non-secure) endpoints
Security Considerations #
For enhanced security, you can include a validation token as part of your bookingNotificationUrl path. This token can be associated with the booking reference, providing an additional layer of authentication that only you know.
Example Implementation:
https://yourdomain.com/webhook/slicepay/{url_encoded_token}
Where url_encoded_token could be:
- A hash of the booking reference + your secret key
- A JWT token containing booking metadata
- A randomly generated token stored in your database
๐ก Important
Ensure your token is properly URL-encoded when constructing the bookingNotificationUrl. Use functions like encodeURIComponent() in JavaScript or equivalent in your preferred language.
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.urlencoded({ extended: true }));
// Your secret key for token generation/validation
const SECRET_KEY = process.env.WEBHOOK_SECRET_KEY;
app.post('/webhook/slicepay/:token', (req, res) => {
try {
const { token } = req.params;
const { agentId, bookingReference, salePrice, currency } = req.body;
const requestId = req.headers['x-request-id'];
// Validate the token
if (!validateToken(token, bookingReference)) {
console.log('Invalid token for booking:', bookingReference);
return res.status(200).send('Invalid token');
}
console.log('Valid webhook received:', {
requestId,
agentId,
bookingReference,
salePrice,
currency
});
// Check for duplicates
if (isDuplicateRequest(requestId)) {
return res.status(200).send('OK');
}
// Process the payment
updateBookingStatus(bookingReference, 'payment_received');
sendConfirmationEmail(bookingReference);
res.status(200).send('OK');
} catch (error) {
console.error('Webhook error:', error);
res.status(200).send('Error processed');
}
});
function validateToken(receivedToken, bookingReference) {
// Example: Generate expected token using HMAC
const expectedToken = crypto
.createHmac('sha256', SECRET_KEY)
.update(bookingReference)
.digest('hex');
// URL decode the received token for comparison
const decodedToken = decodeURIComponent(receivedToken);
return crypto.timingSafeEqual(
Buffer.from(expectedToken),
Buffer.from(decodedToken)
);
}
function generateTokenForBooking(bookingReference) {
// Use this function when creating the bookingNotificationUrl
const token = crypto
.createHmac('sha256', SECRET_KEY)
.update(bookingReference)
.digest('hex');
return encodeURIComponent(token);
}
Regular Flow #
The regular flow creates a payment link that redirects customers to our hosted payment page. This is the simplest
integration method where customers complete their payment plan setup on our secure platform.
๐ก Quick Integration
Perfect for getting started quickly. Generate a link and redirect your customers to our payment page. Your customers will be redirected to our secure
payment page to complete their payment plan setup.
For a more integrated experience, see the Embedded Flow.
Generate a payment link for the redirect flow integration. This is the simplest way to integrate Slice Pay -
create a link and redirect your customers to our hosted payment page.
API Request #
cURL Example #
curl --location --request POST 'https://api.staging.slicepay.travel/api/create-link' \
--header 'Accept: text/html' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'salePrice=1000' \
--data 'currency=AUD' \
--data 'departureDate=2030-10-01' \
--data 'agentId=agent-bypass-5kyp4y' \
--data 'bookingReference=ABC123'
Raw HTTP Example #
POST /api/create-link HTTP/1.1
Host: api.staging.slicepay.travel
Accept: text/html
Content-Type: application/x-www-form-urlencoded
Content-Length: 104
salePrice=1000¤cy=AUD&departureDate=2030-10-01&agentId=agent-bypass-5kyp4y&bookingReference=ABC123
Request Fields #
Number in cents representing the total amount of the sale.
Precision of 2 digits by default: 10000 โ 100.00 โ $100.00
Example: salePrice=256058 โ $2560.58
The date when the flight departs.
An ISO 8601 date format representing the departure date.
Example: departureDate=2024-03-12
The booking reference used to identify the booking related to this payment plan link.
SHOULD be a unique ID per booking within your agency. We'll use this to query you for more
information about the booking.
You can generate multiple payment plan links for the same bookingReference.
Limited to 20 characters long using UTF-8 encoding.
Example: bookingReference=h712345-yhfb-789746
Your personal agent identifier generated by Slice Pay.
โ ๏ธ Security Notice
Anyone with this key can generate payment links on your behalf.
Treat it as a secret key and never expose it in client-side code.
Example: agentId=agent-123
Upon each successful deposit, this URL will be called by our systems via webhook.
URL Validation Criteria:
- The URL MUST be valid
- The URL MUST start with
https://
- The domain MUST be previously authorized for your agent
- The URL MUST have NO querystring parameters
Webhook Request Details:
We'll perform a POST request with these headers:
Content-Type: application/x-www-form-urlencoded
Accept: text/html
X-Request-ID: [unique-id] - Use for deduplication
Webhook Parameters:
agentId - The original agentId that created the link
-
bookingReference - The original bookingReference this payment is related
to
-
salePrice - The original salePrice in cents sent through
Create Link API
-
currency - The original currency sent through
Create Link API
-
Example:
bookingReference=12345&agentId=agent-123&salePrice=1000¤cy=AUD
Example: https://agent-website.com/callback
Successful Response #
When successful, the API returns HTML containing a payment link that you can parse and use to
redirect your customer.
<html>
<a name="payment-link" href="[dynamically generated payment link]">
Pay using instalments
</a>
<time class="sg-payment-link-expiry-date" datetime="2024-12-31T23:59:59Z"></time>
</html>
๐ก Implementation Tip
Use a DOM parser to extract the href attribute from the anchor tag with
name="payment-link". The expiry date can be found in the
datetime attribute of the time element.
Error Response #
See Problem Responses section for details.
More Implementation Examples #
Here are comprehensive examples showing how to integrate with the Create Payment Link API in different environments.
JavaScript Successful Response Handling (ES6) #
const parse = html => new JSDOM(html).window.document;
// Make request
const url = 'https://api.staging.slicepay.travel/api/create-link';
const response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
salePrice: '100000',
currency: 'AUD',
departureDate: '2030-10-01',
bookingReference: 'ABC123',
agentId: 'agent-bypass-5kyp4y'
}).toString()
});
// Response Handling
const responseBody = await response.text();
const paymentLinkHref = parse(responseBody).querySelector('a[name="payment-link"]')?.href;
const paymentLinkText = parse(responseBody).querySelector('a[name="payment-link"]')?.textContent;
const paymentLinkExpiryDate = parse(responseBody).querySelector('.sg-payment-link-expiry-date')?.getAttribute('datetime');
if (paymentLinkHref && response.status === 200) {
const paymentLink = {
href: paymentLinkHref,
text: (paymentLinkText || '').trim(),
expiryDate: paymentLinkExpiryDate
};
use(paymentLink); // Payment link is available, use it as a payment option to customer
} else {
throw new Error(`Unexpected response: ${response.status} ${responseBody}`);
}
JavaScript Error Handling (ES6) #
const parse = html => new JSDOM(html).window.document;
// Make request
const url = 'https://api.staging.slicepay.travel/api/create-link';
const response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
//salePrice: '100000', // <-- Missing required field "salePrice"
currency: 'AUD',
departureDate: '2030-10-01',
bookingReference: 'ABC123',
agentId: 'agent-bypass-5kyp4y'
}).toString()
});
// Response Handling - See Problem Responses section for details
const responseBody = await response.text();
const problemTitle = parse(responseBody).querySelector('.sg-problem .sg-problem-title')?.textContent;
const problemDescription = parse(responseBody).querySelector('.sg-problem .sg-problem-description')?.textContent;
if (problemTitle && response.status === 400) {
const problemDetails = {
problemTitle: problemTitle.trim(),
problemDescription: (problemDescription || '').trim()
};
handleError(problemDetails);
} else {
throw new Error(`Unexpected response: ${response.status} ${responseBody}`);
}
โน๏ธ Complete Error Handling
For comprehensive error handling patterns and status codes, see the
Problem Responses section.
Save this code in a .html file and open with the browser.
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/html5-boilerplate@5.3.0/dist/css/main.css">
<style>
* {
font-family: Arial, sans-serif;
}
/*
1. Remove shadow border for Samsung devices
2. Remove default border width and style for Chrome on Windows
3. Safari on iPhone requires border set
*/
.sp-btn {
position: relative;
padding: 15px 15px 15px 15px;
color: #000;
margin: -1px auto;
display: block;
width: 100%;
text-align: left;
box-shadow: 3px 3px 3px 0px rgb(0 0 0 / 10%);
-webkit-appearance: none;
font-size: 1em;
border-radius: 10px;
text-align: center;
font-weight: normal;
border-width: 1px; /* 2 */
border-style: solid; /* 2 */
border-color: #000; /* 3 */
background-color: #FFF; /* 1 */
}
</style>
<meta name="theme-color" content="#fafafa">
</head>
<body>
<div style="margin: auto auto; display: flex; justify-content: center;">
<div style="max-width: 400px; margin: auto auto;">
<form name="create-payment-link" method="POST" action="https://api.staging.slicepay.travel/api/create-link">
<div>
Sale Price: <input type="text" name="salePrice" inputmode="numeric" required value="100000">
</div>
<div>
Currency: <input type="text" name="currency" required value="AUD">
</div>
<div>
Departure: <input type="date" name="departureDate" required value="2030-10-01">
</div>
<div>
Booking Reference: <input type="text" name="bookingReference" required value="ABC123">
</div>
<div>
AgentId: <input type="text" name="agentId" value="agent-bypass-5kyp4y" required>
</div>
<button type="submit" style="margin-top: 10px;" class="sp-btn">Generate Payment Link</button>
</form>
</div>
</div>
</body>
</html>
Embedded Flow #
Create an embedded payment experience that allows customers to select their payment plan directly on your
website. This provides a seamless, branded experience while keeping customers on your site.
๐ก Enhanced Experience
The embedded flow provides the best user experience by allowing customers to see and select their
preferred payment plan without leaving your website. Perfect for maintaining brand consistency and
improving conversion rates. You can even customize the background color to match your site's theme
and ensure consistent appearance across different device themes.
โ ๏ธ Important Note
The embedded flow requires webhook integration to handle payment notifications. Make sure your
bookingNotificationUrl is properly configured and can handle POST requests from our system.
Quick Links
Need the simpler integration? Check out the Regular Flow which
redirects customers to our hosted payment page.
API Request #
cURL Example #
curl --location --request POST 'https://api.staging.slicepay.travel/api/create-link/embedded' \
--header 'Accept: text/html' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'salePrice=1000' \
--data 'currency=AUD' \
--data 'departureDate=2030-10-01' \
--data 'agentId=agent-bypass-5kyp4y' \
--data 'bookingReference=ABC123' \
--data 'bookingNotificationUrl=https://example.com/test-callback'
Raw HTTP Example #
POST /api/create-link/embedded HTTP/1.1
Host: api.staging.slicepay.travel
Accept: text/html
Content-Type: application/x-www-form-urlencoded
Content-Length: 103
salePrice=1000¤cy=AUD&departureDate=2030-10-01&agentId=agent-bypass-5kyp4y&bookingReference=ABC123&bookingNotificationUrl=https://example.com/test-callback
Request Fields #
Number in cents representing the total amount of the sale.
Precision of 2 digits by default: 10000 โ 100.00 โ $100.00
Example: salePrice=256058 โ $2560.58
The date when the flight departs.
An ISO 8601 date format representing the departure date.
Example: departureDate=2024-03-12
The booking reference used to identify the booking related to this payment plan link.
SHOULD be a unique ID per booking within your agency. We'll use this to query you for more
information about the booking.
You can generate multiple payment plan links for the same bookingReference.
Limited to 20 characters long using UTF-8 encoding.
Example: bookingReference=h712345-yhfb-789746
Your personal agent identifier generated by Slice Pay.
โ ๏ธ Security Notice
Anyone with this key can generate payment links on your behalf.
Treat it as a secret key and never expose it in client-side code.
Example: agentId=agent-123
Upon each successful deposit, this URL will be called by our systems via webhook.
URL Validation Criteria:
- The URL MUST be valid
- The URL MUST start with
https://
- The domain MUST be previously authorized for your agent
- The URL MUST have NO querystring parameters
Webhook Request Details:
We'll perform a POST request with these headers:
Content-Type: application/x-www-form-urlencoded
Accept: text/html
X-Request-ID: [unique-id] - Use for deduplication
Webhook Parameters:
agentId - The original agentId that created the link
-
bookingReference - The original bookingReference this payment is related
to
-
salePrice - The original salePrice in cents sent through
Create Link API
-
currency - The original currency sent through
Create Link API
-
Example:
bookingReference=12345&agentId=agent-123&salePrice=1000¤cy=AUD
Example: https://agent-website.com/callback
Upon each successful deposit, we'll instruct the User Agent to perform a GET request on
redirectUrlSucceeded.
URL Validation Criteria:
- The URL MUST be valid
- The URL MUST start with
https://
- The domain MUST be previously authorized for your agent
Examples: https://agent-website.com/done,
https://agent-website.com/done?exampleSessionId={example-session-id},
https://agent-website.com/done/{example-session-id}
Successful Response #
When successful, the API returns HTML containing a payment link that you can parse and use to
redirect your customer.
<html>
<a name="payment-link" href="[dynamically generated payment link]">
Pay using instalments
</a>
<time class="sg-payment-link-expiry-date" datetime="2024-12-31T23:59:59Z"></time>
</html>
๐ก Implementation Tip
Use a DOM parser to extract the href attribute from the anchor tag with
name="payment-link". The expiry date can be found in the
datetime attribute of the time element.
Error Response #
See Problem Responses section for details.
More Implementation Examples #
Here are comprehensive examples showing how to integrate with the Create Payment Link API in different environments.
JavaScript Successful Response Handling (ES6) #
const parse = html => new JSDOM(html).window.document;
// Make request
const url = 'https://api.staging.slicepay.travel/api/create-link';
const response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
salePrice: '100000',
currency: 'AUD',
departureDate: '2030-10-01',
bookingReference: 'ABC123',
agentId: 'agent-bypass-5kyp4y'
}).toString()
});
// Response Handling
const responseBody = await response.text();
const paymentLinkHref = parse(responseBody).querySelector('a[name="payment-link"]')?.href;
const paymentLinkText = parse(responseBody).querySelector('a[name="payment-link"]')?.textContent;
const paymentLinkExpiryDate = parse(responseBody).querySelector('.sg-payment-link-expiry-date')?.getAttribute('datetime');
if (paymentLinkHref && response.status === 200) {
const paymentLink = {
href: paymentLinkHref,
text: (paymentLinkText || '').trim(),
expiryDate: paymentLinkExpiryDate
};
use(paymentLink); // Payment link is available, use it as a payment option to customer
} else {
throw new Error(`Unexpected response: ${response.status} ${responseBody}`);
}
JavaScript Error Handling (ES6) #
const parse = html => new JSDOM(html).window.document;
// Make request
const url = 'https://api.staging.slicepay.travel/api/create-link';
const response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
//salePrice: '100000', // <-- Missing required field "salePrice"
currency: 'AUD',
departureDate: '2030-10-01',
bookingReference: 'ABC123',
agentId: 'agent-bypass-5kyp4y'
}).toString()
});
// Response Handling - See Problem Responses section for details
const responseBody = await response.text();
const problemTitle = parse(responseBody).querySelector('.sg-problem .sg-problem-title')?.textContent;
const problemDescription = parse(responseBody).querySelector('.sg-problem .sg-problem-description')?.textContent;
if (problemTitle && response.status === 400) {
const problemDetails = {
problemTitle: problemTitle.trim(),
problemDescription: (problemDescription || '').trim()
};
handleError(problemDetails);
} else {
throw new Error(`Unexpected response: ${response.status} ${responseBody}`);
}
โน๏ธ Complete Error Handling
For comprehensive error handling patterns and status codes, see the
Problem Responses section.
Save this code in a .html file and open with the browser.
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/html5-boilerplate@5.3.0/dist/css/main.css">
<style>
* {
font-family: Arial, sans-serif;
}
/*
1. Remove shadow border for Samsung devices
2. Remove default border width and style for Chrome on Windows
3. Safari on iPhone requires border set
*/
.sp-btn {
position: relative;
padding: 15px 15px 15px 15px;
color: #000;
margin: -1px auto;
display: block;
width: 100%;
text-align: left;
box-shadow: 3px 3px 3px 0px rgb(0 0 0 / 10%);
-webkit-appearance: none;
font-size: 1em;
border-radius: 10px;
text-align: center;
font-weight: normal;
border-width: 1px; /* 2 */
border-style: solid; /* 2 */
border-color: #000; /* 3 */
background-color: #FFF; /* 1 */
}
</style>
<meta name="theme-color" content="#fafafa">
</head>
<body>
<div style="margin: auto auto; display: flex; justify-content: center;">
<div style="max-width: 400px; margin: auto auto;">
<form name="create-payment-link" method="POST" action="https://api.staging.slicepay.travel/api/create-link">
<div>
Sale Price: <input type="text" name="salePrice" inputmode="numeric" required value="100000">
</div>
<div>
Currency: <input type="text" name="currency" required value="AUD">
</div>
<div>
Departure: <input type="date" name="departureDate" required value="2030-10-01">
</div>
<div>
Booking Reference: <input type="text" name="bookingReference" required value="ABC123">
</div>
<div>
AgentId: <input type="text" name="agentId" value="agent-bypass-5kyp4y" required>
</div>
<button type="submit" style="margin-top: 10px;" class="sp-btn">Generate Payment Link</button>
</form>
</div>
</div>
</body>
</html>
Recommended Frontend Integration #
-
Generate the Embeddable Link: Use the create link API to
generate a unique embeddable link. This link will be provided to you as a response.
-
Embed the Link in your HTML: Include the following code in your HTML, replacing
<the link coming from create link API comes here> with the actual link you
received. This MUST be placed where you want the widget to appear:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My travel agency</title>
</head>
<body>
<!-- Basic usage without background color customization -->
<script data-quote-url="<the link coming from create link API comes here>" src="https://api.slicepay.travel/slicepay.js?callToActionId=ota-call-to-action-button"></script>
<button id="ota-call-to-action-button">Deposit</button>
<!-- Advanced usage with custom background color -->
<script data-quote-url="<the link coming from create link API comes here>" data-bg-color="#f8f9fa" src="https://api.slicepay.travel/slicepay.js?callToActionId=ota-call-to-action-button-custom"></script>
<button id="ota-call-to-action-button-custom">Deposit with Custom Theme</button>
</body>
</html>
Parameters #
This is the call to action component id that goes into the query parameter script's src. It can be either an anchor (<a>) or button (<button>)
Customize the background color of the embedded payment interface to match your website's design and prevent conflicts with OS dark/light theme settings.
This parameter ensures consistent branding and appearance regardless of the user's system preferences.
Default: White (#ffffff) if no background color is specified.
Examples:
data-bg-color="#ffffff" (white background)
data-bg-color="#f8f9fa" (light gray background)
data-bg-color="#1a1a1a" (dark background)
data-bg-color="rgb(248,249,250)" (light gray using RGB)
data-bg-color="rgba(255,255,255,0.95)" (semi-transparent white)
Handling Content Security Policy (CSP) #
If you're using a Content Security Policy (CSP) on your website, you need to add the following directives
to allow the Slice Pay component to work correctly.
Directives #
script-src
- Allow scripts to be loaded from the Slice Pay domain
- Example:
script-src 'self' https://api.slicepay.travel;
style-src
- Allow styles to be loaded from the Slice Pay domain
- Example:
style-src 'self' https://api.slicepay.travel;
connect-src
- Allow connections to the Slice Pay domain
- Example:
connect-src 'self' https://api.slicepay.travel;
frame-src
- Allow frames to be loaded from the Slice Pay domain
- Example:
frame-src 'self' https://api.slicepay.travel;
Validating the Integration #
Before deploying your Slice Pay integration to production, it's critical to thoroughly validate that all components
are working correctly. This comprehensive validation process ensures your customers will have a smooth payment
experience and that your system can handle both successful transactions and error scenarios.
๐จ Critical Before Production
Complete ALL validation steps before going live. Incomplete testing can result in failed customer payments,
missed webhooks, and lost revenue. Take the time to validate every aspect of the integration.
๐งช Complete Testing
Test all payment flows, error scenarios, and edge cases
๐ Webhook Validation
Ensure your system receives and processes payment notifications
๐ง Email Confirmation
Verify both customer and agency email notifications work
๐ Dashboard Monitoring
Confirm transactions appear correctly in your Slice Pay dashboard
Testing Checklist #
Use this comprehensive checklist to ensure your Slice Pay integration is production-ready. Each item SHOULD
be completed and verified in the staging environment before proceeding to production.
Verify you can successfully create payment links using your chosen integration method:
- โ
If using Regular Flow: Generate redirect payment links (webhook OPTIONAL)
- โ
If using Embedded Flow: Generate embedded payment links (webhook REQUIRED)
- โ
Parse HTML response correctly to extract payment link URL
- โ
Handle problem responses appropriately
Complete the full payment flow:
- โ
Navigate to payment link successfully
- โ
Select a payment plan from available options
- โ
Complete payment using test card
- โ
Verify successful payment confirmation page
๐ก Test Card Details
Visa: 4242424242424242
Mastercard: 5555555555554444
Declined card: 4000000000000002
Expired card: 4000000000000069
Always blocked: 4100000000000019
Use any future expiry date, any 3-digit CVC, and any name.
More test cards can be found here: https://docs.stripe.com/testing
Ensure your webhook endpoint is working correctly (REQUIRED for Embedded Flow, OPTIONAL for Regular Flow):
- โ
Configure
bookingNotificationUrl in your requests (required for Embedded Flow)
- โ
Verify webhook endpoint returns HTTP 200 status
- โ
Receive webhook POST request after successful payment
- โ
Parse webhook parameters:
agentId, bookingReference, salePrice, currency
- โ
Implement deduplication using
X-Request-ID header
- โ
Update booking status in your system based on webhook
- โ
Test webhook retry handling (temporarily return non-200 status)
โ ๏ธ Integration-Specific Requirements
Regular Flow: Webhooks are OPTIONAL but recommended for automated booking status updates.
Embedded Flow: Webhooks are REQUIRED - the embedded flow needs webhooks to notify your system of successful payments.
Verify all email notifications are sent correctly:
- โ
Agency receives deposit confirmation email
- โ
Customer receives deposit confirmation email
- โ
Email content includes correct booking reference and amount
- โ
Email addresses are configured correctly in your Slice Pay account
- โ
Check spam/junk folders during testing
Confirm transactions appear in your Slice Pay dashboard:
- โ
Log into your Slice Pay agent dashboard
- โ
Verify test transaction appears with correct details
- โ
Check transaction status shows as "Paid" or "Completed"
- โ
Confirm booking reference matches your system
- โ
Verify payment amount and currency are correct
- โ
Check payment plan details and schedule
Test various error scenarios to ensure robust error handling:
- โ
Test API parameter validation - Refer to Request Fields and Embedded Request Fields for proper field handling
- โ
Verify problem message parsing for all problem responses
- โ
Test webhook endpoint availability (if using webhooks)
- โ
Handle network timeouts and connection failures
Step-by-Step Validation #
Follow this detailed validation process to systematically test your integration. Complete each step in order,
using the staging environment and test cards.
Test your chosen integration method with a standard booking scenario:
Expected Results:
- HTTP 200 response with valid HTML
- Payment link URL extracted from
a[name="payment-link"]
- Expiry date present in
.sg-payment-link-expiry-date
- No problem messages in response
Navigate to the payment link and complete the payment process:
- Open the payment link URL in a browser
- Verify the booking details are displayed correctly
- Select a payment plan from the available options
- Enter test card details:
4242424242424242
- Complete the payment form
- Verify successful payment confirmation
๐ก Test Card Details
Use any future expiry date, any 3-digit CVC, and any name.
Check that your webhook endpoint receives the payment notification:
๐ Webhook Requirements by Integration
Regular Flow: Skip this step if you didn't include bookingNotificationUrl
Embedded Flow: This step is mandatory - webhooks are REQUIRED for embedded integration
๐ Webhook Request Details
For complete webhook request format, headers, and parameters, see the Webhook Notifications documentation section.
Validation Steps:
- Verify webhook receives POST request within 30 seconds
- Check all REQUIRED parameters are present
- Confirm
X-Request-ID header is included
- Verify your system updates booking status
- Ensure webhook returns HTTP 200 status
Verify both agency and customer email notifications:
- Agency Email: Check configured agency email inbox
- Customer Email: Provided during payment process
- Content Verification: Booking reference, amount, payment plan details
- Email Delivery: Check main inbox and spam folders
Log into your Slice Pay dashboard and verify the transaction:
- Access your Slice Pay agent dashboard
- Navigate to recent transactions or bookings
- Find the test transaction by booking reference
- Verify all details match your test parameters
- Check payment status and schedule
Production Readiness #
Before deploying to production, ensure all systems are properly configured and monitored. This checklist
covers the final steps to make your integration production-ready.
- โ
Use production
agentId (different from staging)
- โ
Store
agentId securely (environment variables, secrets manager)
- โ
Never expose
agentId in client-side code
- โ
Use HTTPS for all webhook endpoints
- โ
Implement webhook token validation if needed
- โ
Configure proper Content Security Policy
- โ
Set up secure logging (avoid logging sensitive data)
- โ
Monitor webhook endpoint availability and response times
- โ
Set up alerts for webhook failures or timeouts
- โ
Monitor API request success rates and problem responses
- โ
Track problem messages in production responses
- โ
Set up email notification monitoring
- โ
Configure dashboard access for operations team
- โ
Implement transaction reconciliation processes
- โ
Update API URLs to production:
https://api.slicepay.travel
- โ
Configure production webhook URLs (no test domains)
- โ
Set up production email addresses for notifications
- โ
Verify domain allowlist includes production domains
- โ
Test production configuration with small transaction
- โ
Document production vs staging differences
- โ
Prepare rollback plan if issues occur
- โ
Train customer support team on Slice Pay process
- โ
Document troubleshooting procedures
- โ
Set up escalation path to Slice Pay support
- โ
Prepare customer communication templates
- โ
Test support scenarios (refunds, failed payments)
- โ
Establish monitoring responsibilities
- โ
Schedule post-launch review meeting
๐ฏ Go-Live Strategy
Consider a gradual rollout: Start with a subset of bookings or specific routes to minimize risk.
Monitor closely for the first 24-48 hours and be prepared to quickly resolve any issues.
Troubleshooting #
Common issues encountered during integration validation and their solutions. If you encounter problems
not covered here, contact support@slicepay.travel with
your complete request and response details.
Symptoms: API returns 400/500 error or problem message
Common Causes & Solutions:
- Invalid agentId: Verify you're using correct staging/production agent ID
- Missing parameters: Check all REQUIRED fields are included
- Wrong content-type: Ensure
application/x-www-form-urlencoded is used
- Invalid currency: Use supported ISO 4217 codes
- Date format: Use ISO 8601 format (YYYY-MM-DD) for departureDate
Symptoms: Payment completes but webhook endpoint not called
Applies to: Embedded Flow (REQUIRED) or Regular Flow with OPTIONAL webhook configured
Common Causes & Solutions:
- Domain not allowlisted: Contact support to authorize your webhook domain
- HTTPS REQUIRED: Webhook URLs MUST use HTTPS, not HTTP
- URL format: Ensure no query parameters in bookingNotificationUrl
- Endpoint returns non-200: Webhook endpoint MUST return HTTP 200
- Timeout: Endpoint MUST respond within 30 seconds
- Network issues: Verify endpoint is publicly accessible
๐ Webhook Implementation Examples
For complete webhook implementation examples and testing methods, see the
Webhook Notifications documentation section.
Symptoms: Payment successful but no confirmation emails sent
Common Causes & Solutions:
- Email not configured: Contact support to set up agency email notifications
- Spam filtering: Check spam/junk folders for emails
- Email delay: Emails MAY take up to 5 minutes to arrive
- Invalid email address: Verify customer email was entered correctly
- Email server issues: Temporary delivery delays can occur
Symptoms: Payment form errors or payment failures
Common Causes & Solutions:
- Wrong test cards: Use documented test cards in staging
- Expired payment link: Links expire after a set period, create new ones
- Browser issues: Try different browsers or incognito mode
- JavaScript errors: Check browser console for errors
- CSP issues: Configure Content Security Policy
Symptoms: Transactions not appearing in Slice Pay dashboard
Common Causes & Solutions:
- Wrong environment: Ensure you're checking staging vs production dashboard
- Dashboard access: Contact support to set up dashboard access
- Delay in updates: Transactions MAY take a few minutes to appear
- Wrong agent ID: Verify you're using correct agent ID for environment
๐ง Need Help?
If troubleshooting doesn't resolve your issue, contact support@slicepay.travel with:
- Complete API request (including headers and body)
- Full API response (including any error messages)
- Booking reference and timestamp
- Environment (staging/production)
- Steps you've already tried
Problem Responses #
Learn how to handle errors and problems that can occur when integrating with the Slice Pay API.
Problem messages can appear in any response and SHOULD be handled appropriately.
โ ๏ธ IMPORTANT
Integrating with the Problem API is a critical part of the integration. We'll require the message you
received from the response including the request parameters to troubleshoot any issues you might have.
We recommend to alert engineers whenever a response contains a problem message in production from a
response with HTTP 2xx status code as that indicates an important problem that requires dev attention.
Problem Response Examples #
Problem messages are OPTIONAL elements that can be queriable from ANY response from the server, regardless
of the status code. Although they're more often visible on 4xx and 5xx status code responses, they can
also be visible in 2xx status codes as well.
When an error occurs, the API returns HTML containing error details that you can parse and handle
appropriately.
<html>
<section class="sg-problem">
<h1 class="sg-problem-title">Invalid currency code provided</h1>
<p class="sg-problem-description">The currency code 'UNK' is not supported. Please use a valid currency code.</p>
</section>
</html>
Even successful responses can contain problem messages that indicate important issues requiring attention.
<html>
<a name="payment-link" href="https://pay.slicepay.travel/link/abc123">Pay with Slice Pay</a>
<section class="sg-problem">
<h1 class="sg-problem-title">Deprecated parameter used</h1>
<p class="sg-problem-description">The parameter 'oldParam' is deprecated and will be removed in v2. Please use 'newParam' instead.</p>
</section>
</html>
โ ๏ธ Problem Handling
Always check for problem messages in ALL responses, regardless of HTTP status code. Parse the HTML response to extract any problem messages for proper handling and monitoring.
Problem Message Classes #
Problem messages are OPTIONAL elements that can be queriable from ANY response from the server, regardless
of the status code. Although they're more often visible on 4xx and 5xx status code responses, they can
also be visible in 2xx status codes as well.
The way you handle problems is by looking up certain classes in the HTML response that represent the
details of the problem.
A container for a problem. You can have multiple problems in any given response.
A shorthand dynamic title to identify the category of the error for human readers
Example: Agent is not authorised
A longhand dynamic description of the error for human readers
Example: The agent "agent-123" is missing necessary permissions A, B and C to be able to perform this action.
Supported HTTP Status Codes #
The API follows the HTTP Status Codes semantics.
| Status Code |
Description |
500 Internal Server Error |
The server has encountered a situation it does not know how to handle. |
400 Bad Request |
The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
Usually happens when a documented REQUIRED parameter is missing or the format doesn't match the media type.
For example: sending a {"param":"value","param2":"value2"} string instead of param=value¶m2=value2 for Content-Type: application/x-www-form-urlencoded requests.
|
415 Unsupported Media Type |
The media format of the requested data is not supported by the server, so the server is rejecting the request.
For example: sending a request with Accept: */* when the server only accepts Accept: text/html
|
Error Handling Examples #
JavaScript Error Response Handling (ES6) #
const parse = html => new JSDOM(html).window.document;
// Make request
const url = 'https://api.staging.slicepay.travel/api/create-link';
const response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
//salePrice: '100000', // <-- Missing required field "salePrice"
currency: 'AUD',
departureDate: '2030-10-01',
bookingReference: 'ABC123',
agentId: 'agent-bypass-5kyp4y'
}).toString()
});
// Response Handling
const responseBody = await response.text();
const problemTitle = parse(responseBody).querySelector('.sg-problem .sg-problem-title')?.textContent;
const problemDescription = parse(responseBody).querySelector('.sg-problem .sg-problem-description')?.textContent;
if (problemTitle && response.status === 400) {
const problemDetails = {
problemTitle: problemTitle.trim(),
problemDescription: (problemDescription || '').trim()
};
handleError(problemDetails);
} else {
throw new Error(`Unexpected response: ${response.status} ${responseBody}`);
}
๐ก Error monitoring
Always implement proper error monitoring and logging for problem responses, especially those with
HTTP 2xx status codes that contain problem messages.
โน๏ธ Production alerts
Set up alerts for your engineering team when problem messages are detected in production responses
to ensure quick resolution of issues.