Skip to main content

Events

Events let you track user actions and respond to changes in real-time. For server-side notifications, see Webhooks.

How to Listen

Method 1: Subscribe to Specific Events

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

// Later: unsubscribe
unsubscribe();

Method 2: Handle All Events via Callback

Pass an onEvent callback when opening a session:

// For payment sessions
Paystar.completePayment(sessionUrl, {
onEvent: function ({ event, data }) {
switch (event) {
case "PAYMENT-SESSION.PROCESSED":
handlePaymentProcessed(data);
break;
case "COMPONENT.DISMISS":
handleFormClosed();
break;
}
},
});

// For other flows (AutoPay, Wallet, Paperless, Notifications)
Paystar.startFlow(sessionUrl, {
onEvent: function ({ event, data }) {
console.log("Event:", event, "Data:", data);
},
});

Event Reference

General Events

COMPONENT.DISMISS

Fires when: User dismisses the form/modal (clicks X, presses ESC, or clicks outside the modal)

Data: none

FRAME.LOADED

Fires when: The embedded iframe has finished loading and is ready

Data: none


Payment Events

PAYMENT-SESSION.LOADED

Fires when: The payment form is ready for user interaction

Data: PaymentIntentDetailDto — the full payment session object

PAYMENT-SESSION.UPDATED

Fires when: Payment session details change (e.g., user selects a payment method)

Data: PaymentIntentDetailDto — the updated payment session object

PAYMENT-SESSION.PROCESSED

Fires when: The user has submitted a payment for processing

Data: PaymentIntentDetailDto — the final payment session object:

{
sessionIdentifier: "abc123...",
status: "Succeeded" | "Failed" | "Pending",
subtotal: 150.00,
channel: "QuickPay" | "POS",
lineItems: [
{ description: "January Water Bill", price: 150.00 }
],
paymentSource: {
paymentSourceType: "CreditCard" | "ACH",
accountNumberMasked: "****1234",
nickname: "Personal Card",
},
serviceFeeCalculation: {
amount: 2.50,
},
}

AutoPay Events

AUTOPAY-SESSION.ENROLLED

Fires when: User successfully enrolls in AutoPay

Data: AutopayEnrollmentSettings

{
enrolled: true,
processingLeadTimeInDays: 5,
maximumBalanceAllowed: 500,
paymentSourceId: 123
}

AUTOPAY-SESSION.UNENROLLED

Fires when: User cancels their AutoPay enrollment

Data: none

AUTOPAY-SESSION.SCHEDULED_PAYMENT_CANCELED

Fires when: A pending scheduled AutoPay payment is canceled

Data: none


Paperless Events

PAPERLESS-SESSION.ENROLLED

Fires when: User opts into paperless billing

Data: none

PAPERLESS-SESSION.UNENROLLED

Fires when: User opts out of paperless billing

Data: none

PAPERLESS-SESSION.UPDATED

Fires when: User updates their paperless billing preferences

Data: none


Wallet Events

PAYMENT-SOURCES.ADDED

Fires when: User adds a new payment method

Data: none

PAYMENT-SOURCES.REMOVED

Fires when: User removes a payment method

Data: none


Notification Events

NOTIFICATIONS.UPDATED

Fires when: User updates their notification preferences (email/SMS)

Data: none


Complete Example

A full HTML page showing event handling for a payment flow:

<!DOCTYPE html>
<html>
<head>
<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>
</head>
<body>
<button id="pay-button">Pay $150</button>
<div id="status"></div>

<script>
// Subscribe to events globally
Paystar.subscribe("PAYMENT-SESSION.PROCESSED", function (data) {
document.getElementById("status").innerText = "Payment " + data.status;
});

Paystar.subscribe("COMPONENT.DISMISS", function () {
document.getElementById("status").innerText = "Payment cancelled";
});

// Handle button click
document.getElementById("pay-button").onclick = async function () {
const response = await fetch("/api/create-payment-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ amount: 15000 }),
});
const { sessionUrl } = await response.json();

Paystar.completePayment(sessionUrl, {
onComplete: function (result) {
console.log("Payment result:", result);
},
});
};
</script>
</body>
</html>

Troubleshooting

Events Not Firing?
  • Verify Paystar.initialize() was called (the SDK snippet does this automatically)
  • Check that event names are spelled correctly — they are case-sensitive
  • Look for errors in the browser console
  • Make sure the SDK is fully loaded before subscribing
Getting Duplicate Events?
  • Check you're not subscribing multiple times (e.g., in a re-rendering component)
  • Unsubscribe before re-subscribing if your setup code runs more than once
  • Avoid using both onEvent and subscribe for the same event — pick one approach