Sales authorizations

RMS Sales Authorizations for Control Classes

Sales Authorizations allow an external Revenue Management System (RMS) to control how many tickets can be sold for each Control Class on every leg of a trip.


Core Concepts

Concept Description
Manifest Represents a single trip instance — a specific schedule on a specific date. Contains legs, tickets, load data, and salesAuthorizations.
Control Class A named bucket (e.g. "RBD1", "Economy") used by the RMS to categorize and limit ticket sales.
Sales Authorization A record on a manifest leg that specifies how many tickets the RMS authorizes for a given Control Class between a specific origin and destination station.
Leg A segment of a trip between two consecutive stations.
Segment A pair of origin and destination stations (which can span one or more legs). Authorizations and availability are calculated at the segment level.

1. Accepting Sales Authorizations from an RMS

Endpoint Overview

Currently the only endpoint that accepts external Sales Authorizations is tailored to the data schema of the Appia RMS.

Property Value
Method POST
Path /rms/appia/authorizations
Summary Creates or updates Appia InventoryControl authorizations for Control Classes applied to Manifest legs

Authentication

The endpoint is secured with a token-based authentication. The request must include:

  • A valid X-API-KEY header.
  • A valid Authorization header (JWT token).

Please review how to authenticate.

Request Body Schema

The request body must follow the ManifestAuthorizationPostData schema. At the top level, the body contains an array of inventoryControls, each representing the authorizations for a single departure (schedule-date combination).

Please review the full endpoint documentation.

Example request body:

{
  "inventoryControls": [
    {
      "departure": {
        "number": "1d62a5f9-46f2-44b2-9e9c-2aa07714b10d",
        "departureDate": "2025-12-02",
        "operatorCode": "5f243d100617680712e78dd7"
      },
      "legControls": [
        {
          "originStationCode": "60a1b2c3d4e5f6a7b8c9d0e1",
          "destinationStationCode": "60a1b2c3d4e5f6a7b8c9d0e2",
          "controlClasses": [
            {"code": "RBD1", "authorization": 50},
            {"code": "RBD2", "authorization": 30}
          ]
        }
      ],
      "timestamp": "2025-11-30T16:45:49.178Z"
    }
  ]
}

Important: The salesAuthorizations array on the manifest is fully replaced by each POST call. This is not a partial update — the RMS is expected to send the complete set of authorizations every time.

Example success response:

{
  "results": [
    {
      "scheduleId": "1d62a5f9-46f2-44b2-9e9c-2aa07714b10d",
      "date": "2025-12-02",
      "salesAuthorizations": [
        {
          "originStationId": "60a1b2c3d4e5f6a7b8c9d0e1",
          "destinationStationId": "60a1b2c3d4e5f6a7b8c9d0e2",
          "controlClassCode": "RBD1",
          "controlClassId": "6501a2b3c4d5e6f7a8b9c0d1",
          "authorization": 50,
          "externalTimestamp": "2025-11-30T16:45:49.178Z",
          "updatedAt": {"value": 20251130}
        }
      ],
      "success": true,
      "error": ""
    }
  ]
}

Webhook Event

After all inventoryControls are processed, the handler emits a webhook event: controlclasses.authorizations.updated


2. Reading Existing Sales Authorizations

Endpoint Overview

Property Value
Method GET
Path /manifests/{manifestKey}/sales-authorizations
Summary Returns the Sales Authorizations for RMS Control Classes for a single Manifest

Authentication

Same as the POST endpoint — token-based authentication, requiring valid X-API-KEY and Authorization headers.

Manifest Key Formats

The manifestKey path parameter supports two formats for identifying the target manifest:

Option 1: Manifest ID (ObjectId)

A direct 24-character hexadecimal string that matches the manifest's _id field.

Example: 5f243d100617680712e78dd7

  • Must be exactly 24 hex characters.
  • If the string is 24 characters but not a valid ObjectId, a 400 INVALID_MANIFEST_ID error is returned.

Option 2: Composite Key (Schedule ID + Date)

A combination of the schedule's UUID and the date, separated by a + character.

Format: {ScheduleId}+{Date}

Example: 5cab127c-2c70-4fea-9031-4131e2751cdb+2024-07-25

  • ScheduleId must be a valid UUID v4.
  • Date must follow the yyyy-mm-dd format with valid month/day ranges.
  • If the UUID is invalid, a 400 INVALID_SCHEDULE_ID error is returned.
  • If the date is invalid, a 400 INVALID_MANIFEST_DATE error is returned.

If the key does not match either expected format, a 400 MANIFEST_KEY_UNKNOWN_FORMAT error is returned.

Response Schema

GetSalesAuthorizationsResponse

Field Type Description
_id string The manifest ID (ObjectId)
accountId string The account ID owning this manifest
scheduleId string The schedule ID
date string The manifest date in yyyy-mm-dd format
salesAuthorizations array The authorization records, enriched with availability and bookings

Each item in salesAuthorizations includes all the stored fields from the POST operation plus two computed fields:

Computed Field Type Description
availability integer The number of tickets still available to sell for this Control Class on this segment
bookings integer The current number of unique tickets booked on this segment for this Control Class

Please review the full endpoint documentation.

Example response:

{
  "_id": "5f243d100617680712e78dd7",
  "accountId": "5f243d100617680712e78dd8",
  "scheduleId": "1d62a5f9-46f2-44b2-9e9c-2aa07714b10d",
  "date": "2025-12-02",
  "salesAuthorizations": [
    {
      "originStationId": "60a1b2c3d4e5f6a7b8c9d0e1",
      "destinationStationId": "60a1b2c3d4e5f6a7b8c9d0e2",
      "controlClassCode": "RBD1",
      "controlClassId": "6501a2b3c4d5e6f7a8b9c0d1",
      "authorization": 50,
      "externalTimestamp": "2025-11-30T16:45:49.178Z",
      "updatedAt": {"value": 20251130},
      "availability": 35,
      "bookings": 12
    }
  ]
}


Availability Calculation Details

The formula is:

availability = min(segmentCapacity, authorizedSales − segmentBookings)

Where:

authorizedSales = the authorization value from the matching salesAuthorization entry (found by controlClassId, originStationId, and destinationStationId). Default: 0 if not found.

segmentCapacity = manifest.capacity − maxLoad, where maxLoad is the highest load value across all legs between the origin and destination stations.

segmentBookings = the count of unique ticket IDs across all legs between the origin and destination stations.

Step-by-step example

Given a manifest with:

  • capacity: 50
  • A segment from Station A → Station C (spanning two legs: A→B and B→C)
  • Leg A→B: load = 20, tickets: {t1: ..., t2: ..., t3: ...}
  • Leg B→C: load = 15, tickets: {t1: ..., t4: ...}
  • A sales authorization for Control Class "RBD1" on A→C with authorization = 40

The calculation would be:

  1. maxLoad = max(20, 15) = 20
  2. segmentCapacity = 50 − 20 = 30
  3. segmentBookings = unique tickets across A→B and B→C = {t1, t2, t3, t4} = 4
  4. authorizedSales = 40
  5. availability = min(30, 40 − 4) = min(30, 36) = 30