Skip to main content

Operations & Finance API

The back-office surface: trip oversight and Tour Director substitution, availability overrides, the on-request queue, voucher management, refunds, settlement runs with the administration fee, batch export to your finance system with hold/release control, reporting, and the audit trail.

All endpoints are under /api/optionals/v1 and require an admin bearer token (see Authentication). All amounts are integer minor units. Every report endpoint also serves CSV via ?format=csv.

Authentication

Operations & Finance users authenticate through Keycloak using the OAuth 2.0 Authorization Code flow with PKCE and MFA, federated to your corporate identity provider (for example Microsoft Entra ID) so they sign in with their existing SSO accounts. The Experiences API never accepts user passwords directly — it validates Keycloak-issued access tokens, as described in Authentication.

On sandbox tenants (provider: mock) only, the evaluation login is POST /auth/admin with { "tenantId": "meridian", "email": "operations@meridian.example.com", "password": "<password>" }, returning { token, admin }.

Trips and oversight

All trips

GET /admin/trips?tenantId=meridian

Every trip across all brands, each with its tourDirector and brandName, plus the full Tour Director roster (for substitution pickers).

Trip detail

GET /admin/trips/{tripId}?tenantId=meridian

The complete picture for one departure: trip, Tour Director, full catalog with availability (including unavailable items), guests, orders, and transactions.

Substitute the Tour Director

PATCH /admin/trips/{tripId}/td
{ "tenantId": "meridian", "tdId": "td_12" }

Reassigns the trip to a new Tour Director. Sales already processed under the outgoing Tour Director stay attributed to them for settlement — the response makes that explicit:

{
"trip": { "...": "..." },
"previousTdId": "td_07",
"salesUnderPreviousTd": { "transactionCount": 34, "settledToPreviousTd": true }
}

The incoming Tour Director owns all future sales. The substitution is audited with the transaction count and value under the outgoing Tour Director.

Availability override

PATCH /admin/trips/{tripId}/products/{productId}/availability

Identical body and behavior to the Tour Director availability endpoint — status, capacity override, sold-out policy (block | on_request), note — available centrally for any trip.

Operations queue

On-request items

GET /admin/on-request?tenantId=meridian&status=pending

Items sold beyond the allotment under an on_request policy, with trip, guest, supplier, and value context. Filters: tripId, supplier, status (pending | confirmed).

Confirm with the supplier

POST /admin/orders/{orderId}/items/{itemId}/confirm-request

Marks an on-request item confirmed once the supplier has agreed the extra place. The guest's and Tour Director's views update from "Supplier place pending" to "Supplier confirmed". Audited as on_request.confirmed.

Supplier overview

GET /admin/suppliers?tenantId=meridian

Cross-tour allotment utilisation, pending and confirmed on-request demand, and revenue per supplier — the negotiation view for allotment reviews.

Departures needing attention

GET /admin/attention?tenantId=meridian&windowDays=14

Departures leaving within the window that need action: pending on-request items, suppliers awaiting confirmation, guest forms outstanding, reservation lists due before cut-off.

Vouchers

GET /admin/vouchers?tenantId=meridian&status=active&type=partner
POST /admin/vouchers
PATCH /admin/vouchers/{voucherId}/expiry
POST /admin/vouchers/{voucherId}/void

Batch creation supports partner vouchers (with a partnerName and codes) and goodwill vouchers, up to 500 per call:

{
"tenantId": "meridian",
"type": "partner",
"partnerName": "Atlas Rewards",
"amount": 5000,
"currency": "GBP",
"expiryDate": "2027-03-31",
"withCode": true,
"quantity": 200,
"notes": "Season partner allocation"
}

Vouchers move through activeredeemed | expired | void. Expiry can be extended per voucher (PATCH .../expiry with a new expiryDate); voiding is immediate and audited. Vouchers can be linked to a booking reference so only that party can redeem them.

Refunds

POST /admin/refunds

Same body as the Tour Director refund (transactionId, optional amount, required reason) — without the own-trip restriction, for refunds handled centrally after the tour.

