Partner Integration Guide

Overview

DepartCart encrypts PNR and passenger last name data in seatmap URLs to protect sensitive passenger information. Partners do not perform any encryption themselves. Instead you authenticate with an API key and secret to obtain a short-lived bearer token, then call our API with the raw booking details (pnr and last_name). DepartCart encrypts the data server-side and returns a ready-to-use seatmap deeplink:

https://departcart.com/seatmap?id=Z0FBQUFBQm9VQTE2TnFpUk1Uc0lfd1lyX3VLcUU2aEN5UndZUnp3RS1ma2UxM1hQZjg4Z3ZILWQtOWNxZVBhTzFING5IaUdyZ2ZmRjhwaDR0WHRVWERZRGVNYVlWbVBXUHJTVVlUMmZsR3VoU3RCdjBVNnRHcWZ3SWJSOFFFM28ycjNCN3BZbXA5Tjd1SkxuSTd2cDhadGN5Sm14OTU1blh3PT0=&source=cart

Last name validation: When a passenger opens the link, DepartCart validates that the last name in the encrypted URL matches any passenger on the booking — not just the lead traveller. You can safely use any passenger's last name from the PNR when generating the link.

Credentials

Each partner brand is issued an API key and API secret during onboarding. These are used to obtain bearer tokens. Encryption keys, passwords, and salts are managed entirely by DepartCart and are never shared with partners.

Credential Description
API key Public identifier for your brand. Sent when requesting a bearer token.
API secret Confidential. Used to authenticate token requests. Never expose it in client-side code.

Step 1 — Request a bearer token

Endpoint: POST /generate-bearer-token

Request Body:

{
  "api_key": "YOUR_API_KEY",
  "api_secret": "YOUR_API_SECRET",
  "duration_hours": 24
}

duration_hours is optional and defaults to 24.

Response:

{
  "success": true,
  "bearer_token": "your_brand:1718790000:1718876400:Ab12Cd...:9f8e7d...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "expires_at": 1718876400,
  "brand": "your_brand"
}

Cache and reuse the token until it is close to expiry rather than requesting a new one on every call. A 401 response means the token is missing, invalid, or expired.

Endpoint: POST /api/generate-encrypted-seatmap-url

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

Field Type Required Description
pnr string Yes Booking reference / PNR (e.g. ABC123).
last_name string Yes Any passenger's last name from the booking (e.g. SMITH).
source string No Integration source identifier (e.g. api, app). Defaults to cart.
{
  "pnr": "ABC123",
  "last_name": "SMITH",
  "source": "api"
}

Response:

{
  "success": true,
  "encrypted_id": "Z0FBQUFBQm9VQTE2...",
  "seatmap_url": "/seatmap?id=Z0FBQUFBQm9VQTE2...&source=api",
  "source": "api"
}

seatmap_url is a path on the DepartCart domain. Prepend https://departcart.com to build the full customer-facing deeplink.

Generate the seatmap, cart, and checkout deeplinks for a booking in a single call. As with the seatmap endpoint, encryption is performed server-side and the brand is taken from your bearer token — the difference is that this endpoint returns all three deeplinks as absolute URLs.

Endpoint: POST /generate-encrypted-url

Headers:

Authorization: Bearer <token>
Content-Type: application/json

Request Body:

Field Type Required Description
pnr string Yes Booking reference / PNR.
last_name string Yes Any passenger's last name from the booking.
source string No Integration source identifier. Defaults to cart.
{
  "pnr": "ABC123",
  "last_name": "SMITH",
  "source": "cart"
}

Response:

{
  "success": true,
  "encrypted_id": "Z0FBQUFBQm9VQTE2...",
  "seatmap_url": "https://departcart.com/seatmap?id=Z0FBQUFBQm9VQTE2...&source=cart",
  "cart_url": "https://departcart.com/cart?id=Z0FBQUFBQm9VQTE2...",
  "checkout_url": "https://departcart.com/checkout?id=Z0FBQUFBQm9VQTE2...",
  "source": "cart"
}

