Partner Onboarding Guide
Welcome to DepartCart
This guide will walk you through the complete onboarding process to integrate DepartCart ancillary services into your booking platform.
Overview
DepartCart provides a complete ancillary commerce platform that enables airlines and travel partners to offer premium services like seat selection, priority support, travel insurance, and more. Our platform handles the entire transaction lifecycle from presentation to fulfillment.
Integration Timeline
Typical integration timeline: 2-4 weeks
- Week 1: Onboarding and credential setup
- Week 2: Technical integration and testing
- Week 3: User acceptance testing and refinements
- Week 4: Production deployment and go-live
Step 1: Provide Branding Information
Brand Assets Required
Please provide the following branding materials to ensure a seamless customer experience:
Logo Requirements
- Primary Logo: Vector format (SVG preferred) or high-resolution PNG (minimum 300x100px)
- Secondary/Icon Logo: Square format for use in compact spaces (minimum 100x100px)
- White/Light Versions: For use on dark backgrounds
- File Formats: SVG, PNG, or AI files
Color Palette
- Primary Brand Color: Hex code (e.g., #1E3A8A)
- Secondary Brand Color: Hex code (e.g., #3B82F6)
- Accent Colors: Additional brand colors (if applicable)
- Text Colors: Primary and secondary text colors
- Background Colors: Light and dark background preferences
Typography (Optional)
- Primary Font: Font family name and web font URL (if custom)
- Secondary Font: For body text (if different from primary)
- Font Weights: Specify which weights to use (normal, bold, etc.)
Brand Guidelines
- Style Guide: PDF or link to brand guidelines
- Usage Rules: Any specific requirements for logo usage
- Color Combinations: Preferred color combinations and restrictions
Example Brand Submission
{
"brand_name": "SkylineAir",
"primary_color": "#1E40AF",
"secondary_color": "#3B82F6",
"accent_color": "#10B981",
"text_primary": "#1F2937",
"text_secondary": "#6B7280",
"background_light": "#F9FAFB",
"background_dark": "#111827",
"primary_font": "Montserrat",
"font_url": "https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700",
"logo_primary": "https://assets.skylineair.com/logo-primary.svg",
"logo_icon": "https://assets.skylineair.com/logo-icon.svg"
}
Step 2: Provide GDS Credentials
Supported GDS Systems
DepartCart integrates with major Global Distribution Systems:
- Sabre (Red Apps certified)
- Amadeus (API certified)
- Travelport (Universal API)
Required GDS Access
For Sabre Integration
REST API Credentials:
- Client ID: Your Sabre REST API client ID
- Client Secret: Your Sabre REST API client secret
- Username: Your Sabre username
- Password: Your Sabre password
For Amadeus Integration
API Credentials:
- API Key: Your Amadeus API key
- API Secret: Your Amadeus API secret
- Client ID: Your Amadeus client ID
- Environment: Production or Test environment details
Required Access:
- Flight Offers Search API
- Flight Offers Price API
- Flight Create Orders API
- PNR Management API
- Seat Map Display API
Security Requirements
- IP Whitelisting: Provide our server IPs for GDS access
- SSL Certificates: Ensure proper SSL configuration
- Rate Limiting: Understand GDS rate limits and quotas
- Failover: Configure backup credentials if available
GDS Credential Submission Form
gds_provider: "sabre" # or "amadeus", "travelport"
environment: "production" # or "test"
# Sabre REST Credentials
rest_credentials:
client_id: "YOUR_CLIENT_ID"
client_secret: "YOUR_CLIENT_SECRET"
username: "YOUR_REST_USERNAME"
password: "YOUR_REST_PASSWORD"
# Network Configuration
network:
allowed_ips: ["52.1.2.3", "52.4.5.6"]
rate_limits:
requests_per_minute: 1000
burst_limit: 100
Step 3: Payment Gateway Configuration
Supported Payment Gateways
- Stripe (Recommended)
- Adyen
- PayPal
- Authorize.Net
Merchant of Record Benefits
As the merchant of record, you maintain:
- Full Revenue Control: All payments go directly to your account
- Complete Transaction Visibility: Access to all payment data
- Fraud Rule Management: Configure your own fraud prevention
- Chargeback Handling: Direct relationship with payment processor
- Compliance: Maintain your existing PCI compliance
Stripe Configuration
Required Credentials
- Publishable Key: For client-side payment forms
- Secret Key: For server-side API calls
- Webhook Endpoint Secret: For payment event notifications
Webhook Events to Enable
payment_intent.succeeded
payment_intent.payment_failed
charge.dispute.created
invoice.payment_succeeded
customer.subscription.updated
Example Stripe Configuration
{
"provider": "stripe",
"environment": "production",
"credentials": {
"publishable_key": "pk_live_YOUR_PUBLISHABLE_KEY",
"secret_key": "sk_live_YOUR_SECRET_KEY",
"webhook_secret": "whsec_YOUR_WEBHOOK_SECRET"
},
"settings": {
"currency": "USD",
"capture_method": "automatic",
"payment_methods": ["card", "apple_pay", "google_pay"],
"fraud_rules": {
"enabled": true,
"risk_threshold": "normal"
}
}
}
Adyen Configuration
Required Credentials
- API Key: For API authentication
- Merchant Account: Your Adyen merchant account ID
- Client Key: For client-side integration
- HMAC Key: For webhook verification
Example Adyen Configuration
{
"provider": "adyen",
"environment": "live",
"credentials": {
"api_key": "YOUR_API_KEY",
"merchant_account": "YOUR_MERCHANT_ACCOUNT",
"client_key": "YOUR_CLIENT_KEY",
"hmac_key": "YOUR_HMAC_KEY"
},
"settings": {
"currency": "USD",
"payment_methods": ["scheme", "applepay", "googlepay"],
"fraud_detection": {
"enabled": true,
"risk_score_threshold": 60
}
}
}
Payment Flow Architecture
sequenceDiagram
participant Customer
participant YourSite
participant DepartCart
participant PaymentGateway
participant GDS
Customer->>YourSite: Select ancillary products
YourSite->>DepartCart: Generate encrypted seatmap URL
Customer->>DepartCart: Access seatmap with encrypted data
DepartCart->>GDS: Retrieve seat availability
Customer->>DepartCart: Select seats and proceed to payment
DepartCart->>PaymentGateway: Process payment via your gateway
PaymentGateway->>YourSite: Payment webhook notification
DepartCart->>GDS: Fulfill seat assignments
DepartCart->>YourSite: Transaction webhook notification
Step 4: Generate Seatmap Deeplinks
Encryption is handled entirely server-side by DepartCart. You will be issued an API key and API secret (not encryption keys). You exchange those credentials for a short-lived bearer token, then call our deeplink endpoint with the raw pnr and last_name. DepartCart encrypts the passenger data and returns a ready-to-use seatmap URL.
Generating a deeplink is a two-step flow:
- Exchange your API key and secret for a bearer token.
- Call the deeplink endpoint with the bearer token to receive the seatmap URL.
Keep your API secret server-side. Always request bearer tokens from your backend so your secret is never exposed to browsers or end users.
The base URL for all requests is https://departcart.com.
Step 4.1: Request a Bearer Token
Exchange your API key and secret for a short-lived bearer token.
Request
curl -X POST https://departcart.com/generate-bearer-token \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_API_KEY",
"api_secret": "YOUR_API_SECRET",
"duration_hours": 24
}'
api_key(required): Your DepartCart API key.api_secret(required): Your DepartCart API secret. Keep this server-side.duration_hours(optional): Token lifetime in hours. Defaults to24.
Response
{
"success": true,
"bearer_token": "your_brand:...:...:...:...",
"token_type": "Bearer",
"expires_in": 86400,
"expires_at": 1718876400,
"brand": "your_brand"
}
Cache and reuse the token until it expires (expires_at is a Unix timestamp), then request a new one.
Step 4.2: Generate the Seatmap Deeplink
Call the deeplink endpoint with the bearer token and the passenger's raw pnr and last_name. The brand is derived from the bearer token, so it is not sent in the body.
Request
curl -X POST https://departcart.com/api/generate-encrypted-seatmap-url \
-H "Authorization: Bearer your_brand:...:...:...:..." \
-H "Content-Type: application/json" \
-d '{
"pnr": "ABC123",
"last_name": "SMITH",
"source": "api"
}'
pnr(required): The booking reference. Sent as plain text; DepartCart encrypts it server-side.last_name(required): The passenger's last name. Sent as plain text.source(optional): Attribution tag for the link. Defaults tocart.
Response
{
"success": true,
"encrypted_id": "Z0FBQUFB...",
"seatmap_url": "/seatmap?id=Z0FBQUFB...&source=api",
"source": "api"
}
seatmap_url is a path on the DepartCart domain. Build the customer-facing deeplink by prefixing it with https://departcart.com:
https://departcart.com/seatmap?id=Z0FBQUFB...&source=api
Code Examples
import requests
BASE_URL = "https://departcart.com"
def get_bearer_token(api_key, api_secret, duration_hours=24):
"""Exchange API credentials for a short-lived bearer token."""
response = requests.post(
f"{BASE_URL}/generate-bearer-token",
json={
"api_key": api_key,
"api_secret": api_secret,
"duration_hours": duration_hours,
},
)
response.raise_for_status()
return response.json()["bearer_token"]
def generate_seatmap_deeplink(bearer_token, pnr, last_name, source="api"):
"""Generate a customer-facing seatmap deeplink."""
response = requests.post(
f"{BASE_URL}/api/generate-encrypted-seatmap-url",
headers={
"Authorization": f"Bearer {bearer_token}",
"Content-Type": "application/json",
},
json={
"pnr": pnr,
"last_name": last_name,
"source": source,
},
)
response.raise_for_status()
seatmap_url = response.json()["seatmap_url"]
return f"{BASE_URL}{seatmap_url}"
# Example usage (run this from your backend)
token = get_bearer_token("YOUR_API_KEY", "YOUR_API_SECRET")
deeplink = generate_seatmap_deeplink(token, pnr="ABC123", last_name="SMITH")
print(deeplink) # https://departcart.com/seatmap?id=...&source=api
const BASE_URL = 'https://departcart.com';
async function getBearerToken(apiKey, apiSecret, durationHours = 24) {
// Exchange API credentials for a short-lived bearer token.
const response = await fetch(`${BASE_URL}/generate-bearer-token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: apiKey,
api_secret: apiSecret,
duration_hours: durationHours,
}),
});
if (!response.ok) throw new Error(`Token request failed: ${response.status}`);
const data = await response.json();
return data.bearer_token;
}
async function generateSeatmapDeeplink(bearerToken, pnr, lastName, source = 'api') {
// Generate a customer-facing seatmap deeplink.
const response = await fetch(`${BASE_URL}/api/generate-encrypted-seatmap-url`, {
method: 'POST',
headers: {
Authorization: `Bearer ${bearerToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ pnr, last_name: lastName, source }),
});
if (!response.ok) throw new Error(`Deeplink request failed: ${response.status}`);
const data = await response.json();
return `${BASE_URL}${data.seatmap_url}`;
}
// Example usage (run this from your backend so the API secret stays server-side)
const token = await getBearerToken('YOUR_API_KEY', 'YOUR_API_SECRET');
const deeplink = await generateSeatmapDeeplink(token, 'ABC123', 'SMITH');
console.log(deeplink); // https://departcart.com/seatmap?id=...&source=api
Testing Your Integration
Validate the end-to-end flow before going live:
- Request a token using your sandbox API key and secret against
https://departcart.com/generate-bearer-token. - Call the deeplink endpoint at
https://departcart.com/api/generate-encrypted-seatmap-urlwith the returned bearer token and a testpnrandlast_name. - Open the returned URL (
https://departcart.com+seatmap_url) in a browser to confirm the seatmap loads for the test booking.
Step 5: Integration Options
Option A: GTM Lightweight Integration ⭐ Recommended
Timeline: 1-2 days
Development Effort: Minimal
Customization: Limited but sufficient for most use cases
Deploy seat selection panels using Google Tag Manager. Perfect for:
- Quick deployment
- Minimal development resources
- Standard branding requirements
See our GTM Integration Guide for complete implementation details.
Option B: Full API Integration
Timeline: 2-3 weeks
Development Effort: Moderate to High
Customization: Complete control
Direct API integration with your existing systems. Ideal for:
- Complex custom requirements
- Deep system integration
- Advanced analytics and reporting
See our API Documentation for complete technical details.
Option C: Hybrid Approach
Timeline: 1-2 weeks
Development Effort: Low to Moderate
Customization: Balanced
Combine GTM panels with API webhooks for notifications. Best for:
- Quick deployment with backend integration
- Real-time transaction monitoring
- Custom post-purchase workflows
Step 6: Webhook Configuration
Webhook Endpoint Setup
Provide a secure HTTPS endpoint to receive transaction notifications:
https://api.your-domain.com/webhooks/departcart
Security Requirements
- HTTPS Only: Must use SSL/TLS encryption
- Signature Verification: Implement webhook signature validation
- Idempotency: Handle duplicate events gracefully
- Response Time: Respond within 10 seconds
Example Webhook Handler
import hmac
import hashlib
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhooks/departcart', methods=['POST'])
def handle_departcart_webhook():
# Verify signature
payload = request.get_data(as_text=True)
signature = request.headers.get('X-DepartCart-Signature')
if not verify_signature(payload, signature):
return 'Unauthorized', 401
# Process event
event = request.get_json()
process_webhook_event(event)
return 'OK', 200
def verify_signature(payload, signature):
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
def process_webhook_event(event):
event_type = event.get('type')
if event_type == 'transaction.completed':
handle_transaction_completed(event['data'])
elif event_type == 'payment.processed':
handle_payment_processed(event['data'])
elif event_type == 'fulfillment.updated':
handle_fulfillment_updated(event['data'])
else:
print(f"Unknown event type: {event_type}")
def handle_transaction_completed(data):
transaction_id = data['transaction_id']
amount = data['amount']
print(f"Transaction {transaction_id} completed for ${amount}")
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
[ApiController]
[Route("webhooks")]
public class WebhookController : ControllerBase
{
private readonly string _webhookSecret;
public WebhookController(IConfiguration configuration)
{
_webhookSecret = configuration["DepartCart:WebhookSecret"];
}
[HttpPost("departcart")]
public async Task<IActionResult> HandleDepartCartWebhook()
{
// Read payload
string payload;
using (var reader = new StreamReader(Request.Body))
{
payload = await reader.ReadToEndAsync();
}
// Verify signature
var signature = Request.Headers["X-DepartCart-Signature"].FirstOrDefault();
if (!VerifySignature(payload, signature))
{
return Unauthorized("Invalid signature");
}
// Process event
var webhookEvent = JsonConvert.DeserializeObject<WebhookEvent>(payload);
ProcessWebhookEvent(webhookEvent);
return Ok("Success");
}
private bool VerifySignature(string payload, string signature)
{
if (string.IsNullOrEmpty(signature) || !signature.StartsWith("sha256="))
{
return false;
}
var expectedSignature = signature.Substring(7); // Remove "sha256=" prefix
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_webhookSecret)))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
var computedSignature = Convert.ToHexString(hash).ToLower();
return CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(expectedSignature),
Encoding.UTF8.GetBytes(computedSignature)
);
}
}
private void ProcessWebhookEvent(WebhookEvent webhookEvent)
{
switch (webhookEvent.Type)
{
case "transaction.completed":
HandleTransactionCompleted(webhookEvent.Data);
break;
case "payment.processed":
HandlePaymentProcessed(webhookEvent.Data);
break;
case "fulfillment.updated":
HandleFulfillmentUpdated(webhookEvent.Data);
break;
default:
Console.WriteLine($"Unknown event type: {webhookEvent.Type}");
break;
}
}
private void HandleTransactionCompleted(dynamic data)
{
var transactionId = data.transaction_id;
var amount = data.amount;
Console.WriteLine($"Transaction {transactionId} completed for ${amount}");
}
private void HandlePaymentProcessed(dynamic data)
{
var paymentId = data.payment_id;
Console.WriteLine($"Payment {paymentId} processed successfully");
}
private void HandleFulfillmentUpdated(dynamic data)
{
var status = data.status;
Console.WriteLine($"Fulfillment status updated to: {status}");
}
}
public class WebhookEvent
{
public string Type { get; set; }
public dynamic Data { get; set; }
}
const express = require('express');
const crypto = require('crypto');
const app = express();
// Middleware to capture raw body for signature verification
app.use('/webhooks/departcart', express.raw({ type: 'application/json' }));
app.post('/webhooks/departcart', (req, res) => {
try {
// Get payload and signature
const payload = req.body.toString();
const signature = req.headers['x-departcart-signature'];
// Verify signature
if (!verifySignature(payload, signature)) {
return res.status(401).send('Unauthorized');
}
// Process event
const event = JSON.parse(payload);
processWebhookEvent(event);
res.status(200).send('OK');
} catch (error) {
console.error('Webhook error:', error);
res.status(500).send('Internal Server Error');
}
});
function verifySignature(payload, signature) {
if (!signature || !signature.startsWith('sha256=')) {
return false;
}
const expectedSignature = signature.slice(7); // Remove 'sha256=' prefix
const computedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(computedSignature, 'hex')
);
}
function processWebhookEvent(event) {
switch (event.type) {
case 'transaction.completed':
handleTransactionCompleted(event.data);
break;
case 'payment.processed':
handlePaymentProcessed(event.data);
break;
case 'fulfillment.updated':
handleFulfillmentUpdated(event.data);
break;
default:
console.log(`Unknown event type: ${event.type}`);
}
}
function handleTransactionCompleted(data) {
const transactionId = data.transaction_id;
const amount = data.amount;
console.log(`Transaction ${transactionId} completed for $${amount}`);
}
function handlePaymentProcessed(data) {
const paymentId = data.payment_id;
console.log(`Payment ${paymentId} processed successfully`);
}
function handleFulfillmentUpdated(data) {
const status = data.status;
console.log(`Fulfillment status updated to: ${status}`);
}
app.listen(3000, () => {
console.log('Webhook server listening on port 3000');
});
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.beans.factory.annotation.Value;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@RestController
@RequestMapping("/webhooks")
public class WebhookController {
@Value("${departcart.webhook.secret}")
private String webhookSecret;
private final ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/departcart")
public ResponseEntity<String> handleDepartCartWebhook(
@RequestBody String payload,
@RequestHeader("X-DepartCart-Signature") String signature) {
try {
// Verify signature
if (!verifySignature(payload, signature)) {
return ResponseEntity.status(401).body("Unauthorized");
}
// Process event
JsonNode event = objectMapper.readTree(payload);
processWebhookEvent(event);
return ResponseEntity.ok("Success");
} catch (Exception e) {
System.err.println("Webhook processing error: " + e.getMessage());
return ResponseEntity.status(500).body("Internal Server Error");
}
}
private boolean verifySignature(String payload, String signature) {
if (signature == null || !signature.startsWith("sha256=")) {
return false;
}
try {
String expectedSignature = signature.substring(7); // Remove "sha256=" prefix
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(
webhookSecret.getBytes(), "HmacSHA256");
mac.init(secretKeySpec);
byte[] hash = mac.doFinal(payload.getBytes());
String computedSignature = bytesToHex(hash);
return MessageDigest.isEqual(
expectedSignature.getBytes(),
computedSignature.getBytes()
);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
System.err.println("Signature verification error: " + e.getMessage());
return false;
}
}
private void processWebhookEvent(JsonNode event) {
String eventType = event.get("type").asText();
JsonNode data = event.get("data");
switch (eventType) {
case "transaction.completed":
handleTransactionCompleted(data);
break;
case "payment.processed":
handlePaymentProcessed(data);
break;
case "fulfillment.updated":
handleFulfillmentUpdated(data);
break;
default:
System.out.println("Unknown event type: " + eventType);
}
}
private void handleTransactionCompleted(JsonNode data) {
String transactionId = data.get("transaction_id").asText();
double amount = data.get("amount").asDouble();
System.out.println("Transaction " + transactionId +
" completed for $" + amount);
}
private void handlePaymentProcessed(JsonNode data) {
String paymentId = data.get("payment_id").asText();
System.out.println("Payment " + paymentId + " processed successfully");
}
private void handleFulfillmentUpdated(JsonNode data) {
String status = data.get("status").asText();
System.out.println("Fulfillment status updated to: " + status);
}
private String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
require 'sinatra'
require 'json'
require 'openssl'
# Configure webhook secret
WEBHOOK_SECRET = ENV['WEBHOOK_SECRET']
post '/webhooks/departcart' do
# Get payload and signature
payload = request.body.read
signature = request.env['HTTP_X_DEPARTCART_SIGNATURE']
# Verify signature
unless verify_signature(payload, signature)
halt 401, 'Unauthorized'
end
# Process event
begin
event = JSON.parse(payload)
process_webhook_event(event)
rescue JSON::ParserError => e
puts "JSON parsing error: #{e.message}"
halt 400, 'Bad Request'
rescue StandardError => e
puts "Processing error: #{e.message}"
halt 500, 'Internal Server Error'
end
status 200
body 'OK'
end
def verify_signature(payload, signature)
return false if signature.nil? || !signature.start_with?('sha256=')
expected_signature = signature[7..-1] # Remove 'sha256=' prefix
computed_signature = OpenSSL::HMAC.hexdigest(
OpenSSL::Digest.new('sha256'),
WEBHOOK_SECRET,
payload
)
# Use secure comparison to prevent timing attacks
Rack::Utils.secure_compare(expected_signature, computed_signature)
end
def process_webhook_event(event)
event_type = event['type']
data = event['data']
case event_type
when 'transaction.completed'
handle_transaction_completed(data)
when 'payment.processed'
handle_payment_processed(data)
when 'fulfillment.updated'
handle_fulfillment_updated(data)
else
puts "Unknown event type: #{event_type}"
end
end
def handle_transaction_completed(data)
transaction_id = data['transaction_id']
amount = data['amount']
puts "Transaction #{transaction_id} completed for $#{amount}"
end
def handle_payment_processed(data)
payment_id = data['payment_id']
puts "Payment #{payment_id} processed successfully"
end
def handle_fulfillment_updated(data)
status = data['status']
puts "Fulfillment status updated to: #{status}"
end
# Start the server
if __FILE__ == $0
set :port, 4567
set :bind, '0.0.0.0'
puts "Webhook server starting on port 4567"
end
Webhook Events
You'll receive notifications for:
- Transaction Created: New ancillary purchase initiated
- Payment Completed: Payment successfully processed
- Fulfillment Status: Product fulfillment with airline
- Refund Processed: Refund issued to customer
See Webhook Documentation for complete event schemas.
Step 7: Testing & Go-Live
Sandbox Testing
- Receive sandbox credentials from our team
- Generate seatmap deeplinks with test data
- Verify webhook handling with sample events
- Complete end-to-end transaction in sandbox
- Performance testing under load
User Acceptance Testing
- Internal testing with your team
- Stakeholder review of user experience
- Brand compliance verification
- Mobile responsiveness testing
- Cross-browser compatibility testing
Production Deployment
- Switch to production credentials
- Update DNS/CDN configurations
- Monitor initial transactions
- Verify webhook notifications
- Confirm GDS fulfillment
Launch Checklist
- [ ] Branding assets implemented correctly
- [ ] GDS integration tested and working
- [ ] Payment gateway processing successfully
- [ ] Seatmap deeplink generation verified
- [ ] GTM/API integration deployed
- [ ] Webhooks receiving and processing events
- [ ] Customer support team trained
- [ ] Monitoring and alerting configured
- [ ] Rollback plan prepared
Support During Onboarding
Dedicated Support Team
During onboarding, you'll have access to:
- Integration Engineer: Technical implementation support
- Account Manager: Overall project coordination
- QA Specialist: Testing and validation assistance
Communication Channels
- Slack Channel: Real-time chat support (invitation provided)
- Email: integration@departcart.com
- Video Calls: Weekly check-ins scheduled
Documentation & Resources
- Technical Documentation: Complete API and integration guides
- Code Examples: Sample implementations in multiple languages
- Best Practices: Proven patterns from successful integrations
- Troubleshooting: Common issues and solutions
Post-Launch Support
Ongoing Support Includes
- Technical Support: Bug fixes and integration issues
- Feature Updates: New products and capabilities
- Performance Monitoring: API performance and uptime tracking
- Business Reviews: Regular performance and optimization meetings
SLA Commitments
- API Uptime: 99.9%
- Support Response: < 4 hours (business days)
- Critical Issues: < 1 hour (24/7)
- Feature Requests: Quarterly roadmap reviews
Next Steps
Ready to get started? Contact our integration team:
📧 Email: hello@departcart.com
We'll set up your initial onboarding call within 24 hours and provide you with:
- Dedicated Slack channel
- Sandbox credentials
- Project timeline
- Technical documentation access
Welcome to DepartCart! We're excited to help you maximize your ancillary revenue. 🚀