Build an Advanced Kayana Integration with Stripe in Node.js
Last updated Mar 10, 2026
Build an advanced Kayana integration to securely collect card payments using Kayana’s Payment API powered by Stripe for your e-commerce store.
Overview
The Kayana Payment API enables you to accept payments without building your own PCI-compliant checkout.
This guide walks you through integrating the Stripe Embedded Checkout flow using Node.js in sandbox mode.
What You’ll Build
In this guide you will:
- Create a payment instance on your Node.js server
- Retrieve the Stripe publishable key
- Initialise Stripe on the frontend
- Render Stripe’s secure Embedded Checkout capsule
- Complete the payment securely
Before You Begin
You’ll need:
- A Kayana property ID
- Access to the sandbox environment
- Basic knowledge of Node.js
- A Node.js backend server
- A React / Next.js frontend
Sandbox vs Production
Sandbox
Safe test environment
- Uses Stripe test keys
- No real transactions
- Ideal for development and testing
Production
- Requires authorisation token
- Uses live Stripe keys
- Processes real payments
How It Works
The Stripe payment flow consists of:
Server-side (Node.js)
Create a payment instance using Kayana’s API.
Server receives
client_secretpublishable_key
Client-side
Initialise Stripe and render Embedded Checkout
Stripe
Handles payment confirmation securely.
Server Setup (Node.js)
Base URL
Sandbox:
https://integration.dev.kayana.co.uk
Step 1 - Create a Payment (Node.js Backend)
Create a Node.js API endpoint that calls Kayana’s payment API.
Example using Express.js.
Install dependencies
npm install express node-fetch dotenv
Node.js Server Implementation
require("dotenv").config();
const express = require("express");
const fetch = require("node-fetch");
const app = express();
app.use(express.json());
app.post("/api/business-payment", async (req, res) => {
try {
const response = await fetch(
"https://integration.dev.kayana.co.uk/business/payment",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.KAYANA_API_KEY,
type: "business",
},
body: JSON.stringify({
property_id: "Prop_abc123example",
psp_code: "STRIPE",
currency_code: "GBP",
amount: 12.0,
customer_email: "customer@example.com",
}),
}
);
const data = await response.json();
res.json(data);
} catch (error) {
res.status(500).json({
status: false,
message: "Payment creation failed",
});
}
});
app.listen(3001, () => {
console.log("Server running on port 3001");
});
Environment Variables
Create a .env file:
KAYANA_API_KEY=YOUR_API_KEY
⚠️ Never expose this key in the frontend.
Request Parameters
| Parameter | Type | Description |
| property_id | string | Format Prop_* |
| psp_code | string | STRIPE |
| currency_code | string | GBP, EUR, USD |
| amount | number | Decimal amount (example: 12.0) |
| customer_email | string | Customer email |
Example API Response
{
"status": true,
"data": {
"instance_id": "Payment_xyz789example",
"client_secret": "cs_test_abc123_secret_xyz456",
"publishable_key": "pk_test_abc123example",
"next_step": {
"action": "FORM",
"proceed": true
},
"transaction_id": "Tx_txn456example"
}
}
Response Parameters
| Parameter | Description |
| instance_id | Unique payment instance ID |
| client_secret | Stripe Checkout session secret |
| publishable_key | Stripe public key |
| transaction_id | Internal transaction reference |
⚠️ Important
client_secret must only be used on the frontend to initialise Stripe.
Step 2 - Frontend Integration (Stripe Embedded Checkout)
Install Stripe SDK:
npm install @stripe/react-stripe-js @stripe/stripe-js
React / Next.js Frontend Implementation
"use client";
import { useState } from "react";
import { loadStripe } from "@stripe/stripe-js";
import {
EmbeddedCheckoutProvider,
EmbeddedCheckout,
} from "@stripe/react-stripe-js";
export default function PaymentPage() {
const [clientSecret, setClientSecret] = useState(null);
const [stripePromise, setStripePromise] = useState(null);
const createPayment = async () => {
const res = await fetch("http://your-server.com/api/business-payment", {
method: "POST",
});
const data = await res.json();
if (data.status) {
setStripePromise(loadStripe(data.data.publishable_key));
setClientSecret(data.data.client_secret);
} else {
alert(data.message);
}
};
if (clientSecret && stripePromise) {
return (
<EmbeddedCheckoutProvider
stripe={stripePromise}
options={{ clientSecret }}
>
<EmbeddedCheckout />
</EmbeddedCheckoutProvider>
);
}
return (
<>
<h1>Stripe Payment Testing Page</h1>
<button onClick={createPayment}>
Open Payment Capsule
</button>
</>
);
}
Payment Flow
User clicks "Pay"
↓
Frontend calls Node.js API
↓
Node.js calls Kayana API
↓
Kayana creates a Stripe Checkout session
↓
Returns:
client_secret
publishable_key
↓
Frontend loads Stripe
↓
Stripe Embedded Checkout appears
↓
User enters card details
↓
Stripe confirms payment
Testing in Sandbox
Use Stripe test cards.
| Card Number | Brand | Scenario |
| 4242 4242 4242 4242 | Visa | Successful |
| 4000 0025 0000 3155 | Visa | Requires 3D Secure |
| 4000 0000 0000 9995 | Visa | Declined |
Additional Details:
- Expiry → Any future date
- CVC → Any 3 digits
- ZIP → Any valid format
⚠️ Never use test cards in production.
Error Handling
All responses include:
{
"status": false,
"message": "Description of error"
}
Common Errors
| Error | Cause | Solution |
| Invalid API key | Incorrect x-api-key | Verify with Kayana |
| Invalid property ID | Wrong format | Must start with Prop_* |
| Unsupported currency | Not enabled | Contact Kayana |
| Stripe configuration missing | PSP not enabled | Contact Kayana |
Going Live Checklist
Before production:
- Obtain production x-api-key
- Switch to production base URL
- Use live Stripe publishable key
- Test real card transactions
- Implement Stripe webhooks
Never:
- Use sandbox keys in production
- Expose secret keys in the frontend
Support
Technical Support: Kayana Technical Team Production credentials: Contact Kayana account manager.



