Retailer integration overview

What the Funtrips platform API is, who it is for, and the shape every response takes.

The Funtrips platform API sells experiences — attraction tickets, day trips and deals — on behalf of a retailer. You bring the customers and the storefront; the platform owns the catalog, the pricing, the payment, and the ticket that lands in the customer's inbox.

This documentation is written for a retailer integrating the API directly: you are building your own storefront (web, app, or an embedded frame) against these endpoints, rather than using a hosted Funtrips front-end.

What you integrate

A complete integration touches five things, in roughly this order:

StepWhat you doEndpoints
0. Get credentialsObtain an S2S token; understand which routes need which credentialAuthentication
1. Identify the customerHand your logged-in customer to the platform without asking them to log in againSession exchange
2. Show the catalogList merchants and products, show prices and availabilityThe product catalog
3. SellPlace a reservation, collect customer details, redirect to paymentCheckout
4. DeliverShow the customer their tickets and PDFs after paymentTickets and fulfillment
5. RewardApply loyalty balances, vouchers and memberships to the priceLoyalty wallet, Vouchers

Optionally, feed storefront behaviour back into the platform so it can be correlated with orders and catalog data: analytics ingestion.

You do not have to integrate all five. A retailer that only wants a catalog and a checkout can stop after step 3 — guest checkout works without any identity integration at all.

Base URL

https://api.acc.funtrips.io/v2

The v2 path segment is the deployment stage. Every path in this documentation is relative to that base — GET /merchants means GET https://api.acc.funtrips.io/v2/merchants.

📘

Environments

The URL above is acceptance. Ask your Funtrips contact for the production host and for the credentials belonging to each environment — acceptance credentials never work against production, and acceptance carries test catalog data with test payment providers.

The response envelope

Every successful response is wrapped in the same envelope. The payload you asked for is always under data; everything about the request itself is under meta.

{
  "data": { "…": "the resource, or an array of them" },
  "meta": {
    "correlation_id": "0f4c8e1a-9b2d-4c7e-8a1f-2d3b4c5e6f70",
    "item_count": 12,
    "pagination": { "limit": 20, "next_token": "eyJwayI6…" }
  }
}
FieldWhen presentMeaning
dataAlways on 2xxThe resource. An object for single reads, an array for collections.
meta.correlation_idAlwaysEchoes your X-Correlation-Id, or a generated one. Log this. It is the only key that ties your request to our traces.
meta.item_countCollection responsesNumber of items in data for this page.
meta.paginationPaginated responsesPage size and the cursor for the next page. See Pagination.

Write your client to read data and ignore unknown fields. New fields are added to data objects without a version bump; fields are never removed or retyped without one.

Errors

Errors are never wrapped in the envelope. They are RFC 7807 problem documents served as application/problem+json:

{
  "type": "urn:qup:error:checkout-reservation-expired",
  "title": "reservation has expired",
  "status": 404,
  "detail": "the reservation has expired, please place a new one",
  "instance": "urn:qup:correlation:0f4c8e1a-9b2d-4c7e-8a1f-2d3b4c5e6f70"
}

Branch on type where it is present, and on status otherwise. Never branch on title — it is human-readable prose and may be reworded. Error handling explains which endpoints carry a type and which do not.

Conventions that hold everywhere

  • Money is a string. {"value": "12.50", "currency": "EUR"}. Never parse it into a float — parse it into your language's decimal type. Prices are computed in exact decimal server-side, and a float round-trip is how cent discrepancies get into baskets.
  • Campaign scope is a header. Almost every request needs x-campaign-id. See Campaign context.
  • Language is a header. Accept-Language, negotiated RFC 7231-style. Never a body field or query param.
  • Times are ISO 8601. Dates that mean a calendar day are YYYY-MM-DD. Timestamps are RFC 3339 with a zone.
  • IDs are UUIDs, except external_user_id (yours, opaque to us) and voucher codes.

What is not in these docs

The API also exposes /admin/* routes for back-office operators and /internal/* routes for platform services signed with AWS SigV4. Neither is part of a retailer integration, and neither is documented here. If you believe you need one, talk to us first — the capability you want usually exists on a retailer-facing route.


Did this page help you?