---
title: "Inventory cancellations and direct booking"
description: "Return Platform/SDK inventory safely and book free seats directly from a trusted backend."
---

These routes belong to **Platform/SDK events**, where your application owns
money, commercial orders, fulfilment, refunds, and customer support. SeatLayer
only changes authoritative inventory. Refund payment in your system, then
unbook with the original booking reference. For a trusted POS or comp workflow,
book free seats directly without a buyer hold.

They return `404 not_found` for Managed Ticketing and unresolved events. A
Managed organizer must cancel through the coordinated SeatLayer Order/refund
workflow, and must use Managed Box Office for counter sales.

## Cancel a booking

<ApiEndpoint method="POST" path="/v1/events/:key/unbook" auth="Secret key, dashboard session, or event:cancel manage token" />

```bash
curl -sX POST "https://api.seatlayer.io/v1/events/ev_9f3a/unbook" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{
    "labels": ["A-1","A-2"],
    "bookingRef": "order_5567"
  }'
```

Every label must still be booked under that exact `bookingRef`. The operation
is all-or-nothing:

<Tabs>
  <TabItem label="Success">

```json
{
  "ok": true,
  "unbooked": ["A-1", "A-2"],
  "conflicts": []
}
```

  </TabItem>
  <TabItem label="Booking mismatch">

```json
{
  "error": "booking_mismatch",
  "conflicts": [
    {
      "label": "A-2",
      "status": "booked"
    }
  ]
}
```

  </TabItem>
</Tabs>

The booking reference guard prevents a delayed refund job from freeing a seat
that has since been resold under another order.

<Aside type="caution" title="Unbook is not a refund">
  Return money in your payment system. `unbook` only changes SeatLayer
  inventory. The original booked-seat credit is not returned, and a later
  a later ordinary booking of the same freed unit is not metered again. This
  does not create a seller-owned resale listing or payout workflow.
</Aside>

## Book inventory directly

<ApiEndpoint method="POST" path="/v1/events/:key/box-book" auth="Secret key or dashboard session" />

```bash
curl -sX POST "https://api.seatlayer.io/v1/events/ev_9f3a/box-book" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{
    "labels": ["C-14","C-15"],
    "bookingRef": "pos_88213"
  }'
```

`box-book` is a legacy name for a Platform inventory operation. It transitions
inventory directly from `free` to `booked`; it does not create a SeatLayer
Order, ticket, email, refund, or Door record. There is no hold or browser
checkout handoff. The requested labels are atomic; a conflict leaves all of
them unchanged. Event-scoped browser manage tokens cannot call this route; the
platform backend should normally confirm paid inventory through `/book`.

The route is idempotent by `bookingRef`. A replay succeeds with
`{"ok":true,"booked":[]}` rather than repeating the sale.

## Recommended cancellation workflow

1. Load your order by the stable booking reference.
2. Lock or idempotently claim the cancellation in your database.
3. Refund or void payment according to your business policy.
4. Call `unbook` with the exact labels and original booking reference.
5. Record the response and reconcile any mismatch instead of broadening the
   release.
6. Let `seat.released` update downstream systems.

If inventory must be guaranteed free before refunding, reverse steps 3 and 4
and implement compensation for a failed refund. Choose one policy explicitly.

## Recommended trusted-POS workflow

1. Read current availability in your operator surface.
2. Choose free labels and calculate payment in the trusted POS.
3. Create a stable POS order reference.
4. Call `box-book`.
5. On `409`, reload inventory and ask the operator to reselect.
6. Persist the successful response and issue the ticket in your system.

## Effects

Successful actions update all mounted views in real time, write the event audit
log, and emit signed webhooks:

| Operation | Webhook |
|---|---|
| `box-book` | `seat.booked`; possibly `event.soldout` |
| `unbook` | `seat.released` |

Continue to [reports](/server-api/reports),
[webhook events](/webhooks/events), and
[idempotency and conflicts](/server-api/idempotency-and-conflicts).