Cost Centers
A cost center is a named billing configuration on your sales agent. It determines the commercial terms applied to a booking and how it is paid for. Cost centers are assigned per passenger, so a single order can combine several cost centers if this is enabled for your sales agent. Every agent has at least one: the default cost center, which is used for any passenger you don't assign a cost center to explicitly.
Cost centers let you keep different commercial setups side by side under a single agent. For example, you might have one cost center for your public website and another for a corporate client with negotiated rates, each with its own payment method.
What a cost center controls
Cost centers are set up and configured by All Aboard on request. Contact team@allaboard.eu to create or change one. A cost center captures:
- Commercial rates: the pricing applied to bookings made against the cost center.
- Per-provider preferences: provider-specific settings such as commercial contracts, corporate rates, commissions, and price markup. These let you apply different terms per train operator within the same cost center.
- Service fees: optional fees you add on top of the ticket price, charged to the customer and forwarded to you in full. See Service Fees below.
- Payment methods: the method(s) orders booked against this cost center can be paid with, namely wallet, payment gateway (Stripe), or invoice. See Payment Methods and API Scopes below.
These settings are configured on request, not through the API. Over the API, cost centers are read-only: you can list them and select which one a passenger is billed against.
Accessing cost centers
Cost centers are a property of the SalesAgent type and can be read with the getSalesAgent query. Each CostCenter exposes its id, name, whether it is the default, and its configured paymentMethod.
query GetCostCenters {
getSalesAgent {
uid
costCenters {
id
name
default
paymentMethod
}
}
}Use the returned id when you want to bill an order against a specific cost center.
Selecting a cost center for an order
If no cost center is requested, the order is billed against the agent's default cost center. To bill against a specific cost center, supply the passengers argument to createBooking and set the cost center id on the passenger(s):
mutation CreateBooking {
createBooking(
offerIds: ["offer_e740y733k0r771r2n5a4p2s0z7"]
passengers: [
{ type: ADULT, costCenter: { id: "costcenter_a4q363m054t3d6b1v7h6s1v405" } }
{ type: YOUTH, age: 22, costCenter: { id: "costcenter_a4q363m054t3d6b1v7h6s1v405" } }
]
) {
id
}
}The cost center is set per passenger. If combining cost centers is enabled for your sales agent (contact team@allaboard.eu), a ticket booking can split passengers across cost centers; rail pass bookings always use a single cost center. Any passenger you leave without a cost center is billed against the agent's default, but once any passenger has a non-default cost center, every passenger needs one. Cost centers combined in one booking must share a payment method, since an order is paid with a single method, and each needs its own contact person.
A booking that breaks these rules fails with MULTI_COST_CENTER_NOT_SUPPORTED, MIXED_COST_CENTER_SPECIFICATION or MIXED_PAYMENT_METHOD. An unknown cost center id fails with INVALID_ARGUMENT or COST_CENTER_NOT_AVAILABLE; see When a Cost Center Is Refused.
Booking for another sales agent
A sales agent can be given access to other sales agents: a travel agency, for example, to the companies it books for. Access is set up by All Aboard on request. With it, you book on the other agent's cost centers, and the booking and the order belong to the agent whose cost center they are on.
Finding the agents you can book for
accessibleSalesAgents lists the sales agents you have access to, never your own. Read their cost centers there: getSalesAgent returns only your own agent. filter.query finds agents by part of a name or a uid, ignoring case, best matches first. A sales agent whose orders are switched off is left out of the list.
name is the sales agent's display name, such as the company or agency name. It is null until a name has been recorded, so show the uid in its place.
Example: Find a company's cost centers
query AccessibleSalesAgents {
accessibleSalesAgents(filter: { query: "acme" }, first: 25) {
totalCount
edges {
node {
uid
name
costCenters {
id
name
default
paymentMethod
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}The list is a connection. totalCount counts the sales agents the filter leaves, and pages hold 25 sales agents by default and 100 at most. Continue with after set to pageInfo.endCursor. Cursors are opaque and only continue the list they came from, so present one with the same filter.
Booking on their cost centers
Set one of the agent's cost centers on every passenger, as in Selecting a Cost Center for an Order, and the booking is made on that agent. Set it when you price the journey as well: journeyOffer and combinedJourneyOffer price the passengers with their cost center, so the offers show what the booking will charge.
Example: Price a journey on another agent's cost center
subscription JourneyOffer {
journeyOffer(
journeyId: "b0840b3b-505e-4428-ad02-4ef56528cc10"
passengers: [
{ type: ADULT, costCenter: { id: "costcenter_a4q363m054t3d6b1v7h6s1v405" } }
]
) {
status
itinerary {
... on SegmentCollection {
offers {
id
price {
amount
currency
}
}
}
}
}
}All passengers of one booking carry cost centers of one sales agent. To book people from two companies, make one booking for each.
The order is paid with a payment method of that agent's cost center, and your API key still needs the matching payment scope; see Payment Methods and API Scopes.
Who an order belongs to
An order's salesAgent is the agent whose cost center it is on, and the one it is billed to. createdBy.salesAgent is the agent that placed it, which is you, and createdBy.user is the signed-in user who did, when there was one.
query GetOrder {
node(id: "order_e451s5s5e1m75064n3x147v306") {
... on Order {
reference
salesAgent {
uid
name
}
createdBy {
salesAgent {
uid
name
}
}
}
}
}When a cost center is refused
createBooking checks the cost centers on the passengers. The first cost center named decides the sales agent:
- If it doesn't exist, the request is refused with
INVALID_ARGUMENT. - If it belongs to a sales agent you have no access to, the request is refused with
UNAUTHORIZED. - If that sales agent's orders are switched off, the request is refused with
FORBIDDEN. - If another passenger's cost center isn't one of that agent's, because it belongs to another sales agent or doesn't exist, the request is refused with
COST_CENTER_NOT_AVAILABLE.
Pricing makes the same checks but doesn't report these codes. A journey priced on a refused cost center comes back with its legs in the status UNKNOWN and without offers, and the code only comes from createBooking.
Payment methods and API scopes
Every cost center supports one or more payment methods: wallet, payment gateway (Stripe), or invoice. When you book against a cost center, the API key must carry the matching payments:* scope for the payment method used; otherwise the request is rejected:
| Cost center payment method | Required scope |
|---|---|
| Wallet | live:payments:wallet / test:payments:wallet |
| Payment gateway (Stripe) | live:payments:stripe / test:payments:stripe |
| Invoice | live:payments:invoice / test:payments:invoice |
This means the payment method of the cost center in use must match the scopes granted to the API key making the request. See API Scopes for the full list of scopes and how to choose them.
Service fees
Clients using the embeds can configure service fees on a cost center. Service fees are added on top of the ticket price, charged to the customer through the payment gateway at checkout, and forwarded in full to you.
Service fees can be combined, and each fee can be one of:
- Fixed price per order: a flat amount added once per order.
- Fixed price per ticket issued: a flat amount per issued ticket.
- Percentage of order value: a percentage of the order total.
Because service fees are collected through the payment gateway, they apply to cost centers using the Stripe payment method. They are paid out to you monthly. See Fees and Reconciliation for how service fees appear in your monthly reconciliation.
Configuring embeds safely
Whatever you pass an embed is visible to anyone who views the page. Which credential to pass depends on what the embed does.
Booking embeds
The Journey List, Offer Selection, Rail Pass List and Rail Pass Modal embeds let customers search and pay for a new booking. Restrict their key to the payment gateway only:
- Use an API key with only the base scope and
*:payments:stripe(for exampleliveandlive:payments:stripe). The base scope is required for any request. - Do not grant
orders:read,passenger_profiles:read,payments:wallet, orpayments:invoiceto a public embed key.
With only those two scopes, the key cannot read your orders and cannot create orders with any payment method other than Stripe, so customers can pay for their own bookings while the key cannot be abused to access your orders or spend your wallet or invoice credit. Make sure the cost center the embed uses is configured with the payment gateway payment method so it matches this scope.
Order management embeds
The Refund Manager embed works on an order that already exists, so it has to be able to read and refund that order. A key with only those scopes cannot do either, and an API key that can would reach every order on your sales agent. Pass an access token instead: a credential you mint on your server for that one order, which expires on its own.
Never put an API key carrying orders:read on a public page.