Use case description of how to use the online offers collection to retrieve, display, and sell digital products and services via the Open API.
This collection supports the full purchase lifecycle:
- Display a catalog of available offers.
- Show per-offer details and generate a transparent purchase preview.
- Execute the purchase and provision the service to the customer's account.
- Retrieve a customer's purchase history by offer or account.
- GET online offers
- GET online offer details
- POST online offer purchase preview
- POST purchase an online offer
- GET online offer purchases by customer id
- GET online offer purchases by customer id and offer id
The online offers collection exposes the product catalog and purchase flow for digital goods to third-party integrations.
Core behavior:
- Offers are only returned if active, within their valid publication period, and configured as available for online purchase.
- Each offer defines validity periods, usage scope, and applicable access restrictions.
- Prices and applicable tax rates are determined per offer and surfaced in the preview step.
- Studio access restrictions may limit offer visibility or purchasability to specific locations.
Recommended use cases:
- Direct purchase flows in member-facing web or app
- Partner-embedded e-commerce (course passes, entry packs, time-based access)
- Pre-purchase price transparency with voucher validation
- Post-purchase history display and entitlement tracking
Use GET online offers to return a list of all purchasable offers visible to the integration.
Use this to:
- render the offer catalog in your UI
- filter or sort offers by type, validity, or price
- determine which offers are currently active and available
Use GET online offer details for any offer the customer selects.
Use this to:
- display per-offer terms (validity period, usage scope, access restrictions)
- inform the customer before any pricing step
Use POST online offer purchase preview to calculate and display the final price before the customer commits.
Use this to:
- show a transparent cost breakdown including taxes
- validate and apply voucher codes before checkout
- surface eligibility issues early without initiating a transaction
Voucher code handling: pass the voucher code in the preview request so the system can validate code status (active, expired, usage limit reached), studio and offer applicability, and customer eligibility. A valid preview response includes basePrice, discountedBasePrice, voucherDiscount (Money objects), and a voucherSuccessMessage. If invalid, the response returns a voucherErrorCode. The same voucher context must be passed in the purchase request. Integrations should handle invalid or ineligible codes with explicit user feedback.
Use POST purchase an online offer once the customer confirms.
Use this to:
- provision the service to the customer's account
- retrieve the
studioAccessCodereturned on success for gym entry
Best practice:
- revalidate voucher context at purchase time to guard against stale or concurrently reused codes
- when a voucher code is applied, always request the payment token using the
discountedBasePricefrom the preview response, not the originalbasePrice— the payment must reflect the final amount the customer is charged - store the returned
studioAccessCodeand look up theonlineOfferPurchaseIdvia the purchase history endpoints for support and reporting
Use GET online offer purchases by customer id for a full account-level purchase list.
Use GET online offer purchases by customer id and offer id to narrow the history to a specific product.
Use this to:
- display active entitlements and past purchases in a customer account view
- resolve support questions about specific purchased offers
Note: The payload examples below are integration-oriented drafts. Validate all field names and structures against the current OpenAPI schema before publishing or implementation.
Scenario: Customer selects a 10-entry pass, applies a voucher, and completes checkout.
- GET online offers
- GET online offer details
- POST online offer purchase preview (with voucher code)
- Show confirmed price to customer
- POST purchase an online offer (with same voucher context)
Example preview request payload (illustrative):
{
"onlineOfferId": 12345,
"customerId": 67890,
"voucherCode": "SUMMER21"
}Example preview response shape (illustrative):
{
"basePrice": {
"amount": 40.00,
"currency": "EUR"
},
"discountedBasePrice": {
"amount": 32.00,
"currency": "EUR"
},
"voucherDiscount": {
"amount": 8.00,
"currency": "EUR"
},
"voucherSuccessMessage": "Voucher applied successfully"
}Example purchase payload (illustrative):
{
"onlineOfferId": 12345,
"customerId": 67890,
"validFrom": "2024-07-01",
"voucherCode": "SUMMER21",
"paymentRequestToken": "abc123token"
}Example purchase response shape (illustrative):
{
"studioAccessCode": "PTKXPMUO",
"voucherSuccessMessage": "Voucher applied successfully"
}Scenario: Customer requests a list of their active and past purchases.
- GET online offer purchases by customer id
- Render purchase list with status and expiry
To narrow to a specific offer (e.g., for entitlement check):
- GET online offer purchases by customer id and offer id
- Skipping the preview step: Always generate a purchase preview before executing a transaction. This is the primary price and eligibility validation point.
- Stale voucher context: Voucher codes must be revalidated at purchase time. A code valid during preview may expire or be consumed before the purchase request lands.
- Missing access restriction handling: Studio restrictions can silently exclude offers from catalog results. Verify studio context if expected offers are absent.
- No post-purchase state refresh: Re-fetch purchase history after a successful transaction to keep UI entitlement state current.
- Missing purchase record storage: Persist the
studioAccessCodeimmediately after purchase and retrieve theonlineOfferPurchaseIdfrom purchase history for auditing and support resolution.
Online offer purchases emit three webhook events that together cover the full payment lifecycle.
| Event | When it fires |
|---|---|
CUSTOMER_ONLINE_OFFER_CREATED | The purchase record is created and the contingent is provisioned. Fires immediately on successful purchase, before payment is confirmed by the payment provider. |
CUSTOMER_ONLINE_OFFER_PAYMENT_CAPTURED | The payment for the purchase has been successfully captured by the payment provider. |
CUSTOMER_ONLINE_OFFER_PAYMENT_REJECTED | The payment was rejected by the payment provider. The purchase is fully reversed. |
CUSTOMER_ONLINE_OFFER_CREATED and CUSTOMER_ONLINE_OFFER_PAYMENT_CAPTURED carry the same payload shape:
{
"offerId": 1250918950,
"offerPurchaseId": 1250919341
}All three events scope the entity to the customer: entityId is the customerId.
Event reference:
When a payment for an online offer purchase is rejected, initiates a full reversal of the purchase. This closes the related open claim so the same offer can be purchased again without leaving residual debt behind. Partners are notified through the CUSTOMER_ONLINE_OFFER_PAYMENT_REJECTED webhook.
The following are reversed as part of this process:
- Purchased contingent
- Timeline entries
- Invoices
- Voucher redemption (if a voucher was applied at the time of purchase)
- Online sales are marked as reversed
Because the purchased contingent is hard-deleted during reversal, the data would otherwise be permanently lost. For this reason, the CUSTOMER_ONLINE_OFFER_PAYMENT_REJECTED webhook carries a rich payload containing the full offer purchase details captured at the time of rejection. Integrations that store or act on purchase data should subscribe to this event and use the payload to reconcile their records.
The current reversal flow does not account for partially used benefits. If a benefit was used before the payment was rejected, that usage is not reconstructed during reversal.
CUSTOMER_ONLINE_OFFER_PAYMENT_REJECTED payload:
{
"offerPurchaseId": 1250919341,
"offerId": 1250918950,
"name": "MODIFIED-onlineOfferUseCase",
"category": {
"id": 1210001531,
"name": "analysis"
},
"scopeOfUsage": 5,
"price": {
"amount": "99.00",
"currency": "EUR"
},
"discountValue": {
"amount": "5.00",
"currency": "EUR"
},
"discountedPrice": {
"amount": "94.00",
"currency": "EUR"
},
"studioId": 1210086760,
"studioAccessCode": "PCTQFT97",
"purchaseDate": "2026-06-16T17:27:59+02:00",
"validFrom": "2026-06-16T00:00:00+02:00",
"expiryDate": "2026-07-16T00:00:00+02:00",
"voucherCode": "CHVJP-UE2K-PKRX",
"paymentTransactionId": 1250919271,
"rejectionReason": null
}