Building an advanced Kayana integration with RYFT in Python
Last updated Mar 5, 2026
Build a payment flow using Python (FastAPI) and the Ryft SDK to securely collect card details and process payments. This guide explains how the Python plugin (ryft_plugin.py) replaces the PHP server logic while keeping the same checkout functionality. Instead of manually calling all backend APIs, the plugin exposes a simplified entry point: POST /launch This endpoint:
- Creates a session for the payment
- Opens a browser checkout page
- Internally calls the required Kayana payment gateway APIs
- Displays a secure Ryft card payment form
Overview
The Python plugin acts as a payment proxy server between the frontend checkout page and the Kayana payment API. Instead of using PHP curl requests, the plugin uses:
- FastAPI for backend endpoints
- Python requests library for API communication
- Ryft JavaScript SDK for secure card processing
This allows developers to run a local payment gateway using Python.
What You’ll Build
The Python plugin provides the following features:
- Launch a checkout session
- Create a payment instance using the Kayana API
- Retrieve the Ryft public key for frontend initialization
- Render a secure checkout page
- Process payments using the Ryft SDK
- Log successful payment sessions
Before You Begin
You will need:
- A Kayana Property ID
- A Kayana API key
- Python 3.10+
- Installed dependencies:
- FastAPI
- Uvicorn
- Requests
Python Plugin Configuration
The plugin defines configuration settings used for API communication. CONFIG = { "BASE_URL": "https://integration.dev.kayana.co.uk", "API_KEY": "YOUR_API_KEY" } These values control:
- The Kayana API environment
- Authentication headers
- Payment endpoint URLs
How the Python Plugin Works
- Server creates a payment instance and receives a client_secret
- Server fetches the Ryft public_key
- Frontend renders the payment form and completes the transaction
Step 1 — Launch a Payment Session
The entrypoint of the plugin is /launch. This endpoint:
- validates the request
- creates a session
- opens the checkout page automatically
Endpoint
POST /launch
Request Body
| Parameter | Type | Description |
| property_id | string | Kayana property identifier |
| amount | number | Payment amount |
| customer_email | string | Customer email |
| currency_code | string | ISO currency code |
| api_key | string | Kayana API key |
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.
Example Request
curl -X POST http://localhost:8000/launch \ -H "Content-Type: application/json" \ -d '{ "property_id": "Prop_abc123example", "amount": 12.0, "currency_code": "GBP", "customer_email": "customer@example.com" }'
Example Response
{ "launched": true, "session_id": "e3d2f82a-8d9e-4c9b-8d4f-b3a29e82f1aa", "url": "http://localhost:8000/?session_id=e3d2f82a-8d9e-4c9b-8d4f-b3a29e82f1aa", "message": "Browser opened with payment page." }
Important: Internal API Calls
Unlike the standard Kayana integration guide, the plugin automatically calls the gateway APIs internally.
Internally triggered APIs
When the checkout page loads, the frontend calls: POST /proxy/create-payment which internally calls: POST /web/payment This creates the payment instance and returns the client_secret. Next, the plugin retrieves the Ryft encryption key. GET /proxy/public-key which internally calls: GET /web/payment/public-key This returns the PSP public key required to initialise the Ryft SDK.
Step 2 — Create Payment Instance (Internal)
Endpoint used internally by the plugin: POST /proxy/create-payment This calls the Kayana API: POST /web/payment
Request Payload
{ "property_id": "Prop_abc123example", "psp_code": "RYFT", "currency_code": "GBP", "amount": 12.0, "customer_email": "customer@example.com" }
Response
{ "status": true, "client_secret": "ps_secret_example" } The client_secret is required by the Ryft SDK to confirm the payment.
Step 3 — Retrieve PSP Public Key (Internal)
Endpoint used internally: GET /proxy/public-key Internally calls: GET /web/payment/public-key
Required Headers
| Header | Value |
| x-psp-code | RYFT |
| x-currency-code | GBP |
Response
{ "status": true, "public_key": "pk_sandbox_abc123examplekey" }
Step 4 – Render the Payment Page
The plugin dynamically renders the checkout page using FastAPI.
Endpoint
GET / The HTML template includes the Ryft SDK. <script src="https://embedded.ryftpay.com/v2/ryft.min.js"></script> The payment page performs the following actions:
- Load session data
- Create payment instance
- Retrieve public key
- Initialise Ryft
- Enable card payment form
Step 5 – Initialise Ryft SDK
Once both keys are retrieved, the frontend initialises the Ryft SDK. Ryft.init({ publicKey: STATE.publicKey, clientSecret: STATE.clientSecret }); This allows the SDK to securely collect card information.
Step 6 – Log Successful Payments
When a payment succeeds, the plugin records the payment session.
Endpoint
POST /api/log-payment
Example Logged Data
Session ID Property ID Customer Email Amount Payment Status This helps track transactions for debugging or auditing.
Additional endpoints for orders
Suggested flow: Create Order → Authorise Payment ↓ ├── Capture → Success ├── Cancel → Void payment └── Refund → After capture
Authentication
All API requests must include the following headers:
| Header | Type | Required | Description |
| x-api-key | String | Yes | Your API key |
| type | String | Yes | Must be set to business |
| Content-Type | String | Yes | Must be application/json |
| x-property-id | String | Yes | property id |
1. Capture Authorised Payment
Endpoint POST /web/payment/capture-authorised-payment
Request Parameters
| Field | Type | Required | Description |
| order_id | String | Yes | Order ID |
| amount | Number | Yes | Amount to capture |
cURL Example
curl --location 'https://integration.dev.kayana.co.uk/web/payment/capture-authorised-payment' \ --header 'Content-Type: application/json' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>' \ --data '{ "order_id": "Order_xxx", "amount": 5 }'
Sample Response
{ "status": "success", "message": "Payment captured successfully", "data": { "order_id": "Order_xxx", "captured_amount": 5 } }
2. Cancel Authorised Payment
Endpoint
POST /web/payment/cancel-authorised-payment
Request Parameters
| Field | Type | Required | Description |
| order_id | String | Yes | Order ID |
cURL Example
curl --location 'https://integration.dev.kayana.co.uk/web/payment/cancel-authorised-payment?order_id=Order_xxx' \ --header 'Content-Type: application/json' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>'
Sample Response
{ "status": "success", "message": "Payment cancelled successfully" }
3. Refund Payment
Endpoint
POST /web/payment/refund
Request Parameters
| Field | Type | Required | Description |
| order_id | String | Yes | Order ID |
| amount | Number | Yes | Refund amount |
cURL Example
curl --location --request POST 'https://integration.dev.kayana.co.uk/web/payment/refund?order_id=Order_xxx&amount=0.4' \ --header 'Content-Type: application/json' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>'
Sample Response
{ "status": "success", "message": "Refund processed", "data": { "order_id": "Order_xxx", "refunded_amount": 0.4 } }
4. Fetch Order Details
Endpoint
GET /web/order/fetch-order-details-by-order-id
Request Parameters
| Field | Type | Required | Description |
| order_id | String | Yes | Order ID |
cURL Example
curl --location 'https://integration.dev.kayana.co.uk/web/order/fetch-order-details-by-order-id?order_id=Order_xxx' \ --header 'type: business' \ --header 'x-api-key: <YOUR_API_KEY>'
Sample Response
{ "status": "success", "data": { "order_id": "Order_xxx", "status": "captured", "amount": 5 } }
Error Handling
The plugin includes an advanced error classification system. Errors are categorised into:
- Invalid authorization token
- Missing headers
- Invalid property ID
- Unsupported currency
- PSP configuration missing
Example classification logic: _classify_error(data, status_code) Each error returns: error_code message solution This provides clear feedback to developers.
Testing the Plugin
Run the server using:
- uvicorn main:app --reload --port 8000
The FastAPI server will start on:
- http://localhost:8000
API documentation is available at:
- http://localhost:8000/docs
Sandbox Test Cards
You can test payments using Ryft sandbox cards. Build a Checkout Page with Kaya…
| Card Number | Scenario |
| 4242 4242 4242 4242 | Successful payment |
| 4000 0025 0000 3155 | Requires authentication |
| 4000 0000 0000 9995 | Payment declined |
Going Live
Before moving to production:
- Replace the sandbox API key
- Update the base URL
- Use production public keys
- Disable test cards
- Secure API credentials
Never expose production keys in client-side code.
Support
Need help?
- Technical issues: Contact Kayana Technical Support
- Production credentials: Request from your Kayana account manager
- PSP configuration: Reach out to Kayana Technical Support
Whats next?
- Explore webhook integration for payment notifications
- Learn about refunds and dispute handling
- Set up recurring payments for subscriptions
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 a Checkout Page with Kayana’s Stripe Plugin (Python).



