DepartCart API Reference
Overview
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.
Table of Contents
- Authentication & Security
- Client-Side Encryption (Recommended)
- API Endpoints (Fallback)
- GTM Integration
- Webhook Notifications
- Error Handling
- Implementation Guide
Authentication & Security
Brand-Specific Encryption
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.
Client-Side Encryption (Recommended)
β This is the recommended approach for generating encrypted seatmap URLs. Benefits include:
- No API Dependencies: Generate URLs without calling our servers
- Better Performance: No network latency or rate limits
- Higher Reliability: Works during service outages
- Enhanced Security: Data encrypted before leaving your application
Data Format
PNR and passenger data is encrypted using this JSON structure:
{
"pnr": "ABC123",
"last_name": "SMITH",
"brand": "your_brand_name"
}
Implementation Examples
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
API Endpoints (Fallback)
Generate Encrypted 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
Seatmap Display
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
GTM Integration
Lightweight Integration
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:
- Minimal development: Just add GTM code
- Auto-detection: Finds PNR/passenger data from page
- Modal interface: No page navigation required
- Responsive design: Works on all devices
Setup Steps:
- Add the GTM code above to your tag manager
- Configure trigger for confirmation/account pages
- Ensure your pages have identifiable booking elements
- Test with sample bookings
For detailed GTM integration instructions, see: GTM Integration Guide
Webhook Notifications
Real-Time Transaction Updates
DepartCart sends webhook notifications for all transaction events to keep partners updated in real-time.
Webhook URL Setup: Configure your webhook endpoint during onboarding.
Event Types
transaction.created- New ancillary purchase initiatedtransaction.completed- Payment successful and services confirmedtransaction.failed- Payment or service confirmation failedtransaction.refunded- Full or partial refund processed
Webhook Payload
{
"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"
}
}
}
Webhook Implementation Examples
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
Error Handling
HTTP Status Codes
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
Error Response Format
{
"success": false,
"error": {
"code": "INVALID_PNR",
"message": "The provided PNR could not be found or is invalid",
"details": {
"pnr": "ABC123",
"brand": "your_brand_name"
}
}
}
Common Error Codes
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 system
Implementation Guide
π Quick Start Checklist
Complete these steps to get your DepartCart integration up and running quickly.
π Phase 1: Onboarding Requirements
Essential setup items needed before development begins
- [ ] π¨ Provide branding assets (logos, color palette)
- [ ] π Share GDS credentials (Sabre/Amadeus access)
- [ ] π³ Configure payment gateway (Stripe/Adyen)
- [ ] π Receive encryption keys and webhook secrets
- [ ] π Set up webhook endpoint
βοΈ Phase 2: Integration Options
Choose your preferred integration approach
- [ ] πββοΈ GTM Integration (fastest): Add GTM code to confirmation pages
- [ ] π οΈ API Integration (custom): Implement encryption and direct API calls
- [ ] π Hybrid Approach: GTM for UI, API for custom workflows
π§ͺ Phase 3: Testing
Validate your integration before going live
- [ ] π Test encryption/decryption with sample data
- [ ] πΊοΈ Verify seatmap loads correctly
- [ ] π’ Test webhook notifications
- [ ] π° Validate payment processing
π― Phase 4: Go Live
Final steps for production deployment
- [ ] π Production credentials configured
- [ ] π Webhook monitoring set up
- [ ] π¨ Error handling implemented
- [ ] π Support contact established
β±οΈ Estimated Timeline: 4-8 weeks total
Integration Timeline
| 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
Support & Resources
Documentation Links
Support Contacts
- Technical Support: support@departcart.com
- Integration Team: integration@departcart.com
- Account Management: accounts@departcart.com
Testing Tools
- URL Generator: https://departcart.com/generate-encrypted-url
- Encryption Test: https://departcart.com/test-encryption
- API Documentation: https://departcart.com/api/docs
This documentation is updated regularly. For the latest version, visit: https://departcart.com/docs