---
title: "Events on SeatLayer checkout"
description: "Create SeatLayer-checkout and free events with a secret key, then choose the gateway, check readiness, go live, and manage the booking fee and discount codes."
---

A secret key can create the same events the dashboard creates, and take them on
sale. Connect your payment gateway once in the dashboard (Payments); everything
after that can run from your server.

## Create the event

```http
POST /v1/events
Authorization: Bearer sk_live_…

{ "chartId": "ch_41b2", "name": "Opening Night", "currency": "GBP", "buyerCheckout": "seatlayer" }
```

| You send | You get |
|---|---|
| `buyerCheckout: "seatlayer"` | SeatLayer checkout takes payment through your connected gateway. The event starts in `setup`, and the gateway is assigned when you have one connected. |
| `bookingMode: "free"` | Bookings nobody pays for, through SeatLayer checkout with no gateway. Also starts in `setup`. |
| Neither (or `buyerCheckout: "integrator"`) | Platform inventory: your own checkout takes payment, and the event is on sale at once. This is what a key always made before. |
| `buyerCheckout: "integrator"` with `bookingMode: "free"` | Platform inventory, as above. Free bookings are a SeatLayer checkout event, so the booking mode is ignored when you name your own checkout. |

The accepted values are `buyerCheckout`: `seatlayer` or `integrator`, and
`bookingMode`: `paid` or `free`. A key's create ignores any other value, as it
always has, so the event is Platform inventory.

## Who takes payment

<ApiEndpoint method="GET" path="/v1/events/:key/buyer-checkout" auth="Secret key" />
<ApiEndpoint method="PUT" path="/v1/events/:key/buyer-checkout" auth="Secret key" />

The answer names the current choice, its `revision`, and for each choice what
would block it (live sales, holds, orders in flight, booking history). Change it
with `{ "buyerCheckout": "integrator", "expectedRevision": 3 }`; a stale revision
answers `409 buyer_checkout_revision_conflict`, and a repeat of the current
choice answers `changed: false`.

## Payment gateway

<ApiEndpoint method="GET" path="/v1/events/:key/payment-gateway" auth="Secret key" />
<ApiEndpoint method="PUT" path="/v1/events/:key/payment-gateway" auth="Secret key" />

`GET` lists every gateway your org connected and why each can or cannot take
this event's payments (mode, currency). `PUT { "connectionId": "…" }` assigns
one; `null` unassigns.

## Going on sale

<ApiEndpoint method="GET" path="/v1/events/:key/sales/readiness" auth="Secret key" />
<ApiEndpoint method="POST" path="/v1/events/:key/sales/preflight" auth="Secret key" />
<ApiEndpoint method="POST" path="/v1/events/:key/sales/transition" auth="Secret key" />

An event moves `setup` → `testable` → `live`, and can be `paused` or `ended`.
Readiness lists what the next step still needs (details, tickets, payment,
buyer page and so on). In `testable`, place a test order and record it with
`preflight { "orderId": "ord_…" }`. Then move on:

```http
POST /v1/events/evt_9f3a/sales/transition
Authorization: Bearer sk_live_…

{ "to": "live", "expectedRevision": 4 }
```

A step the event is not ready for answers `409 sales_not_ready` with `unmet`.

## Booking fee and discount codes

<ApiEndpoint method="GET" path="/v1/events/:key/booking-fee" auth="Secret key" />
<ApiEndpoint method="PUT" path="/v1/events/:key/booking-fee" auth="Secret key" />
<ApiEndpoint method="GET" path="/v1/events/:key/discount-codes" auth="Secret key" />
<ApiEndpoint method="POST" path="/v1/events/:key/discount-codes" auth="Secret key" />
<ApiEndpoint method="PATCH" path="/v1/events/:key/discount-codes/:codeId" auth="Secret key" />
<ApiEndpoint method="POST" path="/v1/events/:key/discount-codes/:codeId/end" auth="Secret key" />
<ApiEndpoint method="DELETE" path="/v1/events/:key/discount-codes/:codeId" auth="Secret key" />

`PUT /booking-fee { "bookingFeeMinor": 150 }` sets a fee per order (`null`
clears it). A code is `{ "code": "EARLY10", "kind": "percent", "percent": 10 }`
or `{ "kind": "amount", "amountMinor": 500 }`, with optional `startsAt`,
`endsAt` and `maxUses`. Pause one with `PATCH { "state": "paused" }`, end it for
good with `/end`, or delete one nobody has used.

<Aside type="note" title="Not by key">
  Connecting a gateway (an OAuth flow) and switching an event between live and
  test stay in the dashboard. A key's mode decides an event's mode.
</Aside>

No server SDK wraps these routes; call them from any language.