Returns the fulfillment orders belonging to the authenticated end-user
(resolved from the JWT), newest first by last_mutation_date. Each
item includes its issued tickets inline so a single paginated call is
enough to render "all my tickets".
Orders without tickets yet (PENDING / CONFIRMED before barcodes
are assigned) are returned with an empty tickets array.
Deliverable PDF URLs are not included in list responses — call
the per-order tickets endpoint for a presigned download URL.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Part of ticketing — Tickets and fulfillment explains the order lifecycle and how tickets are issued.
Why this endpoint exists
This is "my tickets". One paginated call returns the customer's orders with their issued tickets embedded, so a wallet screen renders without an N+1 fan-out over orders.
Orders come back newest first by last_mutation_date — the timestamp of the most recent state change, not the purchase date. An older order that just completed fulfillment therefore sorts above a newer one still pending, which is usually what a customer wants to see at the top.
Request
curl "https://api.acc.funtrips.io/v2/me/fulfillment/orders?limit=20&status=COMPLETED" \
-H "x-campaign-id: $CAMPAIGN_ID" \
-H "Authorization: Bearer $END_USER_TOKEN"| Parameter | Type | Notes |
|---|---|---|
limit | integer | 1–100, default 20 |
next_token | string | Cursor from meta.pagination.next_token |
status | enum | Filter to one lifecycle state |
The customer is resolved from the JWT. There is no user parameter — you cannot read another customer's orders through this route, by construction.
Response
{
"data": {
"items": [
{
"fulfillment_order_id": "7c1b3f9a-2d4e-4a6f-9b1a-3c5e7d2f8a0b",
"order_id": "5e2a7c91-3b6d-4f82-a17c-9d4e6b1f3a25",
"campaign_id": "3c1e5a90-7b2d-4f61-9a83-1d4e7f2b8c05",
"external_user_id": "customer-4815162342",
"status": "COMPLETED",
"last_mutation_date": "2026-09-02T11:04:18Z",
"customer_email": "[email protected]",
"total_price": { "value": "52.97", "currency": "EUR" },
"flexible_date": false,
"flexible_ticket_costs": { "value": "0.00", "currency": "EUR" },
"discount_total": { "value": "11.00", "currency": "EUR" },
"tickets": [
{
"fulfillment_line_id": "af31c8d2-59e4-4b17-8c6a-2d0f7e3b9145",
"product_id": "d4b8f2a1-6c3e-4957-b18d-2f5a9c7e3b04",
"product_title": "Dagticket volwassene",
"merchant_id": "8a2f4c61-9d3e-4b57-a0c8-1e5f7b2d9a30",
"merchant_title": "Amsterdam Zoo",
"effective_price": { "value": "18.50", "currency": "EUR" },
"product_age_group": "adult",
"barcode": "3041234567890",
"symbology": "EAN_13",
"validity": { "…": "validity window" },
"merchant_logo": { "…": "Image with DPR variants" },
"ticket_image": { "…": "Image with DPR variants" }
}
]
}
]
},
"meta": {
"correlation_id": "…",
"pagination": { "limit": 20, "next_token": "eyJwayI6…" }
}
}Note the payload nests one level deeper than most collections: data.items, not data.
Order status
| Status | Meaning |
|---|---|
CREATED | Registered, not started |
PENDING | Fulfillment running |
CONFIRMED | Reserved with the provider, barcodes not assigned yet |
COMPLETED | Tickets issued. The only state where tickets are guaranteed present |
FAILED | Fulfillment failed |
CANCELLED | Cancelled before completion |
REFUNDED | Tickets voided and money returned |
REORDERED | Superseded by a date change — tickets voided, money kept, and a newer COMPLETED order exists for the same order_id |
REORDERED is the one that surprises people. After a date change the original order stays in the list in this state, and a second order carries the live tickets. Filter it out of a "my tickets" view, or the customer sees a voided barcode next to their real one.
Empty tickets is normal
tickets is normalAn order in PENDING or CONFIRMED returns "tickets": []. Fulfillment is still running; barcodes do not exist yet.
Render it as "your tickets are being prepared" rather than as an empty order. Poll GET /me/fulfillment/orders/{fulfillment_order_id}/tickets for that order — it returns a 409 with a Retry-After header while the tickets are still being issued, which is a clearer polling signal than an empty array.
No PDF URLs here
deliverable is omitted from list responses, deliberately: pre-signing a download URL for every order on every page is wasteful, and those URLs are short-lived, so most would expire unused.
For the ticket PDF, call the per-order tickets endpoint.
Errors
| Status | Meaning |
|---|---|
400 | Invalid status value, or a malformed limit |
401 | Token missing, expired or invalid |
500 | Unexpected fault. Retryable |
Fulfillment errors carry no type field — branch on status. See Error handling.
A customer with no orders gets 200 with items: [].
Notes
- Guests have no order history. This route resolves the customer from the JWT, so a guest purchase never appears here. Guests get their tickets by e-mail; if you want an order page for them, keep the
order_idfrom Confirm and use get order by order id. - Two different ids.
order_idcomes from checkout confirmation;fulfillment_order_idis the platform's fulfillment record. They address different endpoints — see Get order tickets. customer_emailis PII. Do not log it. Useorder_idand the correlation id in your own records.
