---
title: "Quickstart"
description: "Create a test event, embed the picker, and confirm a booking end to end."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.seatlayer.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

This guide joins the two sides of a SeatLayer integration: the buyer SDK creates a short hold, then your server turns that hold into a permanent booking.

> **Start in test mode**
>
> Use a `pk_test_…` / `sk_test_…` key pair. Sandbox events behave like live events, but bookings spend no credits. Going live is a credential swap after the flow works.

1. **Create an event**

   Publish a chart in the Designer, then create a sandbox event from your server.

```js title="server/create-event.js" {5}
const response = await fetch("https://api.seatlayer.io/v1/events", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    authorization: `Bearer ${process.env.SEATLAYER_SECRET_KEY}`,
  },
  body: JSON.stringify({
    chartId: "ch_grand_theatre",
    name: "Dress rehearsal",
  }),
});

const { meta } = await response.json();
console.log(meta.key); // ev_9f3a
```

2. **Install the buyer SDK**

   Use the CDN directly or add the JavaScript package to your app.

```sh
   npm install @seatlayer/js@^0.30.0
   pnpm add @seatlayer/js@^0.30.0
   yarn add @seatlayer/js@^0.30.0
   bun add @seatlayer/js@^0.30.0
```

3. **Embed the picker**

   Choose the integration that matches your frontend. All variants return the same `holdId` checkout handoff.

### Script tag

```html title="checkout.html"
    <div id="picker" style="height: 640px"></div>
    <script src="https://cdn.seatlayer.io/seatlayer-js@0/seatlayer.js"></script>
    <script>
      const picker = new seatlayer.SeatPicker({
        container: "#picker",
        event: "ev_9f3a",
        onCheckout: async (_, __, handoff) => {
          await fetch("/api/checkout", {
            method: "POST",
            headers: { "content-type": "application/json" },
            body: JSON.stringify({ holdId: handoff.holdId }),
          });
        },
      });
      picker.render();
    </script>
```
### JavaScript

```js title="checkout.js"
    import { SeatPicker } from "@seatlayer/js";

    const picker = new SeatPicker({
      container: "#picker",
      event: "ev_9f3a",
      onCheckout: async (_, __, handoff) => {
        await fetch("/api/checkout", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ holdId: handoff.holdId }),
        });
      },
    });

    await picker.render();
```
### React

```tsx title="Checkout.tsx"
    import { SeatPicker } from "@seatlayer/react";

    export function Checkout() {
      return (
        <SeatPicker
          event="ev_9f3a"
          style={{ height: 640 }}
          onCheckout={async (_, __, handoff) => {
            await fetch("/api/checkout", {
              method: "POST",
              headers: { "content-type": "application/json" },
              body: JSON.stringify({ holdId: handoff.holdId }),
            });
          }}
        />
      );
    }
```

4. **Book from your server**

   Resolve authoritative pricing from the hold, complete your payment logic, then book with the secret key.

```js title="server/checkout.js" {3,15,24}
const eventKey = "ev_9f3a";
const headers = {
  authorization: `Bearer ${process.env.SEATLAYER_SECRET_KEY}`,
  "content-type": "application/json",
};

const holdResponse = await fetch(
  `https://api.seatlayer.io/v1/events/${eventKey}/holds/${holdId}`,
  { headers },
);
if (!holdResponse.ok) throw new Error("Hold is no longer active");
const hold = await holdResponse.json();

// Price from trusted hold items—not values posted by the browser.
const order = await createPaidOrder(hold.items);

const bookResponse = await fetch(
  `https://api.seatlayer.io/v1/events/${eventKey}/book`,
  {
    method: "POST",
    headers,
    body: JSON.stringify({
      holdId,
      bookingRef: order.id,
    }),
  },
);
if (!bookResponse.ok) await handleBookingFailure(bookResponse, order);
```

> **Never expose the secret key**
>
> Browser code receives an event-scoped public configuration only. Keep every `sk_test_…` and `sk_live_…` credential in a server-side environment variable.

## Next

Use the [complete checkout example](/examples/complete-checkout) as an implementation template, then read [integration best practices](/integrations/best-practices) before going live.

Source: https://docs.seatlayer.io/start/quickstart/index.mdx
