Skip to main content

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:

SurfaceHow the shopper checks outCustomer data
Dynamic Hosted CheckoutRedirect to /checkout/s/{sessionId} (hostedCheckout: true)Pass customerData at create → fields pre-fill on the hosted page
Embedded Altruon JSiframe on your sitePass 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 in server/src/routes.js. The browser only ever receives the resulting session_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 (inside billingData), and billingPlatformId are 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}): pass customerData (and optional top-level document) 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. Only billingAddress.country can be set on the frontend if not already on the session.

paymentData (required)​

Payment-related information for the transaction.

FieldTypeRequiredDescription
currencystringYesThree-letter ISO currency code (e.g., "USD", "EUR", "BRL"). Must be set via backend Create Session API.
paymentMethodstringNoPayment method type: "card", "upi", "pix", etc.

Note: If no paymentMethod is provided (discovery mode), the hosted checkout shows every payment method routed for the session currency (e.g. PIX and card for BRL). If you pass paymentMethod (e.g. "card"), only that method is shown. The Create Session response includes payment_method_pinned_at_create to reflect which mode you chose — see Payment method pinning.

On embedded Altruon JS, when no paymentMethod is 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.

FieldTypeRequiredDescription
redirectUrlstringYesFull 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.

FieldTypeRequiredDescription
localestringNoCheckout 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.

FieldTypeRequiredDescription
lineItemsarrayYesArray of items to be purchased. Each item must have type, id, and quantity. Must be set via backend Create Session API.
billingPlatformIdstringYesYour Altruon billing platform connection ID. Must be set via backend Create Session API.
frequencystringNoBilling frequency: "monthly", "yearly", "weekly", etc.
couponCodesarray of stringsNoCoupons to apply for estimate and subscription creation.
metadataobject (string → string)NoMerchant 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.
forceTrialPeriodDaysintegerNoOverride 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 → subscription meta_data; Frisbii → subscription metadata; Recurly → subscription custom_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 billingPlatformId in 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.

FieldTypeDescription
firstNamestringCustomer first name → main First name field on hosted checkout
lastNamestringCustomer last name → main Last name field
emailstringEmail address
phonestringPhone number (shown only if enabled under Settings → Checkout → Fields)
ipstringCustomer IP (optional; used by some gateways)
billingAddressobjectBilling address — see address fields below
shippingAddressobjectShipping address (shown only if shipping fields are enabled)

Address object (billingAddress / shippingAddress):

FieldTypeMaps to hosted checkout field
streetstringAddress line 1
numberstringAddress line 2 (apartment, suite, etc.)
citystringCity
statestringState / province
zipCodestringZip / postal code
countrystringCountry (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 billingAddress as well — they are not copied automatically from top-level firstName / 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.

FieldTypeDefaultDescription
hostedCheckoutbooleanfalseWhen 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.

FieldTypeDefaultDescription
backgroundColorstring#ffffffBackground color (hex, rgb, or named color)
primaryColorstring#4B5563Primary color for buttons and interactive elements
secondaryColorstring#9CA3AFSecondary color for supporting elements
accentColorstring#3B82F6Accent color for highlights and focus states
borderRadiusstring8pxBorder radius for rounded corners
headerTextColorstring#1F2937Header text color
textColorstring#1F2937Body text color
fontFamilystringsystem-ui, sans-serifFont family for all text
dropShadowbooleantrueWhether 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": "..."
}
FieldTypeDescription
session_idstringUnique session identifier (UUID)
expires_atstringISO 8601 timestamp when the session expires (15 minutes from creation)
checkout_urlstringPresent when hostedCheckout: true — redirect the shopper here
payment_method_pinned_at_createbooleanWhether you locked the payment method at session create. See Payment method pinning below.
available_payment_methodsarrayPresent in discovery mode (no paymentMethod in request)
payment_methodstringPresent in specific mode — the selected payment method
gatewaystringPresent in specific mode — the selected gateway
gateway_connection_idstringPresent in specific mode — gateway connection UUID
trialobjectPresent 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.

ValueYou sent at createHosted checkout behavior
falseNo 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).
truepaymentMethod 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​

CodeDescriptionResolution
invalid_requestMissing or invalid request parametersCheck request body structure
unauthorizedInvalid or missing API keyVerify your secret key
invalid_line_itemLine item ID not found or invalidCheck your billing provider
invalid_billing_platformBilling platform not configuredConfigure billing platform in dashboard
rate_limit_exceededToo many requestsImplement 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 (urlAtGateway and urlAtBilling) 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​