Skip to main content

Integration Guide

This guide walks you through integrating Paystar Embedded into your website step by step.

Prerequisites

Before you begin, you'll need:

  1. API Credentials from Paystar — an API Key and a Business Unit Slug (contact your Account Manager)
  2. A backend server to store your API key securely and make API calls to create sessions
  3. HTTPS in production (localhost works for development)

Step 1: Install the SDK

Add the Paystar SDK snippet to your HTML. This creates a lightweight command queue that buffers method calls while the full SDK loads asynchronously.

<script>
!(function () {
var n = (window.Paystar = window.Paystar || []);
if (!n.x) {
((n.x = !0),
(n.m = [
"initialize",
"completePayment",
"startFlow",
"subscribe",
"destroy",
]),
(n.f = function (t) {
return function () {
var e = Array.prototype.slice.call(arguments);
(e.unshift(t), n.push(e), n);
};
}));
}
for (var o = 0; o < n.m.length; o++) {
var c = n.m[o];
n[c] = n.f(c);
}
((n.load = function (t, e) {
var sdkUrl = "https://dev.paystar.io/app/embedded.loader.js";
n._loadOptions = e;
n._dismissError = function () {
var d = document.getElementById("paystar-error");
if (d) {
d.close();
d.remove();
}
var s = document.getElementById("paystar-error-style");
if (s) s.remove();
};
n._showError = function () {
n._dismissError();
var s = document.createElement("style");
s.id = "paystar-error-style";
s.textContent = "#paystar-error::backdrop{background:#000000ba}";
document.head.appendChild(s);
var d = document.createElement("dialog");
d.id = "paystar-error";
d.style.cssText =
"border:0;padding:0;width:530px;max-width:100%;height:100%;max-height:calc(100vh - 4rem);margin:2rem auto;box-shadow:0 0 6px 2px #00000078;display:flex;align-items:center;justify-content:center;font-family:Poppins,sans-serif";
d.innerHTML =
'<button onclick="window.Paystar._dismissError()" style="position:absolute;top:8px;right:8px;background:none;border:0;font-size:1.25rem;cursor:pointer;color:#555">&times;</button><p style="margin:0;padding:2rem;font-size:1.15rem;color:#333;text-align:center;text-align:balance"><strong style="font-size:2rem">Something went wrong.</strong><br><br>This may be caused by a VPN, proxy, or connection from outside the United States. Please disable any such services, connect directly from a US-based network, and try again.</p>';
d.addEventListener("close", function () {
n._dismissError();
});
d.addEventListener("click", function (e) {
if (e.target === d) n._dismissError();
});
document.body.appendChild(d);
d.showModal();
};
var a = document.createElement("script");
a.type = "text/javascript";
a.async = true;
a.src = sdkUrl;
a.onerror = function () {
n.completePayment = function () {
n._showError();
};
n.startFlow = function () {
n._showError();
};
n.initialize = function () {};
n.destroy = function () {
n._dismissError();
};
n.subscribe = function () {};
};
var r = document.getElementsByTagName("script")[0];
r.parentNode.insertBefore(a, r);
}),
(n.SNIPPET_VERSION = "0.2.0"));
Paystar.initialize();
Paystar.load();
})();
</script>

Step 2: Create Sessions (Backend)

All sessions must be created from your backend server. Each session type has its own endpoint and returns a session URL.

Error Handling

If a session creation call fails (network error, validation error, non-success response, etc.), Paystar Embedded will not have a session URL to display — your application is responsible for catching the error and showing an appropriate message to the user.

Payment Session

Create a session for one-time payments. Accounts in Charges[].ClientAccount are automatically synced to Paystar — no flag needed. Future requests with the same account update the record.

async function createPaymentSession(amount, description) {
const response = await fetch(
"https://dev-gateway.paystar.io/integrations/embedded/initiate",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Paystar-Api-Key": process.env.PAYSTAR_API_KEY,
},
body: JSON.stringify({
BusinessUnitSlug: "your-business-unit-slug",
Channel: "QuickPay",
Charges: [
{
Description: description,
Amount: amount, // Amount in cents: 15000 = $150.00
},
],
// Optional: Include customer info to enable wallet features
// and attribute the payment to a customer
ClientUser: {
EmailAddress: "[email protected]",
FirstName: "John",
LastName: "Doe",
},
}),
},
);

