Skip to content
Kayana

Building an advanced Kayana integration with RYFT in React/Next.js

Last updated Mar 9, 2026

Build a secure card payment integration using Kayana Payment API powered by RYFT in a Next.js application.

This guide explains how to:

  • Create a payment session from your backend
  • Retrieve the RYFT public key
  • Initialise the RYFT SDK
  • Render the payment form
  • Complete the payment securely

Overview

The Kayana Payment API allows you to accept card payments without building your own PCI-compliant payment form.

The payment flow works like this:

1️⃣ Server creates a payment instance
2️⃣ Server retrieves the RYFT public key
3️⃣ Frontend loads RYFT SDK
4️⃣ Frontend initializes the payment session
5️⃣ Customer enters card details and completes payment

Before You Begin

You will need:

  • Kayana Property ID
  • API Key
  • Access to Sandbox Environment
  • Basic knowledge of Node.js / Next.js

Sandbox vs Production

Sandbox

Safe testing environment.

  • Uses test payment data
  • No real money transactions
  • Base URL:

https://integration.dev.kayana.co.uk

Production

Live payment environment.

  • Real transactions
  • Requires production API key
  • Base URL:

https://integration.kayana.co.uk

RYFT Payment Flow

Frontend loads

https://embedded.ryftpay.com/v2/ryft.min.js

Frontend initializes RYFT

Ryft.init()

User completes payment

Ryft.attemptPayment()

Set up the server

Base URL

Sandbox:

https://integration.dev.kayana.co.uk

Production:

https://integration.kayana.co.uk

Step 1 - Create Payment Instance (Server Side)

Create a payment session by calling:

POST /web/payment

HeaderValueRequired
Content-Typeapplication/jsonYES
x-api-keyYOUR_API_KEYYES
typebusinessYES
x-property-idStringYes

How to obtain your X API key

Follow these steps inside Partner Admin:

  • Log in to Kayana Partner Admin.
  • Navigate to Settings (left-hand sidebar).
  • Select API Key Management.
  • Click Create API Key.
  • Copy the generated key immediately and send it in the header.

Request Parameters

ParameterTypeDescriptionRequired
property_idstringKayana property identifier (Prop_*)YES
psp_codestringPayment provider (RYFT)YES
pre_authorisebooleanIndicates whether the payment should be pre-authorised instead of captured immediatelyNOT MANDATORY
currency_codestringCurrency code (GBP, USD, EUR)YES
amountnumberPayment amountYES
customer_emailstringCustomer emailYES
payment_modestringPayment method (CARD)YES
x-property-idStringproperty IDYes

Optional Browser Information

FieldType[pDescription
userAgentstringBrowser user agent
acceptHeaderstringAccept header
languagestringBrowser language
colorDepthnumberScreen color depth
screenHeightnumberScreen height
screenWidthnumberScreen width
timeZoneOffsetnumberTimezone offset

Optional Billing Address

FieldType
streetstring
citystring
postalCodestring
countrystring
statestring

Example Server Implementation (Next.js API Route)

export async function POST() {

try {

const response = await fetch(

"https://integration.dev.kayana.co.uk/web/payment",

{

method: "POST",

headers: {

"Content-Type": "application/json",

"x-api-key": "YOUR_API_KEY",

type: "business",

},

body: JSON.stringify({

property_id: "Prop_039f025cdbc74ca9957dbec1b3e193c1",

psp_code: "RYFT",

currency_code: "GBP",

amount: 100.5,

customer_email: "customer@example.com",

payment_mode: "CARD",

browser_info: {

userAgent: "Mozilla/5.0",

acceptHeader: "*/*",

language: "en-US",

colorDepth: 24,

screenHeight: 1080,

screenWidth: 1920,

timeZoneOffset: 0

},

billing_address: {

street: "221B Baker Street",

city: "London",

postalCode: "NW1 6XE",

country: "GB",

state: "Greater London"

}

}),

}

);

const data = await response.json();

return Response.json(data, { status: response.status });

} catch (error) {

return Response.json(

{ error: "Payment failed", details: error.message },

{ status: 500 }

);

}

}

Example API Response

{

"message": "Payment session created successfully",

"status": true,

"data": {

"client_secret": "ps_01KK…MKXJ8NRBCR…",

"next_step": {

"action": "FORM",

"proceed": true

},

"transaction_id": "Tx_9052db2d798f4…..ab8e032",

"order_id": "Order_5ab37f6….0efc5b0a"

}

}

⚠️ Important

client_secret must only be used on the frontend.

Never expose secret API keys to the browser.

Step 2 — Get RYFT Public Key

Your backend should call:

GET /web/payment/public-key

x-api-key

x-psp-code

x-currency-code

type

Example

export async function GET() {

const response = await fetch(

"https://integration.dev.kayana.co.uk/web/payment/public-key",

{

method: "GET",

headers: {

"x-api-key": "YOUR_API_KEY",

"x-psp-code": "RYFT",

"x-currency-code": "GBP",

"type": "business",

},

}

);

const data = await response.json();

return Response.json(data);

}

EXAMPLE RESPONSE

{

"status": true,

"data": {

"public_key": "pk_sandbox_TlD……d+iMtqu/pmWyGvThg…."

}

}

Step 3 - Load RYFT SDK (Frontend)

Add the RYFT SDK to your page.

https://embedded.ryftpay.com/v2/ryft.min.js

Example using Next.js:

<Script

src="https://embedded.ryftpay.com/v2/ryft.min.js"

strategy="afterInteractive"

/>

Step 4 - Initialise RYFT

After fetching:

  • publicKey
  • clientSecret

Initialise the SDK.

window.Ryft.init({

publicKey,

clientSecret

});

Step 5 - Attempt Payment

Trigger payment from the form.

const paymentSession = await window.Ryft.attemptPayment();

Example:

if (

paymentSession.status === "Approved" ||

paymentSession.status === "Captured"

) {

alert("Payment Successful");

}

Testing Payments

Use RYFT test cards in the sandbox.

Example:

CardScenario
4242 4242 4242 4242Successful
4000 0025 0000 31553D Secure
4000 0000 0000 9995Declined

Use:

  • Any future expiry
  • Any CVC

⚠️ Never use test cards in production

Common Errors

ErrorCauseFix
Invalid API KeyWrong x-api-keyVerify key
Invalid Property IDWrong formatMust start with Prop_
Unsupported currencyCurrency not enabledContact Kayana
PSP not enabledRYFT not configuredContact Kayana

Going Live Checklist

Before moving to production:

✔ Get production API key
✔ Switch to production base URL
✔ Verify RYFT configuration
✔ Test real card transactions
✔ Implement payment confirmation webhooks

Security Best Practices

Never:

❌ Expose API keys on frontend
❌ Use sandbox keys in production
❌ Log client_secret publicly

Always:

✔ Process payments via server API routes

Next Steps

If you prefer to use Stripe as your Payment Service Provider (PSP), Kayana also supports a full Stripe integration flow. Refer to our guide on Building an advanced Kayana integration with Stripe in React/Next.js.

Still need a hand?Contact support← All help