Skip to content

Inventory reports and audit log

Retrieve live inventory, configured booked-value snapshots, channel attribution, accessibility breakdowns, CSV exports, and event history.

Updated View as Markdown

Reports are private organizer data. They describe the event’s durable inventory record, including immutable configured-price snapshots captured when inventory was booked. They are not a payment-provider or commercial-order ledger.

JSON report

GET/v1/events/:key/reportSecret key, dashboard session, or event:reports manage token
curl -s "https://api.seatlayer.io/v1/events/ev_9f3a/report" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY"

The response is {report, event, categories}.

{
  "report": {
    "byStatus": {
      "free": 40,
      "held": 3,
      "booked": 55,
      "not_for_sale": 2
    },
    "byCategory": [
      {
        "category": "vip",
        "total": 80,
        "free": 35,
        "held": 2,
        "booked": 41,
        "not_for_sale": 2,
        "bookedValue": 3075,
        "bookedRevenue": 3075
      }
    ],
    "bySection": [
      {
        "sectionId": "sec-stalls",
        "sectionLabel": "Stalls",
        "zoneId": "floor-main",
        "total": 400,
        "free": 180,
        "held": 4,
        "booked": 206,
        "not_for_sale": 10,
        "bookedValue": 15450,
        "bookedRevenue": 15450
      }
    ],
    "byAccessibility": [],
    "byWheelchairProvision": []
  },
  "event": {
    "key": "ev_9f3a",
    "name": "Opening Night",
    "status": "active",
    "seatTotal": 1200
  },
  "categories": [
    {
      "key": "vip",
      "label": "VIP",
      "color": "#d97706",
      "price": 75
    }
  ]
}

Interpret each breakdown

Field Meaning
byStatus Guest-weighted totals for the entire event
byCategory Status and configured booked value by category key
bySection Status and configured booked value by event section, with zone id
byAccessibility One row per accommodation type
byWheelchairProvision Physical accessible seat versus empty wheelchair space

A grouped table or variable-occupancy object is guest-weighted, so its quantity contributes to capacity rather than counting the object once.

Accessibility rows are not mutually exclusive: one seat with multiple accommodations contributes to each matching row. Do not sum those rows to derive whole-event inventory.

bookedValue is the sum of stored configured-price snapshots in major currency units for inventory that is currently booked. It changes when bookings are cancelled and does not prove that a payment was charged, settled, or refunded. bookedRevenue returns the same number as a deprecated compatibility alias.

CSV export

CSV downloads are dashboard/Control Room exports in this launch: they require a dashboard session and reject secret keys. They are not published OpenAPI operations or server-SDK methods. Server integrations should call the typed JSON reports above and serialize the fields they need; do not depend on an internal .csv route.

The response is a downloadable text/csv file with:

category,label,price,total,free,held,booked,not_for_sale,booked_value

A TOTALS row follows the category rows. Accessibility, wheelchair-provision, and section breakdowns remain available in JSON because they are not one mutually exclusive category table.

Sales channel report

GET/v1/events/:key/channels/reportSecret key, dashboard session, or event:channels:view manage token

One row per sales channel, plus Public sale. Each row carries two things that are easy to confuse and that move independently.

allocation Where inventory is assigned right now, and its physical status. Changes when you move seats.
attribution Which channel each unit was sold from, recorded at the moment of booking and never rewritten.
{
  "report": {
    "assignmentVersion": 7,
    "includesBookedValue": true,
    "includesRevenue": true,
    "methodology": {
      "allocation": "Current allocation: where inventory is assigned right now…",
      "attribution": "Sale attribution: the channel each unit was sold from…",
      "sellThrough": "Sell-through = attributed sold / current allocated…"
    },
    "rows": [
      {
        "channelId": "public",
        "name": "Public sale",
        "externalRef": null,
        "state": "active",
        "allocation": { "allocated": 800, "free": 612, "held": 4, "booked": 180, "blocked": 4, "units": 800 },
        "attribution": { "sold": 180, "units": 180, "bookedValue": 8100, "revenue": 8100 },
        "sellThrough": 0.225
      },
      {
        "channelId": "chn_7f2a",
        "name": "Travel Agency A",
        "externalRef": "travel-agency-a",
        "state": "active",
        "allocation": { "allocated": 120, "free": 78, "held": 2, "booked": 40, "blocked": 0, "units": 120 },
        "attribution": { "sold": 40, "units": 40, "bookedValue": 3000, "revenue": 3000 },
        "sellThrough": 0.3333333333333333
      }
    ],
    "totals": {
      "allocated": 1000, "free": 690, "held": 6, "booked": 220, "blocked": 4,
      "sold": 220, "bookedValue": 11100, "revenue": 11100
    }
  },
  "event": { "key": "ev_9f3a", "name": "Opening Night", "status": "active", "seatTotal": 1000 }
}

bookedValue is the canonical configured-value field. revenue and includesRevenue return the same values as deprecated compatibility aliases. These are inventory attribution snapshots, not proof of a charge or settlement.

