Session API Reference
Complete reference for creating and managing payment sessions with Altruon.
Overview
Before you can accept a payment, you must create a payment session from your backend. The session holds cart details (billingData), optional customer information (customerData), and payment preferences for the checkout flow.
Sessions power two surfaces:
| Surface | How the shopper checks out | Customer data |
|---|---|---|
| Dynamic Hosted Checkout | Redirect to /checkout/s/{sessionId} (hostedCheckout: true) | Pass customerData at create → fields pre-fill on the hosted page |
| Embedded Altruon JS | iframe on your site | Pass customerData via SDK setters from the browser (see Configuration) |
Working example: in the Altruon Merchant Demo, all secret-key calls to this API live in a single backend file (
server/src/altruonClient.js), and the session payload is assembled inserver/src/routes.js. The browser only ever receives the resultingsession_id. Use the same separation in production.
Create Session
Creates a new payment session that can be used with Altruon JS.
Endpoints
- Sandbox:
https://{your-domain}.api.sandbox.altruon.io/api/session/v1/create - Production:
https://{your-domain}.api.altruon.io/api/session/v1/create
Replace {your-domain} with your actual Altruon domain (e.g., mycompany).
Authentication
Requests must be authenticated using your secret API key:
headers: {
'Content-Type': 'application/json',
'x-secret-key': 'sk_sandbox_test_XXXXXX...'
}
Security Note: Never expose your secret key in client-side code. Always call this endpoint from your backend.
Request Body
Complete Example (embedded Altruon JS)
{
"paymentData": {
"currency": "USD",
"paymentMethod": "card"
},
"redirectUrl": "https://yourdomain.com/success",
"billingData": {
"lineItems": [
{
"type": "plan",
"id": "price_1SMtJj4hYau76GhIakR22BKu",
"quantity": "1"
}
],
"billingPlatformId": "3287b8c7-ce43-41fd-9d58-f510e610b8f3"
},
"styleCustomization": {
"backgroundColor": "#3a3a3a",
"primaryColor": "#4B5563",
"secondaryColor": "#3a3a3a",
"accentColor": "#5B7FFF",
"borderRadius": "5px",
"headerTextColor": "#ffffff",
"fontFamily": "Verdana, cursive",
"textColor": "#ffffff",
"dropShadow": false
}
}
Complete Example (dynamic hosted checkout)
Redirect the shopper to the checkout_url in the response. Include customerData to pre-fill the hosted form — see Pre-filling customer data.
{
"hostedCheckout": true,
"paymentData": { "currency": "BRL" },
"redirectUrl": "https://yourdomain.com/success",
"billingData": {
"lineItems": [
{ "type": "plan", "id": "price_1SMtJj4hYau76GhIakR22BKu", "quantity": 1 }
],
"billingPlatformId": "3287b8c7-ce43-41fd-9d58-f510e610b8f3"
},
"customerData": {
"firstName": "João",
"lastName": "Silva",
"email": "joao@example.com",
"billingAddress": {
"street": "Av. Paulista",
"city": "São Paulo",
"state": "SP",
"zipCode": "01310-100",
"country": "BR"
}
},
"document": "12345678909"
}
Request Parameters
Important: The fields
currency,lineItems(insidebillingData), andbillingPlatformIdare required and must be set via the backend Create Session API. They cannot be modified from the frontend.Customer data depends on your checkout surface:
- Dynamic Hosted Checkout (
hostedCheckout: true→/checkout/s/{sessionId}): passcustomerData(and optional top-leveldocument) in the Create Session request. Fields are pre-filled when the shopper opens the hosted page. See Dynamic Hosted Checkout.- Embedded Altruon JS (iframe): pass customer fields from the browser via
setCustomer()/setAddresses()before payment. OnlybillingAddress.countrycan be set on the frontend if not already on the session.
paymentData (required)
Payment-related information for the transaction.
| Field | Type | Required | Description |
|---|---|---|---|
currency | string | Yes | Three-letter ISO currency code (e.g., "USD", "EUR", "BRL"). Must be set via backend Create Session API. |
paymentMethod | string | No | Payment method type: "card", "upi", "pix", etc. |
Note: If no
paymentMethodis provided (discovery mode), the hosted checkout shows every payment method routed for the session currency (e.g. PIX and card for BRL). If you passpaymentMethod(e.g."card"), only that method is shown. The Create Session response includespayment_method_pinned_at_createto reflect which mode you chose — see Payment method pinning.On embedded Altruon JS, when no
paymentMethodis provided, rendering follows your backoffice routing entries:
- Multiple routing entries match the currency: The component will render a drawer UI allowing the customer to select between available payment methods (e.g., Card and UPI for INR currency)
- Single routing entry matches the currency: The component will render only the required payment fields for that specific payment method (e.g., for EUR with only card routing, it will render card number, expiry date, CVV, and optionally cardholder name for some gateways) without the drawer UI
Example:
{
"paymentData": {
"currency": "USD",
"paymentMethod": "card"
}
}
redirectUrl (required)
The URL to redirect users to after successful payment completion.
| Field | Type | Required | Description |
|---|---|---|---|
redirectUrl | string | Yes | Full URL including protocol (e.g., "https://yourdomain.com/success") |
Example:
{
"redirectUrl": "https://yourdomain.com/success"
}
locale (optional)
Controls the language of the hosted checkout UI and embedded Altruon JS checkout.
| Field | Type | Required | Description |
|---|---|---|---|
locale | string | No | Checkout language. Supported: en, pt_br. Also accepts pt-BR, pt, en-US. Unsupported values fall back to en. When omitted, the checkout auto-selects from currency (BRL → Portuguese). |
Example:
{
"locale": "pt_br"
}
billingData (required)
Billing platform and subscription plan information.
| Field | Type | Required | Description |
|---|---|---|---|
lineItems | array | Yes | Array of items to be purchased. Each item must have type, id, and quantity. Must be set via backend Create Session API. |
billingPlatformId | string | Yes | Your Altruon billing platform connection ID. Must be set via backend Create Session API. |
frequency | string | No | Billing frequency: "monthly", "yearly", "weekly", etc. |
couponCodes | array of strings | No | Coupons to apply for estimate and subscription creation. |
metadata | object (string → string) | No | Merchant key/value pairs forwarded to the billing platform on subscription creation (e.g. Stripe subscription metadata). Max 50 keys; key ≤ 40 chars; value ≤ 500 chars. |
forceTrialPeriodDays | integer | No | Override trial length in days (1–730). Must be nested inside billingData. See Override trial length per checkout. |
Example:
{
"billingData": {
"lineItems": [
{
"type": "plan",
"id": "price_1SMtJj4hYau76GhIakR22BKu",
"quantity": "1"
}
],
"billingPlatformId": "3287b8c7-ce43-41fd-9d58-f510e610b8f3",
"frequency": "monthly",
"metadata": {
"user_id": "user_123",
"platform": "web"
}
}
}
Platform mapping: Stripe → subscription
metadata; Chargebee → subscriptionmeta_data; Frisbii → subscriptionmetadata; Recurly → subscriptioncustom_fields(field names must exist in Recurly).
Minimal example (no metadata):
{
"billingData": {
"lineItems": [
{
"type": "plan",
"id": "price_1SMtJj4hYau76GhIakR22BKu",
"quantity": "1"
}
],
"billingPlatformId": "3287b8c7-ce43-41fd-9d58-f510e610b8f3",
"frequency": "monthly"
}
}
Note: You can find your
billingPlatformIdin the Altruon Dashboard under Integrations > Billing Providers.
customerData (optional)
Customer identity and address information. Optional at create time, but recommended when using Dynamic Hosted Checkout so the hosted page opens with fields already filled in.
| Field | Type | Description |
|---|---|---|
firstName | string | Customer first name → main First name field on hosted checkout |
lastName | string | Customer last name → main Last name field |
email | string | Email address |
phone | string | Phone number (shown only if enabled under Settings → Checkout → Fields) |
ip | string | Customer IP (optional; used by some gateways) |
billingAddress | object | Billing address — see address fields below |
shippingAddress | object | Shipping address (shown only if shipping fields are enabled) |
Address object (billingAddress / shippingAddress):
| Field | Type | Maps to hosted checkout field |
|---|---|---|
street | string | Address line 1 |
number | string | Address line 2 (apartment, suite, etc.) |
city | string | City |
state | string | State / province |
zipCode | string | Zip / postal code |
country | string | Country (ISO 3166-1 alpha-2, e.g. "BR", "US") |
Example:
{
"customerData": {
"firstName": "João",
"lastName": "Silva",
"email": "joao@example.com",
"phone": "+5511999999999",
"billingAddress": {
"street": "Av. Paulista",
"number": "1000",
"city": "São Paulo",
"state": "SP",
"zipCode": "01310-100",
"country": "BR"
}
}
}
Billing-address name fields: if your checkout configuration collects first/last name under Billing address (separate from the main name block), include those values inside
billingAddressas well — they are not copied automatically from top-levelfirstName/lastName.
Pre-filled values are defaults: the shopper can edit them before paying. After a failed 3DS/card redirect, the same session restores whatever was last saved on the session.
document (optional)
Top-level tax or identity document (e.g. CPF/CNPJ for Brazil). Pre-fills PagBrasil PIX and card document fields when present.
{
"document": "12345678909"
}
hostedCheckout (optional)
Set to true when redirecting the shopper to Altruon Dynamic Hosted Checkout at /checkout/s/{sessionId} instead of embedding Altruon JS. See Dynamic Hosted Checkout.
| Field | Type | Default | Description |
|---|---|---|---|
hostedCheckout | boolean | false | When true, the create response includes checkout_url and the session uses the full hosted checkout UI (site branding, order summary). Mutually exclusive with hostedPageConfigId. |
styleCustomization (optional)
Customize the appearance of the payment component to match your brand.
| Field | Type | Default | Description |
|---|---|---|---|
backgroundColor | string | #ffffff | Background color (hex, rgb, or named color) |
primaryColor | string | #4B5563 | Primary color for buttons and interactive elements |
secondaryColor | string | #9CA3AF | Secondary color for supporting elements |
accentColor | string | #3B82F6 | Accent color for highlights and focus states |
borderRadius | string | 8px | Border radius for rounded corners |
headerTextColor | string | #1F2937 | Header text color |
textColor | string | #1F2937 | Body text color |
fontFamily | string | system-ui, sans-serif | Font family for all text |
dropShadow | boolean | true | Whether to show drop shadows on elements |
Example:
{
"styleCustomization": {
"backgroundColor": "#ffffff",
"primaryColor": "#0066FF",
"secondaryColor": "#6B7280",
"accentColor": "#0066FF",
"borderRadius": "12px",
"headerTextColor": "#000000",
"fontFamily": "Inter, system-ui, sans-serif",
"textColor": "#1F2937",
"dropShadow": true
}
}
Response
Success Response (200 OK)
{
"session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"expires_at": "2026-06-21T12:15:00Z",
"checkout_url": "https://mycompany.sandbox.altruon.io/checkout/s/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payment_method_pinned_at_create": false,
"available_payment_methods": [
{
"payment_method": "card",
"gateway": "CHECKOUTCOM",
"gateway_connection_id": "..."
}
]
}
Specific mode (you passed paymentMethod in the request):
{
"session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"expires_at": "2026-06-21T12:15:00Z",
"checkout_url": "https://mycompany.sandbox.altruon.io/checkout/s/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payment_method_pinned_at_create": true,
"payment_method": "card",
"gateway": "CHECKOUTCOM",
"gateway_connection_id": "..."
}
| Field | Type | Description |
|---|---|---|
session_id | string | Unique session identifier (UUID) |
expires_at | string | ISO 8601 timestamp when the session expires (15 minutes from creation) |
checkout_url | string | Present when hostedCheckout: true — redirect the shopper here |
payment_method_pinned_at_create | boolean | Whether you locked the payment method at session create. See Payment method pinning below. |
available_payment_methods | array | Present in discovery mode (no paymentMethod in request) |
payment_method | string | Present in specific mode — the selected payment method |
gateway | string | Present in specific mode — the selected gateway |
gateway_connection_id | string | Present in specific mode — gateway connection UUID |
trial | object | Present when the plan has a catalog trial or billingData.forceTrialPeriodDays was set. Contains inTrial, trialEnd, amountDueNow, etc. See Trials. |
Payment method pinning
Every Create Session response includes payment_method_pinned_at_create. It records your intent at create time and does not change when the shopper selects or retries a payment method during checkout.
| Value | You sent at create | Hosted checkout behavior |
|---|---|---|
false | No paymentMethod (discovery mode) | Shopper sees every payment method routed for the session currency (e.g. PIX and card for BRL). After a failed payment, all methods remain available so the shopper can switch (e.g. card declined → try PIX). |
true | paymentMethod set (specific mode) | Shopper sees only the method (and gateway) you specified. This stays locked for the life of the session, including after a failed payment. |
Why this field exists: During checkout, Altruon persists the shopper’s chosen payment method on the session before processing payment (for example when they submit a card form). That update must not be confused with your create-time choice. payment_method_pinned_at_create separates:
- Merchant intent — set once when you call Create Session
- Shopper selection — written during checkout and used for payment processing
You typically do not need to branch on this field in your backend unless you build custom checkout UI. Altruon hosted checkout uses it automatically. The same value is also returned on Get Session (GET /api/session/v1/{sessionId}) and on checkout config when loaded with sessionId.
When to use each mode:
- Discovery (
false) — default for dynamic hosted checkout when you want the shopper to pick from all routed methods (most BRL checkouts with PIX + card). - Specific (
true) — when you already know the method (e.g. card-only upgrade flow, or a deep link from your app that says “pay with PIX”).
// Discovery — shopper chooses on the hosted page
{ "paymentData": { "currency": "BRL" } }
// Specific — only card is shown
{ "paymentData": { "currency": "BRL", "paymentMethod": "card" } }
Error Response (4xx/5xx)
{
"error": {
"code": "invalid_request",
"message": "Missing required field: paymentData.currency",
"details": {}
}
}
Implementation Examples
Node.js / Express
const express = require('express');
const app = express();
app.post('/create-checkout-session', async (req, res) => {
const { planId, billingPlatformId, currency } = req.body;
try {
const response = await fetch(
'https://mycompany.api.sandbox.altruon.io/api/session/v1/create',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-secret-key': process.env.ALTRUON_SECRET_KEY
},
body: JSON.stringify({
paymentData: {
currency: currency || 'USD',
paymentMethod: 'card'
},
redirectUrl: 'https://mycompany.com/success',
billingData: {
lineItems: [
{
type: 'plan',
id: planId,
quantity: '1'
}
],
billingPlatformId: billingPlatformId
},
styleCustomization: {
backgroundColor: '#ffffff',
primaryColor: '#0066FF',
accentColor: '#0066FF',
borderRadius: '8px',
fontFamily: 'Inter, sans-serif'
}
})
}
);
const data = await response.json();
if (!response.ok) {
throw new Error(data.error.message);
}
res.json({ sessionId: data.session_id });
} catch (error) {
console.error('Error creating session:', error);
res.status(500).json({ error: error.message });
}
});
Python / Flask
from flask import Flask, request, jsonify
import requests
import os
app = Flask(__name__)
@app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session():
data = request.get_json()
plan_id = data.get('planId')
billing_platform_id = data.get('billingPlatformId')
currency = data.get('currency', 'USD')
try:
response = requests.post(
'https://mycompany.api.sandbox.altruon.io/api/session/v1/create',
headers={
'Content-Type': 'application/json',
'x-secret-key': os.environ.get('ALTRUON_SECRET_KEY')
},
json={
'paymentData': {
'currency': currency,
'paymentMethod': 'card'
},
'redirectUrl': 'https://mycompany.com/success',
'billingData': {
'lineItems': [
{
'type': 'plan',
'id': plan_id,
'quantity': '1'
}
],
'billingPlatformId': billing_platform_id
},
'styleCustomization': {
'backgroundColor': '#ffffff',
'primaryColor': '#0066FF',
'accentColor': '#0066FF',
'borderRadius': '8px',
'fontFamily': 'Inter, sans-serif'
}
}
)
response.raise_for_status()
result = response.json()
return jsonify({'sessionId': result['session_id']})
except requests.exceptions.RequestException as e:
return jsonify({'error': str(e)}), 500
Ruby / Rails
# app/controllers/checkout_controller.rb
class CheckoutController < ApplicationController
def create_session
plan_id = params[:planId]
billing_platform_id = params[:billingPlatformId]
currency = params[:currency] || 'USD'
response = HTTParty.post(
'https://mycompany.api.sandbox.altruon.io/api/session/v1/create',
headers: {
'Content-Type' => 'application/json',
'x-secret-key' => ENV['ALTRUON_SECRET_KEY']
},
body: {
paymentData: {
currency: currency,
paymentMethod: 'card'
},
redirectUrl: 'https://mycompany.com/success',
billingData: {
lineItems: [
{
type: 'plan',
id: plan_id,
quantity: '1'
}
],
billingPlatformId: billing_platform_id
},
styleCustomization: {
backgroundColor: '#ffffff',
primaryColor: '#0066FF',
accentColor: '#0066FF',
borderRadius: '8px',
fontFamily: 'Inter, sans-serif'
}
}.to_json
)
if response.success?
render json: { sessionId: response['session_id'] }
else
render json: { error: response['error']['message'] }, status: :internal_server_error
end
end
end
PHP / Laravel
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
class CheckoutController extends Controller
{
public function createSession(Request $request)
{
$planId = $request->input('planId');
$billingPlatformId = $request->input('billingPlatformId');
$currency = $request->input('currency', 'USD');
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'x-secret-key' => env('ALTRUON_SECRET_KEY')
])->post(
'https://mycompany.api.sandbox.altruon.io/api/session/v1/create',
[
'paymentData' => [
'currency' => $currency,
'paymentMethod' => 'card'
],
'redirectUrl' => 'https://mycompany.com/success',
'billingData' => [
'lineItems' => [
[
'type' => 'plan',
'id' => $planId,
'quantity' => '1'
]
],
'billingPlatformId' => $billingPlatformId
],
'styleCustomization' => [
'backgroundColor' => '#ffffff',
'primaryColor' => '#0066FF',
'accentColor' => '#0066FF',
'borderRadius' => '8px',
'fontFamily' => 'Inter, sans-serif'
]
]
);
if ($response->successful()) {
return response()->json([
'sessionId' => $response->json()['session_id']
]);
} else {
throw new \Exception($response->json()['error']['message']);
}
} catch (\Exception $e) {
return response()->json([
'error' => $e->getMessage()
], 500);
}
}
}
Best Practices
1. Session Expiration
Sessions expire after 15 minutes. Create a new session if the previous one expires.
2. Security
- Never store or log secret keys
- Always create sessions on your backend
- Validate all input parameters before creating a session
- Use environment variables for API keys
3. Error Handling
Always handle errors gracefully and provide meaningful messages to users:
try {
const response = await createSession(planId);
// Success
} catch (error) {
if (error.code === 'invalid_line_item') {
// Handle invalid line item
} else if (error.code === 'unauthorized') {
// Handle authentication error
} else {
// Handle generic error
}
}
4. Testing
Use sandbox mode during development and testing:
- Sandbox endpoint:
https://{your-domain}.api.sandbox.altruon.io/api/session/v1/create - Sandbox keys:
sk_sandbox_test_...
Common Error Codes
| Code | Description | Resolution |
|---|---|---|
invalid_request | Missing or invalid request parameters | Check request body structure |
unauthorized | Invalid or missing API key | Verify your secret key |
invalid_line_item | Line item ID not found or invalid | Check your billing provider |
invalid_billing_platform | Billing platform not configured | Configure billing platform in dashboard |
rate_limit_exceeded | Too many requests | Implement retry logic with backoff |
Transaction Details API
After a successful payment, you'll receive a transactionId in the onSuccess callback. To get complete details about the transaction, subscription, customer, and invoice, call the Transaction Details endpoint from your backend.
Endpoint
Get Transaction Details:
- Sandbox:
GET https://{your-domain}.api.sandbox.altruon.io/api/v1/transaction/{transactionId}/details - Production:
GET https://{your-domain}.api.altruon.io/api/v1/transaction/{transactionId}/details
Authentication:
headers: {
'Content-Type': 'application/json',
'x-secret-key': 'sk_sandbox_test_XXXXXX...'
}
Response:
{
"transaction": {
"id": "66a22937-a351-417e-81c1-9ac5164be9ab",
"idAtGateway": "pay_wthwuqodnobedlulbexcjfylma",
"urlAtGateway": "https://dashboard.sandbox.checkout.com/payments/all-payments/payment/pay_wthwuqodnobedlulbexcjfylma",
"type": "initialPayment",
"amount": "12300",
"amountInMajorUnit": "123.00",
"currency": "EUR",
"status": "success",
"gateway": "checkoutcom",
"errorMessage": null
},
"customer": {
"idAtBillingPlatform": "cus_TM8zJeFCKE15oB",
"urlAtBilling": "https://dashboard.stripe.com/customers/cus_TM8zJeFCKE15oB",
"billingPlatform": "stripe"
},
"invoice": {
"idAtBillingPlatform": "in_1SPQhq4hYau76GhIbWx8zT8H",
"urlAtBilling": "https://dashboard.stripe.com/invoices/in_1SPQhq4hYau76GhIbWx8zT8H",
"amount": "12300",
"amountInMajorUnit": "123.00",
"currency": "EUR",
"billingPlatform": "stripe"
},
"subscription": {
"idAtBillingPlatform": "sub_1SPQhq4hYau76GhIFvpT8HSx",
"urlAtBilling": "https://dashboard.stripe.com/subscriptions/sub_1SPQhq4hYau76GhIFvpT8HSx",
"nextBillingDate": "2025-12-03T16:34:10Z",
"billingPlatform": "stripe"
}
}
New Feature: The response now includes direct URLs (
urlAtGatewayandurlAtBilling) that link to the respective entity pages in your payment gateway and billing provider dashboards. These URLs allow your team to quickly access detailed information in Stripe, Checkout.com, or other provider dashboards for support and reconciliation purposes.
For detailed implementation examples and use cases, see the Callbacks documentation.
Next Steps
- Quick Start Guide - Integrate Altruon JS with your session
- Callbacks - Handle payment events and get transaction details
- Coupons - Apply coupons in session API or SDK methods
- Configuration - Configure the payment component
- Style Customization - Advanced styling options
- Examples - Real-world implementations