DepartCart provides secure, white-label ancillary services for airlines and travel partners. We recommend implementing client-side encryption to generate encrypted URLs directly in your application for optimal performance and security. API endpoints are also available as a fallback option.
Each partner brand has unique encryption parameters for security isolation:
{
"brand": "your_brand_name",
"password": "your-brand-secret-key-2025",
"salt": "your_brand_salt_2025"
}
Note: Actual credentials are provided during onboarding and differ from examples shown here.
β This is the recommended approach for generating encrypted seatmap URLs. Benefits include:
PNR and passenger data is encrypted using this JSON structure:
{
"pnr": "ABC123",
"last_name": "SMITH",
"brand": "your_brand_name"
}
import json
import base64
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
def encrypt_passenger_data(pnr, last_name, brand_name, password, salt):
"""Encrypt passenger data for DepartCart API"""
# Prepare data payload
data = {
"pnr": pnr.strip().upper(),
"last_name": last_name.strip().upper(),
"brand": brand_name
}
# Derive encryption key
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt.encode(),
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
# Encrypt data
fernet = Fernet(key)
json_data = json.dumps(data)
encrypted_data = fernet.encrypt(json_data.encode())
# Return URL-safe base64 encoded string
return base64.urlsafe_b64encode(encrypted_data).decode()
# Example usage
encrypted_id = encrypt_passenger_data(
pnr="ABC123",
last_name="SMITH",
brand_name="your_brand",
password="your-brand-secret-key-2025",
salt="your_brand_salt_2025"
)
# Create seatmap URL
seatmap_url = f"https://departcart.com/seatmap?id={encrypted_id}&source=api"
using System;
using System.Text;
using System.Text.Json;
using System.Security.Cryptography;
public class DepartCartEncryption
{
public static string EncryptPassengerData(string pnr, string lastName,
string brandName, string password, string salt)
{
// Prepare data payload
var data = new
{
pnr = pnr.Trim().ToUpper(),
last_name = lastName.Trim().ToUpper(),
brand = brandName
};
// Convert to JSON
string jsonData = JsonSerializer.Serialize(data);
byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonData);
// Derive key using PBKDF2
using (var pbkdf2 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 100000))
{
byte[] key = pbkdf2.GetBytes(32);
// Encrypt using AES
using (var aes = Aes.Create())
{
aes.Key = key;
aes.GenerateIV();
using (var encryptor = aes.CreateEncryptor())
{
byte[] encrypted = encryptor.TransformFinalBlock(jsonBytes, 0, jsonBytes.Length);
// Combine IV + encrypted data
byte[] result = new byte[aes.IV.Length + encrypted.Length];
Array.Copy(aes.IV, 0, result, 0, aes.IV.Length);
Array.Copy(encrypted, 0, result, aes.IV.Length, encrypted.Length);
return Convert.ToBase64String(result);
}
}
}
}
}
// Example usage
string encryptedId = DepartCartEncryption.EncryptPassengerData(
pnr: "ABC123",
lastName: "SMITH",
brandName: "your_brand",
password: "your-brand-secret-key-2025",
salt: "your_brand_salt_2025"
);
string seatmapUrl = $"https://departcart.com/seatmap?id={encryptedId}&source=api";
const crypto = require('crypto');
function encryptPassengerData(pnr, lastName, brandName, password, salt) {
// Prepare data payload
const data = {
pnr: pnr.trim().toUpperCase(),
last_name: lastName.trim().toUpperCase(),
brand: brandName
};
// Convert to JSON
const jsonData = JSON.stringify(data);
// Derive key using PBKDF2
const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
// Generate IV and encrypt
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(jsonData, 'utf8', 'base64');
encrypted += cipher.final('base64');
// Combine IV + encrypted data
const combined = Buffer.concat([iv, Buffer.from(encrypted, 'base64')]);
return combined.toString('base64');
}
// Example usage
const encryptedId = encryptPassengerData(
'ABC123',
'SMITH',
'your_brand',
'your-brand-secret-key-2025',
'your_brand_salt_2025'
);
const seatmapUrl = `https://departcart.com/seatmap?id=${encryptedId}&source=api`;
import java.util.Base64;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
public class DepartCartEncryption {
public static String encryptPassengerData(String pnr, String lastName,
String brandName, String password, String salt) throws Exception {
// Prepare data payload
Map<String, String> data = new HashMap<>();
data.put("pnr", pnr.trim().toUpperCase());
data.put("last_name", lastName.trim().toUpperCase());
data.put("brand", brandName);
// Convert to JSON
ObjectMapper mapper = new ObjectMapper();
String jsonData = mapper.writeValueAsString(data);
// Derive key using PBKDF2
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 100000, 256);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] key = factory.generateSecret(spec).getEncoded();
// Generate IV and encrypt
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(jsonData.getBytes("UTF-8"));
// Combine IV + encrypted data
byte[] result = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(encrypted, 0, result, iv.length, encrypted.length);
return Base64.getEncoder().encodeToString(result);
}
// Example usage
public static void main(String[] args) throws Exception {
String encryptedId = encryptPassengerData(
"ABC123",
"SMITH",
"your_brand",
"your-brand-secret-key-2025",
"your_brand_salt_2025"
);
String seatmapUrl = "https://departcart.com/seatmap?id=" + encryptedId + "&source=api";
System.out.println(seatmapUrl);
}
}
require 'openssl'
require 'base64'
require 'json'
class DepartCartEncryption
def self.encrypt_passenger_data(pnr, last_name, brand_name, password, salt)
# Prepare data payload
data = {
pnr: pnr.strip.upcase,
last_name: last_name.strip.upcase,
brand: brand_name
}
# Convert to JSON
json_data = data.to_json
# Derive key using PBKDF2
key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, 100000, 32, OpenSSL::Digest::SHA256.new)
# Generate IV and encrypt
cipher = OpenSSL::Cipher.new('AES-256-CBC')
cipher.encrypt
cipher.key = key
iv = cipher.random_iv
encrypted = cipher.update(json_data) + cipher.final
# Combine IV + encrypted data
result = iv + encrypted
Base64.strict_encode64(result)
end
end
# Example usage
encrypted_id = DepartCartEncryption.encrypt_passenger_data(
'ABC123',
'SMITH',
'your_brand',
'your-brand-secret-key-2025',
'your_brand_salt_2025'
)
seatmap_url = "https://departcart.com/seatmap?id=#{encrypted_id}&source=api"
puts seatmap_url
Endpoint: POST /api/generate-encrypted-seatmap-url
Description: Server-side encryption for partners who prefer not to implement client-side encryption. Note: Client-side encryption is recommended for better performance and reliability.
Request Body:
{
"pnr": "ABC123",
"last_name": "SMITH",
"brand": "your_brand_name"
}
Response:
{
"success": true,
"encrypted_id": "Z0FBQUFBQm9VQTE2TnFpUk1Uc0lfd1lyX3VLcUU2aEN5UndZUnp3RS1ma2UxM1hQZjg4Z3ZILWQtOWNxZVBhTzFING5IaUdyZ2ZmRjhwaDR0WHRVWERZRGVNYVlWbVBXUHJTVVlUMmZsR3VoU3RCdjBVNnRHcWZ3SWJSOEFFM28ycjNCN3BZbXA5Tjd1SkxuSTd2cDhadGN5Sm14OTU1blh3PT0=",
"seatmap_url": "https://departcart.com/seatmap?id=Z0FBQUFBQm9VQTE2TnFpUk1Uc0lfd1lyX3VLcUU2aEN5UndZUnp3RS1ma2UxM1hQZjg4Z3ZILWQtOWNxZVBhTzFING5IaUdyZ2ZmRjhwaDR0WHRVWERZRGVNYVlWbVBXUHJTVVlUMmZsR3VoU3RCdjBVNnRHcWZ3SWJSOEFFM28ycjNCN3BZbXA5Tjd1SkxuSTd2cDladGN5Sm14OTU1blh3PT0=&source=api"
}
Example Usage:
import requests
response = requests.post('https://departcart.com/api/generate-encrypted-seatmap-url', json={
'pnr': 'ABC123',
'last_name': 'SMITH',
'brand': 'your_brand_name'
})
data = response.json()
seatmap_url = data['seatmap_url']
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
var payload = new
{
pnr = "ABC123",
last_name = "SMITH",
brand = "your_brand_name"
};
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://departcart.com/api/generate-encrypted-seatmap-url",
content);
var responseData = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ApiResponse>(responseData);
string seatmapUrl = result.seatmap_url;
const response = await fetch('https://departcart.com/api/generate-encrypted-seatmap-url', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
pnr: 'ABC123',
last_name: 'SMITH',
brand: 'your_brand_name'
})
});
const data = await response.json();
const seatmapUrl = data.seatmap_url;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
public class DepartCartAPI {
public static String generateSeatmapUrl(String pnr, String lastName, String brandName)
throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
// Prepare payload
Map<String, String> payload = new HashMap<>();
payload.put("pnr", pnr);
payload.put("last_name", lastName);
payload.put("brand", brandName);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(payload);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://departcart.com/api/generate-encrypted-seatmap-url"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
Map<String, Object> result = mapper.readValue(response.body(), Map.class);
return (String) result.get("seatmap_url");
}
// Example usage
public static void main(String[] args) throws Exception {
String seatmapUrl = generateSeatmapUrl("ABC123", "SMITH", "your_brand_name");
System.out.println("Seat selection: " + seatmapUrl);
}
}
require 'net/http'
require 'uri'
require 'json'
class DepartCartAPI
def self.generate_seatmap_url(pnr, last_name, brand_name)
uri = URI('https://departcart.com/api/generate-encrypted-seatmap-url')
payload = {
pnr: pnr,
last_name: last_name,
brand: brand_name
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = payload.to_json
response = http.request(request)
if response.code == '200'
result = JSON.parse(response.body)
result['seatmap_url']
else
nil # Handle error
end
end
end
# Example usage
seatmap_url = DepartCartAPI.generate_seatmap_url('ABC123', 'SMITH', 'your_brand_name')
puts "Seat selection: #{seatmap_url}" if seatmap_url
Endpoint: GET /seatmap
Parameters:
id (string): Encrypted passenger data IDsource (string, optional): Integration source identifier (api, gtm, cart, etc.)Example:
https://departcart.com/seatmap?id=Z0FBQUFBQm9VQTE2...&source=api
For a quick, low-maintenance integration, use Google Tag Manager to inject seat selection panels into your confirmation or account pages.
GTM Code Template:
<script>
(function() {
// Ultra-minimal GTM injectable - just loads the script, no logic
var script = document.createElement('script');
script.src = 'https://departcart.com/static/loaders-dist/seat_selection_loader.js';
script.setAttribute('data-gtm-source', 'true');
document.head.appendChild(script);
})();
</script>
Benefits:
Setup Steps:
For detailed GTM integration instructions, see: GTM Integration Guide
DepartCart sends webhook notifications for all transaction events to keep partners updated in real-time.
Webhook URL Setup: Configure your webhook endpoint during onboarding.
transaction.created - New ancillary purchase initiatedtransaction.completed - Payment successful and services confirmedtransaction.failed - Payment or service confirmation failedtransaction.refunded - Full or partial refund processed{
"event_type": "transaction.completed",
"event_id": "evt_1234567890",
"timestamp": "2025-06-16T10:30:00Z",
"brand": "your_brand_name",
"transaction": {
"id": "txn_abc123def456",
"pnr": "ABC123",
"status": "completed",
"total_amount": 89.98,
"currency": "USD",
"payment": {
"method": "stripe",
"gateway_transaction_id": "pi_1234567890",
"amount_charged": 89.98,
"processing_fee": 2.70,
"net_amount": 87.28
},
"passenger": {
"first_name": "John",
"last_name": "SMITH",
"email": "john.smith@example.com"
},
"flight": {
"airline_code": "AA",
"flight_number": "1234",
"departure_date": "2025-06-20",
"departure_airport": "JFK",
"arrival_airport": "LAX",
"segment_id": "AA1234-20250620-JFKLAX"
},
"ancillaries": [
{
"type": "seat",
"description": "Premium Economy Seat 12A",
"seat_number": "12A",
"price": 45.00,
"cost": 15.00,
"margin": 30.00
},
{
"type": "baggage",
"description": "Extra Baggage 23kg",
"weight": "23kg",
"price": 44.98,
"cost": 25.00,
"margin": 19.98
}
],
"fulfillment": {
"seat_confirmation": "CONFIRMED",
"baggage_confirmation": "CONFIRMED",
"gds_record_locator": "ABC123",
"updated_at": "2025-06-16T10:29:45Z"
}
}
}
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
@app.route('/webhook/departcart', methods=['POST'])
def handle_departcart_webhook():
# Verify webhook signature (recommended)
signature = request.headers.get('X-DepartCart-Signature')
payload = request.get_data()
if not verify_webhook_signature(payload, signature):
return jsonify({'error': 'Invalid signature'}), 401
# Process webhook data
webhook_data = request.get_json()
event_type = webhook_data['event_type']
transaction = webhook_data['transaction']
if event_type == 'transaction.completed':
# Update your records
update_booking_ancillaries(
pnr=transaction['pnr'],
ancillaries=transaction['ancillaries'],
payment_info=transaction['payment']
)
# Send confirmation email
send_purchase_confirmation(
passenger=transaction['passenger'],
flight=transaction['flight'],
ancillaries=transaction['ancillaries']
)
elif event_type == 'transaction.refunded':
# Process refund
process_refund(
transaction_id=transaction['id'],
refund_amount=transaction['payment']['amount_charged']
)
return jsonify({'status': 'received'}), 200
def verify_webhook_signature(payload, signature):
# Verify using your webhook secret
webhook_secret = "your_webhook_secret_key"
expected_signature = hmac.new(
webhook_secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected_signature}", signature)
using Microsoft.AspNetCore.Mvc;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
[ApiController]
[Route("webhook")]
public class WebhookController : ControllerBase
{
[HttpPost("departcart")]
public async Task<IActionResult> HandleDepartCartWebhook()
{
// Read webhook payload
using var reader = new StreamReader(Request.Body);
var payload = await reader.ReadToEndAsync();
// Verify signature
var signature = Request.Headers["X-DepartCart-Signature"].FirstOrDefault();
if (!VerifyWebhookSignature(payload, signature))
{
return Unauthorized("Invalid signature");
}
// Parse webhook data
var webhookData = JsonSerializer.Deserialize<WebhookPayload>(payload);
switch (webhookData.event_type)
{
case "transaction.completed":
await HandleTransactionCompleted(webhookData.transaction);
break;
case "transaction.refunded":
await HandleTransactionRefunded(webhookData.transaction);
break;
}
return Ok(new { status = "received" });
}
private bool VerifyWebhookSignature(string payload, string signature)
{
var webhookSecret = "your_webhook_secret_key";
var keyBytes = Encoding.UTF8.GetBytes(webhookSecret);
var payloadBytes = Encoding.UTF8.GetBytes(payload);
using var hmac = new HMACSHA256(keyBytes);
var computedHash = hmac.ComputeHash(payloadBytes);
var expectedSignature = $"sha256={Convert.ToHexString(computedHash).ToLower()}";
return string.Equals(expectedSignature, signature, StringComparison.OrdinalIgnoreCase);
}
}
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.raw({ type: 'application/json' }));
app.post('/webhook/departcart', (req, res) => {
const signature = req.headers['x-departcart-signature'];
const payload = req.body;
// Verify webhook signature
if (!verifyWebhookSignature(payload, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Parse webhook data
const webhookData = JSON.parse(payload);
const { event_type, transaction } = webhookData;
switch (event_type) {
case 'transaction.completed':
handleTransactionCompleted(transaction);
break;
case 'transaction.refunded':
handleTransactionRefunded(transaction);
break;
}
res.json({ status: 'received' });
});
function verifyWebhookSignature(payload, signature) {
const webhookSecret = 'your_webhook_secret_key';
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(`sha256=${expectedSignature}`),
Buffer.from(signature)
);
}
async function handleTransactionCompleted(transaction) {
// Update booking records
await updateBookingAncillaries(transaction);
// Send confirmation email
await sendPurchaseConfirmation(transaction);
}
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import javax.servlet.http.HttpServletRequest;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
@RestController
@RequestMapping("/webhook")
public class WebhookController {
private static final String WEBHOOK_SECRET = "your_webhook_secret_key";
@PostMapping("/departcart")
public ResponseEntity<Map<String, String>> handleDepartCartWebhook(
HttpServletRequest request, @RequestBody String payload) {
try {
// Verify signature
String signature = request.getHeader("X-DepartCart-Signature");
if (!verifyWebhookSignature(payload, signature)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Map.of("error", "Invalid signature"));
}
// Parse webhook data
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> webhookData = mapper.readValue(payload, Map.class);
String eventType = (String) webhookData.get("event_type");
Map<String, Object> transaction = (Map<String, Object>) webhookData.get("transaction");
switch (eventType) {
case "transaction.completed":
handleTransactionCompleted(transaction);
break;
case "transaction.refunded":
handleTransactionRefunded(transaction);
break;
}
return ResponseEntity.ok(Map.of("status", "received"));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", "Processing error"));
}
}
private boolean verifyWebhookSignature(String payload, String signature)
throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(WEBHOOK_SECRET.getBytes(), "HmacSHA256");
mac.init(secretKey);
byte[] hash = mac.doFinal(payload.getBytes());
StringBuilder expectedSignature = new StringBuilder("sha256=");
for (byte b : hash) {
expectedSignature.append(String.format("%02x", b));
}
return expectedSignature.toString().equals(signature);
}
private void handleTransactionCompleted(Map<String, Object> transaction) {
// Update booking records and send confirmation email
System.out.println("Transaction completed: " + transaction.get("id"));
}
private void handleTransactionRefunded(Map<String, Object> transaction) {
// Process refund
System.out.println("Transaction refunded: " + transaction.get("id"));
}
}
require 'sinatra'
require 'json'
require 'openssl'
class WebhookController < Sinatra::Base
WEBHOOK_SECRET = 'your_webhook_secret_key'
post '/webhook/departcart' do
# Read payload
request.body.rewind
payload = request.body.read
# Verify signature
signature = request.env['HTTP_X_DEPARTCART_SIGNATURE']
unless verify_webhook_signature(payload, signature)
status 401
return { error: 'Invalid signature' }.to_json
end
# Parse webhook data
webhook_data = JSON.parse(payload)
event_type = webhook_data['event_type']
transaction = webhook_data['transaction']
case event_type
when 'transaction.completed'
handle_transaction_completed(transaction)
when 'transaction.refunded'
handle_transaction_refunded(transaction)
end
content_type :json
{ status: 'received' }.to_json
end
private
def verify_webhook_signature(payload, signature)
expected_signature = "sha256=#{OpenSSL::HMAC.hexdigest('SHA256', WEBHOOK_SECRET, payload)}"
Rack::Utils.secure_compare(expected_signature, signature)
end
def handle_transaction_completed(transaction)
# Update booking records and send confirmation email
puts "Transaction completed: #{transaction['id']}"
end
def handle_transaction_refunded(transaction)
# Process refund
puts "Transaction refunded: #{transaction['id']}"
end
end
200 - Success400 - Bad Request (invalid parameters)401 - Unauthorized (invalid or missing credentials)403 - Forbidden (insufficient permissions)404 - Not Found (resource doesn't exist)422 - Unprocessable Entity (validation errors)500 - Internal Server Error{
"success": false,
"error": {
"code": "INVALID_PNR",
"message": "The provided PNR could not be found or is invalid",
"details": {
"pnr": "ABC123",
"brand": "your_brand_name"
}
}
}
INVALID_PNR - PNR not found or invalid formatENCRYPTION_ERROR - Failed to decrypt passenger dataBRAND_NOT_CONFIGURED - Brand not set up for ancillary servicesPAYMENT_FAILED - Payment processing errorGDS_ERROR - Unable to communicate with airline reservation systemComplete these steps to get your DepartCart integration up and running quickly.
Essential setup items needed before development begins
Choose your preferred integration approach
Validate your integration before going live
Final steps for production deployment
| Phase | Duration | Activities |
|---|---|---|
| Setup | 1-2 weeks | Onboarding, credentials, branding |
| Development | 2-4 weeks | Implement encryption, integrate APIs |
| Testing | 1-2 weeks | End-to-end testing, UAT |
| Launch | 1 week | Production deployment, monitoring |
For detailed implementation steps, see: Partner Onboarding Guide
This documentation is updated regularly. For the latest version, visit: https://departcart.com/docs