> ## Documentation Index
> Fetch the complete documentation index at: https://playbook.smedleygroup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How A Sale Happens

> The revenue path end to end: availability, checkout creation, payment on Vivenu, and how a paid ticket comes back linked to a driver.

This is the path that takes money. Everything else in GKL Platform exists to support it.

## The Division Of Labour

Vivenu is the shop. It owns the ticket types, the prices, the stock, the payment and the ticket itself. GKL Platform owns everything Vivenu cannot know: whether a particular driver is allowed to buy a particular ticket, and which driver a ticket belongs to.

> [!NOTE]
>
> The booking website never talks to Vivenu's API. Every call goes through GKL API, which proxies to Vivenu. The only time the customer touches Vivenu directly is to pay, and to view a ticket barcode afterwards.

## Where Customers Come From

Customers do not arrive at the booking website directly. They arrive at the apex domain, `fat-kartingleague.com`, which is the marketing site. It carries the list of events, and each one redirects through to our booking website at `events.fat-kartingleague.com`.

> [!WARNING]
>
> The apex site is a Lovable site owned and maintained by the sales and marketing teams. It is entirely outside Advanced Tech's control, and how they maintain their list of events is not known to anyone here. It is nonetheless the front door to every sale: if an event is missing from it, or a redirect is wrong, customers never reach the booking website at all and nothing on our side registers a problem.

The dependency also runs the other way. The CloudFront distributions in front of both web apps use `www.fat-kartingleague.com` as their fallback origin, so a failure on our side sends visitors to the marketing site rather than an error page.

## The Path

**1. The site asks what this user can buy**

The booking website requests the availability tree for an event and a user. GKL returns, for every driver that user owns, the ticket types that driver may buy, split into perfect and close matches. See [Ticket Eligibility](/software/developer/estate/systems/gkl/ticket-eligibility).

**2. The customer chooses tickets for drivers**

Selection happens in our UI, not Vivenu's. Each line is a ticket type paired with a specific driver.

**3. GKL creates the checkout in Vivenu**

GKL calls Vivenu to create a transaction checkout, carrying the chosen items, any vouchers and coupons, a sales channel of `sch-web`, and the metadata described below.

**4. GKL pre-fills the customer details**

A second call sends the user's name and email to the checkout, so the customer does not retype what we already hold.

**5. The customer pays on Vivenu**

GKL returns a checkout URL into the Vivenu shop with `step=2&noSteps=true`, which drops the customer straight onto payment rather than the start of Vivenu's own flow.

**6. Vivenu tells us what happened**

Checkout, transaction and ticket webhooks arrive back at GKL, HMAC signed. Each is mirrored into our own collections.

## The Driver Linkage

This is the part nobody would guess, and it is what makes the whole model work.

When GKL creates the checkout, it attaches metadata that Vivenu stores and hands back untouched:

| Where | Field | Meaning |
| - | - | - |
| On the transaction | `gklUserId` | Which GKL user is buying |
| On **each item** | `gklDriverId`, `gklUserId` | Which GKL driver that specific ticket is for |

So the driver is decided **before payment**, travels through Vivenu as opaque metadata, and comes back on the ticket webhook. When that webhook arrives, GKL reads `gklUserId` and `gklDriverId` out of the ticket's meta and stores the ticket already attached to the right driver.

> [!WARNING]
>
> On an **update** webhook, our own stored values win. GKL uses the existing ticket's user and driver if it already has the ticket, and only falls back to the Vivenu metadata when it does not. This is deliberate: an operator who reassigns a ticket to a different driver must not have that reassignment silently reverted the next time Vivenu updates the ticket.

That fallback order is also why a ticket created outside our checkout flow, directly in Vivenu, arrives with no driver attached and has to be assigned by hand.

## What Else The Checkout Endpoint Handles

**Aborting.** A customer can abandon a checkout. GKL fetches it from Vivenu, confirms the `gklUserId` in its metadata matches the caller, and only aborts if the status is still `NEW`. Anything further along is refused.

**Discounts.** A code is validated against Vivenu for the event's seller, and comes back classified as a coupon or a voucher, with a state. The distinction matters because they behave differently at checkout.

**Free tickets.** Operators issue these through the dashboard, which asks GKL to create them in Vivenu directly rather than going through a checkout.

## Where It Breaks

| Failure | Consequence |
| - | - |
| A webhook fails to deliver | The sale happened but we do not know. Nothing alarms, because no request arrived. See [Vivenu Webhook Health](/software/developer/operations/weekly#vivenu-webhook-health) |
| The HMAC secret drifts | Webhooks return 401 and the same thing happens, but visibly in Vivenu's dashboard |
| A ticket is created directly in Vivenu | It arrives with no `gklDriverId`, so no driver is attached. It surfaces on the problematic tickets page in the Operator Dashboard for someone to assign by hand |
| Eligibility is wrong | Either a driver is offered a class they cannot race, or is blocked from one they can |

## Related Documentation

| Page | Relevance |
| - | - |
| [Ticket Eligibility](/software/developer/estate/systems/gkl/ticket-eligibility) | How the availability tree is decided |
| [The Domain Model](/software/developer/estate/systems/gkl/domain-model) | What a ticket, checkout and transaction actually are |
| [Hub Regions and Configuration](/software/developer/estate/systems/gkl/hub-regions-and-configuration) | Where the Vivenu credentials and shop URL come from |
| [Configuring the Webhooks](/software/third-party/vivenu/hub-deployment/development/configure-webhooks) | Setting up the four webhooks for a seller |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.