Settlements

The settlement lifecycle is deliberately truthful about what the platform observes: draftexported (payment hold requested) → released for payment. Payment runs remain in your finance system.

List settlements

GET /admin/settlements?tenantId=meridian&status=draft&tdId=td_07

All settlements with the Tour Director's name resolved, filterable by status and Tour Director.

Run a settlement

POST /admin/settlements/run
{ "tenantId": "meridian", "periodStart": "2026-08-03", "periodEnd": "2026-08-09" }

Groups every unsettled completed transaction in the period per Tour Director per currency, applies the configured administration fee, and creates draft settlements. Returns 201 with the created settlements:

{
"settlements": [
{
"id": "set_881",
"reference": "SET-2026W32-TD4471-GBP",
"tdId": "td_07",
"currency": "GBP",
"periodStart": "2026-08-03",
"periodEnd": "2026-08-09",
"lines": [
{ "category": "card_sales", "label": "Card sales", "amount": 301000, "transactionCount": 41 },
{ "category": "cash_sales", "label": "Cash collected", "amount": 96000, "transactionCount": 18 },
{ "category": "refunds", "label": "Refunds", "amount": -8500, "transactionCount": 2 },
{ "category": "admin_fee", "label": "Administration fee (3%)", "amount": -11655, "transactionCount": 0 }
],
"grossAmount": 388500,
"adminFeeAmount": 11655,
"adminFeePercent": 3,
"netPayable": 376845,
"status": "draft",
"transactionIds": ["..."]
}
]
}

Settlement detail

GET /admin/settlements/{settlementId}?tenantId=meridian

The settlement with the Tour Director's name and every included transaction — the transaction-level detail retained for audit and reconciliation.

Export to the finance system

POST /admin/settlements/export
POST /admin/settlements/export?format=csv # direct CSV download
{ "tenantId": "meridian", "settlementIds": ["set_881", "set_882"] }

Produces the accounts-payable batch: one invoice per Tour Director per period, gross settled as item lines, the administration fee as a credit line, net payable per Tour Director — and every invoice flagged to load on hold in your finance system. Returns { batchRef, csv, settlements } (or the CSV itself with format=csv), and moves the settlements to exported.

Release for payment

POST /admin/settlements/{settlementId}/release

The explicit finance action that releases an on-hold invoice for payment. Separate from export by design — export requests the hold, release lifts it. Both actions are audited with the acting user. Your finance system remains the system of record for payment runs and disbursement.

Reports

Six report endpoints, all supporting ?format=csv for spreadsheet export and from/to date filters where noted:

EndpointParametersWhat it answers
GET /admin/reports/salesgroupBy = trip | td | brand | method, from, toSales summary grouped by departure, Tour Director, brand, or payment method
GET /admin/reports/productsfrom, toSales per optional experience — the product performance view
GET /admin/reports/gratuitiesfrom, toGratuity totals per recipient type and currency
GET /admin/reports/vouchersstatus, tripId, tdIdVoucher issuance and redemption
GET /admin/reports/transactionstripId, tdId, type, method, from, toTransaction-level detail with full filtering
GET /admin/reports/reconciliationfrom, toPer-currency reconciliation: gateway takings vs cash vs vouchers vs settled vs exported net — the numbers finance checks against the gateway and AP

Audit trail

GET /admin/audit?tenantId=meridian&entityType=order&tripId=trip_301&from=2026-08-01&to=2026-08-18&limit=200

The full audit log — every login, order, payment, refund, availability change, voucher action, and settlement action, each with actor type, actor id and name, action, entity, optional structured data, and timestamp. Filters: entityType, entityId, tripId, actorId, from, to, limit.

{
"events": [
{
"id": "evt_10021",
"actorType": "admin",
"actorId": "adm_02",
"actorName": "Priya Nair",
"action": "settlement.released",
"entityType": "settlement",
"entityId": "set_881",
"createdAt": "2026-08-14T09:12:44.000Z"
}
]
}