BlueSnap offers a white-labeled hosted application for partners that want to go live quickly and provide their merchants with a branded application experience. After we launch your application, it receives updates automatically, which means you do not have to devote development resources to creating, deploying, or maintaining your custom merchant application.
During partner onboarding, you provide your implementation team your corporate logo and your primary brand color to use for the call-to-action button on each page. Our team will add your branding to the application so you can get started with minimal effort. The only indication that you use a hosted solution is that bluesnap
is present in the application URL.
In addition to the simplified implementation and maintenance efforts, the white-labeled hosted solution offers a more streamlined application workflow. Merchants do not have to sign up for a BlueSnap test account before submitting their application account—the white-labeled solution submits an application account directly. After the application submission, the merchant is redirected to your platform's website. BlueSnap does not send an email verification directly to your merchant.
Implementation Workflows
The white-labeled hosted application requires minimal development effort to redirect merchants from your platform to our hosted application. We authenticate the merchant with a JSON web token (JWT) that expires in 24 hours so merchants complete the application across multiple sessions. If the 24 hour timeframe is not sufficient, you can refresh the token with another API request.
Prerequisites
Before you begin, you need to complete the following:
- Go to New Signup and create a BlueSnap Sandbox Account.
- Get API credentials from your BlueSnap implementation team.
Initial Request
Your platform must have a submit button with an event listener that sends a POST request to the Create Hosted Application API. The request creates an application account for the merchant. Here is a sample cURL request to demonstrate the payload:
curl -v -X POST https://platform.bluesnap.com/services/services/2/merchants/partner-side-initiated-submission \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
-d '
{
"userId": "12345",
"returnUrl": "https://example.com/return",
"refreshUrl": "https://example.com/refresh",
"successUrl": "https://example.com/success",
"merchantInfo": {
"email": "[email protected]"
}
}`
In this request payload contains the following information:
userId
— Identify the merchant with a custom ID that you create and send to identify the merchant application to BlueSnap. BlueSnap saves this value to authenticate the merchant if they complete their application across multiple sessions.
Alternatively, you can omituserId
and let BlueSnap generate a unique ID and return it in the response.userId
andbluesnapId
are the only ways to authenticate the user after they begin the application.refreshUrl
— URL that can reset the 24-hour expiration on the JWT if the merchant tries to complete their application after the JWT expired. This also gives the merchant the option to save their progress and return at a later time. For details, see Token Refresh.merchantInfo.email
— Required to identify the merchant.
Initial Response
The response to this request includes a URL for the white-labeled hosted application. Redirect your merchant to this URL to complete the BlueSnap merchant application.
The URL includes the JWT that is appended to the URL as a query string:
{
"userId": "12345",
"bluesnapId": "1234567",
"url": "https://sandbox.bluesnap.com/jsp/merchant_application.jsp?jwt=eyJhbGciOiJIUzI1NiJ9.eyJwYXlsb2FkIjp7ImNvbW1vbkp3dFBheWxvYWQiOnsiaWQiOiI1OTU4NTkxODYxNTgwMDg5OTI3NzEiLCJtZXJjaGFudElkIjo0MDAwNDgsImRhdGVDcmVhdGVkIjoxNjA2OTk2MjI5OTExLCJlbnYiOiJERVY2In0sImN1cnJlbmN5IjoiVVNEIiwic3VjY2Vzc1VybCI6Imh0dHBzOi8vaG9tZS5ibHVlc25hcC5jb20iLCJjYW5jZWxVcmwiOiJodHRwczovL2FwLmJsdWVzbmFwLmludDo0MDA0L2NhbmNlbCIsIm1lcmNoYW50VHJhbnNhY3Rpb25JZCI6IjU5NTg1OTE4NjE1ODAwODk5Mjc3MSIsImxpbmVJdGVtcyI6W3siaWQiOiJpZDEiLCJsYWJlbCI6IlJhaW5ib3ciLCJkZXNjcmlwdGlvbiI6IlRvdWNoIHRoZSBSYWluYm93IiwicXVhbnRpdHkiOjEsImFtb3VudCI6MTAuMCwiaW1nVXJsIjpudWxsfV19fQ.Mi4eiNKCsGDTsLHnTXPfe4-UNpQYSY-OvKufwZr2jR0"
}
Token Refresh
The JWT expires after 24 hours. If the user needs to go back and complete the application after expiration, BlueSnap will redirect them to the refreshUrl
that you provided in the initial request.
The refreshUrl
should accept the either the merchant's userId
or bluesnapId
as a query string parameter. For example:
https://example.com/refresh?userId=12345
After you extract the ID from the query string, send the ID in a request to BlueSnap:
curl -v -X POST https://platform.bluesnap.com/services/services/2/merchants/partner-side-initiated-submission \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
-d '
{
"userId": "12345",
"returnUrl": "https://example.com/return",
"refreshUrl": "https://example.com/refresh",
"successUrl": "https://example.com/success"
}`
The response includes a url
with the refreshed JWT. Redirect the user to this URL to complete the application:
{
"bluesnapId": "12345",
"url": "https://sandbox.bluesnap.com/jsp/merchant_application.jsp?jwt=<jwt-string>"
}
If BlueSnap cannot authenticate the bluesnapId
, we return a 404 error. If we cannot authenticate the userId
, we create a new account and redirect the user to a new form. We save the userId for future authentication.
If the link expired and you didn’t send a refreshUrl
in the initial request, we display a screen with an error message. To refresh the token, the merchant must navigate back to your platform and and select the submit application button to restart the application process.
Sample Implementation
This section contains a sample application to help you understand the implementation flow. You will need to replace variable values with your environment and merchant information.
Note
This code is not suitable for production. It demonstrates the workflows necessary to implement the white-labeled hosted application, and it includes minimal HTML and CSS. Each step provides a general description of the relevant code sample. For additional details, refer to the comments in each sample.
Step 1: Install Dependencies
-
The server uses Node.js and the npm package manager. To verify that you have these dependencies, run the following commands in your terminal:
npm -v node -v
-
Install the package dependencies. Create a file named
package.json
at the root of your project, and copy the following JSON into that file:{ "name": "whitelabel-flow-demo", "version": "1.0.0", "description": "", "main": "partnerBackendExample.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "private": true, "dependencies": { "cors": "^2.8.5", "express": "^5.1.0", "node-fetch": "^2.7.0" } }
-
To install the package dependencies, run the following command in your terminal:
npm install
Step 2: Server Implementation
Create a server.js
file at the root of your project, and copy this code into the file:
const express = require("express");
const fetch = require("node-fetch");
const cors = require("cors");
const app = express();
app.use(express.json());
app.use(cors());
// Bluesnap API credentials
const api_key = "my_api_key";
const password = "password";
// White-labeled Hosted Application endpoint
const applicationEndpoint =
"https://sandbox.bluesnap.com/services/2/merchants/partner-side-initiated-submission";
/**
* Creates the payload object for BlueSnap's Partner Submission API.
* @param {string} userId - Internal ID that identifies the merchant
* @param {string|undefined} bluesnapId - ID assigned to the merchant by BlueSnap
* @param {string} email - Merchant's email address
* @returns {Object} JSON payload with merchant information and redirect URLs
*/
function preparePayload(userId, bluesnapId, email) {
return {
userId,
bluesnapId,
successUrl: `https://example.com/submission?result=success&uniqueId=${userId}`,
refreshUrl: `https://example.com/submission/refresh?uniqueId=${userId}`,
returnUrl: `https://example.com/submission?action=return&uniqueId=${userId}`,
merchantInfo: {
email,
},
};
}
// POST /start-submission
// Proxies a BlueSnap Hosted Application API request.
//
// Accepts JSON body with merchant information: uniqueId, optional bluesnapId,
// and email.
// Authenticates with BlueSnap and returns the hosted application URL or error.
app.post("/start-submission", async (req, res) => {
const { userId, bluesnapId, email } = req.body;
const reqBody = preparePayload(userId, bluesnapId, email);
const credentials = btoa(`${api_key}:${password}`);
const response = await fetch(applicationEndpoint, {
method: "POST",
headers: {
Authorization: `Basic ${credentials}`,
"Content-Type": "application/json",
},
body: JSON.stringify(reqBody),
});
const data = await response.json();
res.status(response.status).json(data);
});
// Start the server on port 3001
app.listen(3001, () => console.log("Proxy server running on port 3001"));
The server proxies a request to the Create Hosted Application API. It includes a route handler that sends your merchant information in a request to BlueSnap and returns a response object containing the redirect URL.
Step 3: Start Application
Your frontend should collect the required merchant information and send it in a request to the /start-submission
endpoint defined in server.js
. This example implementation provides sample userId
and email
values, but production implementations should collect this information with an HTML form. Here is a sample sequence diagram to illustrate the flow:

Code Sample
Create a start-application.htmls
file at the root of your project, and copy this code into the file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Merchant Application</title>
<style>
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
font-family: sans-serif;
}
button {
padding: 20px 40px;
font-size: 1.5rem;
border: none;
border-radius: 8px;
background-color: #007bff;
color: white;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<button id="startBtn">Start merchant application</button>
<script>
// Get Application button and start merchant app on click
document.getElementById('startBtn').addEventListener('click', startMerchantAppSubmission);
// Define merchant values, extract uniqueId parameter from URL
const userId = new URLSearchParams(window.location.search).get('uniqueId')
const email = '[email protected]'
const bluesnapId = undefined
const backendUrl = 'http://partner-domain.com/start-submission'
/**
* Sends application request to backend and redirects merchant to BlueSnap.
* Gathers merchant details and calls /start-submission on the backend.
* If successful, redirects the user to BlueSnap's hosted application URL.
*/
async function startMerchantAppSubmission() {
const headers = new Headers();
const data = preparePayload(userId, bluesnapId, email)
headers.append('Content-Type', 'application/json');
try {
const response = await fetch(backendUrl, {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
})
if (!response.ok) {
throw new Error("Http error. Status:" + response.status)
}
const { url, bluesnapId, uniqueId } = await response.json()
// Redirect the merchant to URL
if (url) {
redirectToBluesnap(url)
}
} catch (err) {
console.log(err)
}
}
/**
* Helper function that creates the payload for merchant application via
* backend proxy.
* @param {string} userId - Internal ID that identifies the merchant
* @param {string|undefined} bluesnapId - ID assigned to the merchant by BlueSnap
* @param {string} email - Merchant email address
* @returns {Object} Payload sent to backend to start merchant application
*/
function preparePayload(userId, bluesnapId, email) {
return {
userId,
bluesnapId,
email
}
}
/**
* Helper function that navigates the user to the given BlueSnap URL.
* @param {string} url - URL provided by BlueSnap with JWT token
*/
function redirectToBluesnap(url) {
window.location.href = url
}
</script>
</body>
</html>
Step 4. Refresh Token
To refresh the token, you need to extract either the userId
or bluesnapId
from the URL's query parameters and send it in a request to your start-submission
route on your server. The BlueSnap server authenticates your user and replies with a URL and JWT token. Here is a sample sequence diagram to illustrate the flow:

Code Sample
Create a refresh-token.htmls
file at the root of your project, and copy this code into the file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Merchant Application</title>
<style>
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
font-family: sans-serif;
}
</style>
</head>
<body>
<h1>Refreshing the token. It can take some time...</h1>
<script>
// Get values from session for request payload
const uniqueId = new URLSearchParams(window.location.search).get('uniqueId') // userId or bluesnapId
const email = '[email protected]'
const bluesnapId = undefined
const backendUrl = 'http://partner-domain.com/start-submission'
/**
* Sends application request to backend and redirects merchant to BlueSnap.
* Gathers merchant details and calls /start-submission on the backend.
* If successful, redirects the user to BlueSnap's hosted application URL.
*/
async function startMerchantAppSubmission() {
const headers = new Headers();
const data = preparePayload(userId, bluesnapId, email)
headers.append('Content-Type', 'application/json');
try {
const response = await fetch(backendUrl, {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
})
if (!response.ok) {
throw new Error("Http error. Status:" + response.status)
}
const { url, bluesnapId, userId } = await response.json()
if (url) {
redirectToBluesnap(url)
}
} catch (err) {
console.log(err)
}
}
/**
* Helper function that creates the payload for merchant application via
* backend proxy.
* @param {string} userId - Internal ID that identifies the merchant
* @param {string|undefined} bluesnapId - ID assigned to the merchant by BlueSnap
* @param {string} email - Merchant email address
* @returns {Object} Payload sent to backend to start merchant application
*/
function preparePayload(userId, bluesnapId, email) {
return {
userId,
bluesnapId,
email
}
}
/**
* Helper function that navigates the user to the given BlueSnap URL.
* @param {string} url - URL provided by BlueSnap with JWT token
*/
function redirectToBluesnap(url) {
window.location.href = url
}
// just call the refresh of the authentication token immediately
startMerchantAppSubmission()
</script>
</body>
</html>
Step 5: Start the Server
To start the server, run this command in your terminal:
node server.js