Annual Tickets

Annual passes - personalization flow after purchase, token-based access, customer create and personalization update.

An annual ticket is a ticket of type annual - redeemable multiple times, often personalized, sometimes bought as a gift and personalized later by the recipient. This page describes the personalization flow after purchase: who can personalize, with which token, and which endpoints are available.

Buying an annual ticket itself goes through a regular order via POST /api/v4/orders with a ticket of type annual - see Tickets and Orders.

Full endpoint and schema reference: Swagger.

Mental model

After purchase, the buyer receives a confirmation mail with a personalization token. That token opens a separate, scoped workflow on the /annual namespace - no API user login required, just the token in the query string.

Order
 └── ticket_sales (n)
      └── personalizations (n)   ← each card / seat individually
           ├── customer ........ who the card belongs to
           ├── address_id ...... shipping address
           └── dispatch_mode_id  dispatch mode

An annual ticket can carry multiple personalizations (e.g. family card). Each personalization references its own customer.

Endpoints at a glance

All endpoints live under the /api/v4/annual namespace and need ?token=<personalization_token>.

EndpointWhat
GET /api/v4/annual/order?token=:tokenFetch the order with ticket sales and personalizations
POST /api/v4/annual/customers?token=:tokenCreate a customer for a personalization (e.g. the recipient)
PUT /api/v4/annual/customers/:id?token=:tokenUpdate customer data
PUT /api/v4/annual/personalizations/:id?token=:tokenBind a personalization to a customer and an address
POST /api/v4/annual/personalizations/:id/upload?token=:tokenUpload a portrait photo for the personalized card
POST /api/v4/annual/personalization/finalize?token=:tokenFinalize the personalization
PUT /api/v4/annual/ticket_sales/:id?token=:tokenMove the start date (start_at) of the card

Common tasks

Fetch the order to personalize

curl "https://demo.gomus.de/api/v4/annual/order?token=PERSONALIZATION_TOKEN"

Response contains:

  • Customer (the buyer)
  • Addresses
  • ticket_sales with a personalizations array
  • Per personalization: current customer, address_id, dispatch_mode_id and a ready flag (boolean, ready to ship)

Create a new person for a personalization

When the annual ticket is given as a gift:

curl -X POST "https://demo.gomus.de/api/v4/annual/customers?token=PERSONALIZATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": {
      "name": "Peter",
      "surname": "Pan",
      "email": "peter@example.com",
      "customer_salutation_id": 1,
      "addr_city": "Berlin",
      "addr_country_id": 60,
      "addr_street": "Brunnenstraße 7D",
      "addr_zip": "10119"
    }
  }'

Response contains the new customer.id, an addresses[] list and - importantly - a personalization_token. You need this in the next step.

Bind a personalization to a customer

curl -X PUT "https://demo.gomus.de/api/v4/annual/personalizations/:id?token=PERSONALIZATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "personalization": {
      "customer_personalization_token": "13fe3a0d-...",
      "customer_adress_id": 151,
      "dispatch_mode_id": 3
    }
  }'

customer_personalization_token comes from the customer create response. customer_adress_id is the shipping address. dispatch_mode_id from Lookups.

Move the start date of the card

curl -X PUT "https://demo.gomus.de/api/v4/annual/ticket_sales/:id?token=PERSONALIZATION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "ticket_sale": { "start_at": "2026-06-01 10:00:00" } }'

Pitfalls

  • Token-based, not user-based. The /annual namespace works without an API user login - the personalization token from the order confirmation mail is the auth. Therefore: never leave the token in URL logs or as a query string in frontend routers; relay it server-side.
  • Two different tokens. There is the order's personalization token (opens the flow) and the customer_personalization_token (identifies a newly created customer subject for the personalization binding). Don't mix them up.
  • The address field is named customer_adress_id (single d) on personalization update. Typo baked into the server schema, lives like that for years.
  • Pull dispatch_mode_id from lookups. Ids are instance-specific - see Lookups.