const result = await response.json();
return result.data.PaymentLogInLink;
}

AutoPay Session

Create a session for autopay enrollment. Set SyncAccount: true to sync the account to Paystar (required when introducing a new account). ClientUser is always automatically synced.

async function createAutopaySession(accountNumber, customerEmail) {
const response = await fetch(
"https://dev-gateway.paystar.io/integrations/embedded/initiate-manage-autopay",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Paystar-Api-Key": process.env.PAYSTAR_API_KEY,
},
body: JSON.stringify({
BusinessUnitSlug: "your-business-unit-slug",
SyncAccount: true,
ClientAccount: {
AccountNumber: accountNumber,
Name: "John Doe",
},
ClientUser: {
EmailAddress: customerEmail,
FirstName: "John",
LastName: "Doe",
},
}),
},
);

const result = await response.json();
return result.data.SessionLink;
}

Wallet Session

Create a session for payment method management. Wallet sessions are per-customer (no ClientAccount). ClientUser is always automatically synced.

async function createWalletSession(customerEmail) {
const response = await fetch(
"https://dev-gateway.paystar.io/integrations/embedded/initiate-manage-wallet",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Paystar-Api-Key": process.env.PAYSTAR_API_KEY,
},
body: JSON.stringify({
BusinessUnitSlug: "your-business-unit-slug",
ClientUser: {
EmailAddress: customerEmail,
FirstName: "John",
LastName: "Doe",
},
}),
},
);

const result = await response.json();
return result.data.SessionLink;
}

Paperless Session

Create a session for paperless billing enrollment. Set SyncAccount: true to sync the account (required when introducing a new account). ClientUser is always automatically synced.

async function createPaperlessSession(accountNumber, customerEmail) {
const response = await fetch(
"https://dev-gateway.paystar.io/integrations/embedded/initiate-manage-paperless",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Paystar-Api-Key": process.env.PAYSTAR_API_KEY,
},
body: JSON.stringify({
BusinessUnitSlug: "your-business-unit-slug",
SyncAccount: true,
ClientAccount: {
AccountNumber: accountNumber,
},
ClientUser: {
EmailAddress: customerEmail,
},
}),
},
);

const result = await response.json();
return result.data.SessionLink;
}

Notification Session

Create a session for managing email/SMS notification preferences. ClientUser is always automatically synced.

async function createNotificationSession(customerEmail) {
const response = await fetch(
"https://dev-gateway.paystar.io/integrations/embedded/initiate-manage-notifications",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Paystar-Api-Key": process.env.PAYSTAR_API_KEY,
},
body: JSON.stringify({
BusinessUnitSlug: "your-business-unit-slug",
ClientUser: {
EmailAddress: customerEmail,
FirstName: "John",
LastName: "Doe",
},
}),
},
);

const result = await response.json();
return result.data.SessionLink;
}

Step 3: Open Sessions (Frontend)

Once you have a session URL from your backend, use the SDK to open it.

Payment Sessions

Use completePayment() to open payment sessions:

Paystar.completePayment(sessionUrl, {
onComplete: function (result) {
console.log("Payment completed!", result);
},
});

All Other Flows

Use startFlow() for AutoPay, Wallet, Paperless, and Notification sessions:

Paystar.startFlow(sessionUrl, {
onEvent: function ({ event, data }) {
console.log("Event:", event, "Data:", data);
},
});

See the SDK Reference for the full options available on each method.

Step 4: Handle Events

Subscribe to events to track user actions:

const unsubscribe = Paystar.subscribe(
"PAYMENT-SESSION.PROCESSED",
function (data) {
console.log("Payment processed:", data);
},
);

// Later: unsubscribe if needed
unsubscribe();

See the Events page for all available events and their payloads.

Step 5: Customize (Optional)

Custom Container

Instead of the default modal, embed the form directly in your page:

<div id="payment-container" style="height: 600px; width: 100%;"></div>

<script>
Paystar.completePayment(sessionUrl, {
container: "#payment-container",
});
</script>

See the SDK Reference for container requirements.

Security Best Practices

warning

Follow these rules to keep your integration secure:

  1. Never expose your API key in client-side code, HTML, or JavaScript
  2. Always create sessions from your backend — the frontend only receives session URLs
  3. Validate webhook signatures if using webhooks
  4. Use HTTPS in production — localhost is acceptable for development only