When creating a channel report link, send includesBookedValue: true to include these configured values. The older includesRevenue request field remains an additive compatibility alias; if both fields are sent, they must agree.

Sell-through, and why it can exceed 100%

sellThrough is attributed sold divided by current allocated. The numerator is frozen at sale time; the denominator is live. So a channel whose remaining inventory is moved out after it sold can report more than 1.0, and a channel with no allocation left reports null rather than 0 — there is genuinely nothing to divide by, which is not the same as “sold nothing”.

The same three sentences ship inside every response as methodology, so a report you export or forward explains itself.

Who sees what

Capability Result
event:channels:view Every allocation and attribution figure, with configured booked value hidden as bookedValue: null and includesBookedValue: false
event:channels:view + event:reports The same report, with configured booked value in bookedValue
event:reports alone 403 missing_manage_capability

Configured booked value is null, never 0, when you may not see it — a zero would read as a channel that sold nothing.

Channel CSV export

Channel CSV is likewise a dashboard export rather than a stable server-SDK operation. Integrations should retrieve the typed channel report and generate their own file.

channel_id,channel,external_ref,state,allocated,free,held,booked,blocked,sold_by_attribution,sell_through,booked_value_by_attribution

A TOTALS row follows. sell_through is a ratio, not a percentage string, so a spreadsheet can format it; an empty cell means there is no current allocation to divide by. The booked_value_by_attribution column is absent entirely when the caller lacks event:reports.

Partner-facing channel reports

An organizer can share one channel without granting dashboard or API access. In Performance → Channel, choose Share partner report for a private channel. The generated URL opens a live, read-only projection containing one channel row and the exact inventory currently assigned to it.

The projection deliberately excludes event totals, sibling channel names, buyer identities, holds, and booking references. Configured booked value is excluded unless the organizer explicitly enables it for that link. The partner can search and filter the allocation or export the scoped inventory as CSV.

The URL capability appears after #, is removed from browser history before the application starts, and is stored by SeatLayer only as a SHA-256 hash. The organizer must copy it when it is created; later listings contain status, expiry, view count, and last-viewed time, never the URL. Revoke the link to stop access immediately.

Audit log

GET/v1/events/:key/logSecret key, dashboard session, or event:reports manage token

Entries are newest first. limit defaults to 50 and is capped at 200. Pass the returned nextBefore as before to retrieve older entries.

curl -s \
  "https://api.seatlayer.io/v1/events/ev_9f3a/log?limit=50&before=405" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY"
{
  "entries": [
    {
      "id": 404,
      "at": 1736897900000,
      "action": "book",
      "labels": ["A-1", "A-2"],
      "ref": "order_5567"
    }
  ],
  "nextBefore": 354
}

Actions include hold, replace, extend, book, release, expiry, block, unblock, unbook, reveal, and availability changes as those operations occur.

Incremental booking reconciliation

GET/v1/events/:key/booking-changesSecret key, dashboard session, or event:view/event:reports manage token

Platform events expose an oldest-first, append-only change feed for inventory bookings. Use it for a background reconciliation job that must discover later cancellations to older booking references without rescanning every booking.

curl -s \
  "https://api.seatlayer.io/v1/events/ev_9f3a/booking-changes?after=418&limit=100" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY"
{
  "changes": [
    {
      "id": 419,
      "action": "partial_cancel",
      "at": 1786897900000,
      "labels": ["A-2"],
      "actor": "refund-worker",
      "source": "server_api",
      "booking": {
        "eventKey": "ev_9f3a",
        "bookingRef": "order_5567",
        "state": "partially_cancelled",
        "activeQuantity": 1,
        "activeConfiguredValue": 75,
        "currency": "USD"
      }
    }
  ],
  "nextAfter": null,
  "checkpoint": 419
}

The numeric activity id—not bookedAt or updatedAt—is the cursor. That matters because cancelling a week-old booking changes its current record while its original booking time stays the same, and multiple changes may share one millisecond.

Drain pages while nextAfter is non-null. After the final page, persist checkpoint and send it as the next after. An empty poll echoes the same checkpoint. Actions are book, replay, partial_cancel, cancel, and reconcile; each change includes the current inventory-only booking record. The feed contains no buyer, payment, refund, ticket, email, or door data.

Reporting checklist

  • Keep configured booked value grouped by event currency.
  • Do not label SeatLayer snapshots as payment-provider settlement.
  • Do not sum overlapping accessibility rows.
  • Export until nextBefore is null when a complete audit is required.
  • Persist the final booking-change checkpoint only after your reconciliation write commits.
  • Restrict browser manage tokens to the event and event:reports.
  • Store your own order, refund, tax, fee, and payment identifiers.
  • Retain the event key and booking reference in every reconciliation record.
  • Reconcile channel booked value by attribution, never by current allocation.
  • State the sell-through denominator anywhere you republish the figure.

Archived events continue to serve reports. See event lifecycle and webhook delivery.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close