Quickstart
Create a checkout session, mount the iframe, and listen for payment events. This is the public reference - pre-approval merchants can read every snippet here without signing in.
1. Create a checkout session
Your server hits POST /api/v1/checkout_sessions with a secret key. The response gives you a session id you pass to the browser. The body never carries card data.
// server-side — Node.js / TypeScript
const response = await fetch("https://veyragate.com/api/v1/checkout_sessions", {
method: "POST",
headers: {
"Authorization": "Bearer vg_sk_test_...",
"Content-Type": "application/json",
"Idempotency-Key": orderId, // optional but recommended
},
body: JSON.stringify({
amount_cents: 4299,
currency: "usd",
customer_email: "customer@example.com",
description: "Order #1001",
return_url: "https://store.example.com/order-received/1001",
allowed_origin: "https://store.example.com",
metadata: { order_id: "1001" },
}),
});
const session = await response.json();
// session.id - pass to the browser
// session.embed_url - the iframe URL (Veyra.mount uses session.id directly)
// session.expires_at - session is valid for 60 minutes by default2. Mount the iframe
Drop the Veyra script tag onto your checkout page and call Veyra.mount with the session id. The iframe takes over card entry; your page never sees the card data.
<!-- public/checkout.html -->
<script src="https://veyragate.com/v1/checkout.js"></script>
<div id="veyra-checkout"></div>
<script>
const handle = Veyra.mount("#veyra-checkout", {
sessionId: "vcs_...", // the id returned by /v1/checkout_sessions
onReady(event) {
console.log("checkout iframe ready", event);
},
onSuccess(event) {
// event = { payment_id, session_id, return_url, ... }
window.location.href = event.return_url;
},
onError(event) {
console.error("checkout error", event);
},
});
</script>3. Verify the webhook
Veyra POSTs payment.succeeded (and payment_failed, charge.refunded, dispute.created) to your endpoint with an HMAC-SHA256 signature. Verify it before trusting the payload.
// server-side - Node.js, on your webhook endpoint
const crypto = require("node:crypto");
function verifyVeyraWebhook(rawBody, headerValue, secret) {
if (!headerValue) return false;
let timestamp = null;
const signatures = [];
for (const part of headerValue.split(",")) {
const [k, v] = part.trim().split("=", 2);
if (k === "t") timestamp = parseInt(v, 10);
else if (k === "v1") signatures.push(v);
}
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return signatures.some(
(sig) =>
sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)),
);
}For full verification snippets in 7 languages, see Verifying webhook signatures.
Next
- Use the test cards to exercise every success and decline branch without touching real funds.
- Read Errors & idempotency to handle declines and safely retry POSTs.
- Apply for a merchant account to mint your own
vg_sk_test_...key and run the snippets above end-to-end.