Squarespace
Squarespace has no third-party payment gateway API at all, native or otherwise. This is a workaround: an embeddable button plus a small serverless function holding the only secret involved.
This one is different from the rest of this site, and worth saying plainly: Squarespace has no API for adding a third-party payment gateway, full stop. Squarespace Payments, Stripe, PayPal, and Square cover the entire native commerce surface, and Squarespace’s own documentation is explicit that custom code on a Squarespace site is front-end only — there’s no server-side extension point to hook a new payment method into. Anything that accepts BoomPay on a Squarespace site is necessarily a workaround sitting partly outside Squarespace’s commerce system, not an integration with it.
If you need BoomPay to behave like a real checkout option — inventory sync, order history inside Squarespace, abandoned cart recovery, and so on — this isn’t that. It’s a way to accept a Boomcoin payment from a Squarespace page; everything downstream of the payment is on you to wire up.
Architecture
Button renders
A Code Block on your page embeds a plain button and a few lines of JS -- no secrets in it.
Click calls your function
The browser posts to a small serverless function you host, which holds the only API key in this whole flow.
Intent created, customer redirected
The function calls createIntent() and the browser is sent to BoomPay's hosted link.
Signed return
BoomPay redirects to your function's own /api/return route with paymentIntentId and X-Boom-Signature.
Confirmation
The function verifies the signature, re-fetches the payment, and redirects to a real page on your Squarespace site.
Files
<!-- Paste into a Squarespace Code Block on your product or cart page -->
<button id="boompay-btn" style="padding:12px 20px;font:inherit;cursor:pointer;">
Pay with Boomcoin
</button>
<script>
document.getElementById('boompay-btn').addEventListener('click', function () {
fetch('https://your-app.example.com/api/create-intent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 24.00, // set this per product/cart -- don't trust page DOM values you didn't set yourself
label: 'Order from your-store.squarespace.com',
}),
})
.then(function (r) { return r.json(); })
.then(function (data) { window.location = data.link; });
});
</script>
// api/create-intent.js -- deployable to Vercel, Netlify Functions, Render,
// or any plain Node host. Shown as a generic (req, res) handler.
const BoomPay = require('boom-pay-sdk');
const boomPay = new BoomPay({
apiKey: process.env.BOOMPAY_API_KEY,
sandbox: process.env.NODE_ENV !== 'production',
});
module.exports = async function handler(req, res) {
if (req.method !== 'POST') return res.status(405).end();
const { amount, label } = req.body;
const intent = await boomPay.payments.createIntent({
amount,
successUrl: `${process.env.APP_URL}/api/return?status=success`,
failureUrl: `${process.env.APP_URL}/api/return?status=failure`,
label,
});
res.status(200).json({ link: intent.link });
};
// api/return.js -- a bare serverless function, not an Express app, so this
// verifies the signature by hand rather than using boomPay.webhooks()
// (which is Express middleware and has nothing to mount onto here).
const crypto = require('crypto');
const BoomPay = require('boom-pay-sdk');
const boomPay = new BoomPay({
apiKey: process.env.BOOMPAY_API_KEY,
sandbox: process.env.NODE_ENV !== 'production',
});
module.exports = async function handler(req, res) {
const { paymentIntentId, status } = req.query;
const signature = (req.query['X-Boom-Signature'] || '').replace(/ /g, '+');
const expected = crypto
.createHmac('sha1', process.env.BOOMPAY_API_KEY)
.update(paymentIntentId || '')
.digest('base64');
if (!safeEqual(expected, signature)) {
return res.status(403).send('Invalid signature');
}
// Re-fetch rather than trusting anything else in the query string.
const payment = await boomPay.payments.getPayment(paymentIntentId);
if (status === 'success' && payment.paidAt) {
return res.redirect(302, 'https://your-store.squarespace.com/payment-confirmed');
}
return res.redirect(302, 'https://your-store.squarespace.com/payment-failed');
};
function safeEqual(a, b) {
const bufA = Buffer.from(a);
const bufB = Buffer.from(b);
if (bufA.length !== bufB.length) return false;
return crypto.timingSafeEqual(bufA, bufB);
}
Setup
Deploy the two function files to Vercel, Netlify Functions, Render, or any small Node host — whichever you’re already using for the rest of this site’s integrations is fine. Add the button snippet to a Squarespace Code Block on your product page or a custom page, pointing it at your deployed function’s URL. Create plain Squarespace pages for /payment-confirmed and /payment-failed for the function to redirect to.
Testing in sandbox
With sandbox mode on, click the button on a live preview of the page, confirm you land on a sapi.boom.market page, approve a test payment, and check that you’re redirected back to your confirmation page. Then trigger a cancelled or expired payment and confirm the failure path lands somewhere sensible too.
Go-live checklist
- Switch the function’s BoomPay client out of sandbox mode and use a live API key once a full test payment has gone through.
- Set the button’s
amountfrom something you control server-side per product — don’t let the page’s own JS decide the price unsupervised. - Decide how order fulfillment actually happens once a payment lands, since Squarespace’s own order management never sees this transaction at all.