Use seatmap_url to drop the customer directly into seat selection, cart_url for the full ancillary cart, or checkout_url to jump straight to payment. These are absolute URLs and can be used as-is.


Implementation Examples

Python

import requests

BASE_URL = "https://departcart.com"

# 1) Exchange API credentials for a bearer token
auth = requests.post(f"{BASE_URL}/generate-bearer-token", json={
    "api_key": "YOUR_API_KEY",
    "api_secret": "YOUR_API_SECRET",
}).json()
token = auth["bearer_token"]

# 2) Generate the seatmap deeplink for a booking
resp = requests.post(
    f"{BASE_URL}/api/generate-encrypted-seatmap-url",
    headers={"Authorization": f"Bearer {token}"},
    json={"pnr": "ABC123", "last_name": "SMITH", "source": "api"},
).json()

seatmap_deeplink = f"{BASE_URL}{resp['seatmap_url']}"
print(seatmap_deeplink)

C

using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;

const string baseUrl = "https://departcart.com";
var client = new HttpClient();

// 1) Exchange API credentials for a bearer token
var authResp = await client.PostAsJsonAsync($"{baseUrl}/generate-bearer-token", new
{
    api_key = "YOUR_API_KEY",
    api_secret = "YOUR_API_SECRET",
});
var auth = await authResp.Content.ReadFromJsonAsync<Dictionary<string, object>>();
string token = auth["bearer_token"].ToString();

// 2) Generate the seatmap deeplink for a booking
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var resp = await client.PostAsJsonAsync($"{baseUrl}/api/generate-encrypted-seatmap-url", new
{
    pnr = "ABC123",
    last_name = "SMITH",
    source = "api",
});
var result = await resp.Content.ReadFromJsonAsync<Dictionary<string, object>>();
string seatmapDeeplink = $"{baseUrl}{result["seatmap_url"]}";

JavaScript / Node.js

const BASE_URL = 'https://departcart.com';

// 1) Exchange API credentials for a bearer token
const auth = await fetch(`${BASE_URL}/generate-bearer-token`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        api_key: 'YOUR_API_KEY',
        api_secret: 'YOUR_API_SECRET',
    }),
}).then(r => r.json());

// 2) Generate the seatmap deeplink for a booking
const result = await fetch(`${BASE_URL}/api/generate-encrypted-seatmap-url`, {
    method: 'POST',
    headers: {
        'Authorization': `Bearer ${auth.bearer_token}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ pnr: 'ABC123', last_name: 'SMITH', source: 'api' }),
}).then(r => r.json());

const seatmapDeeplink = `${BASE_URL}${result.seatmap_url}`;
console.log(seatmapDeeplink);

Keep your API secret server-side. Bearer tokens should be requested from your backend. Never embed your API secret in browser or mobile client code.

Testing

  1. Request a bearer token with your sandbox credentials.
  2. Call /api/generate-encrypted-seatmap-url with a sample pnr and last_name.
  3. Open https://departcart.com{seatmap_url} and confirm the seatmap loads correctly.

Security Benefits

  1. Data Protection: PNR and passenger names are encrypted in transit and within the URL.
  2. No shared secrets: Partners never hold encryption keys; only DepartCart can encrypt or decrypt.
  3. Brand Isolation: Each brand's data is encrypted with its own server-side key.
  4. Short-lived access: Bearer tokens expire, limiting the impact of a leaked token.

Support

For implementation assistance or to receive your brand's API credentials, contact: - Technical Support: support@departcart.com - Integration Team: integration@departcart.com

FAQ

Q: Do I need to implement encryption myself? A: No. Encryption is performed entirely server-side. You send the raw pnr and last_name; DepartCart returns the encrypted deeplink.

Q: How long are bearer tokens valid? A: By default 24 hours, configurable via duration_hours when requesting a token. Request a new token when the current one expires.

Q: How long are the generated seatmap URLs valid? A: The encrypted id does not expire, but it is tied to the booking and brand it was generated for.

Q: Which last name should I send? A: Any passenger's last name from the booking — DepartCart validates against all passengers on the PNR.

Q: What if a customer opens an invalid link? A: They will see an "Invalid or expired link" error message.