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:
| Step | What you do | Endpoints |
|---|---|---|
| 0. Get credentials | Obtain an S2S token; understand which routes need which credential | Authentication |
| 1. Identify the customer | Hand your logged-in customer to the platform without asking them to log in again | Session exchange |
| 2. Show the catalog | List merchants and products, show prices and availability | The product catalog |
| 3. Sell | Place a reservation, collect customer details, redirect to payment | Checkout |
| 4. Deliver | Show the customer their tickets and PDFs after payment | Tickets and fulfillment |
| 5. Reward | Apply loyalty balances, vouchers and memberships to the price | Loyalty 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.
EnvironmentsThe 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…" }
}
}| Field | When present | Meaning |
|---|---|---|
data | Always on 2xx | The resource. An object for single reads, an array for collections. |
meta.correlation_id | Always | Echoes your X-Correlation-Id, or a generated one. Log this. It is the only key that ties your request to our traces. |
meta.item_count | Collection responses | Number of items in data for this page. |
meta.pagination | Paginated responses | Page 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.
Updated about 2 hours ago
