seatlayer

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 18 Imported by: 0

README

SeatLayer Go SDK

Official Go server SDK for the SeatLayer reserved-seating API.

Server-side only. This package authenticates with your secret key. Never embed it in anything a ticket buyer can reach — browser surfaces get short-lived, origin-bound tokens that you mint here.

Install

go get github.com/seatlayer/seatlayer-go

Requires Go 1.23 or newer (for range-over-func iterators). No dependencies — standard library only.

Quick start

import (
    "context"
    "os"

    "github.com/seatlayer/seatlayer-go"
)

client, err := seatlayer.New(os.Getenv("SEATLAYER_SECRET_KEY"))
if err != nil {
    return err
}
ctx := context.Background()

// 1. Provision a venue for a new organiser from one of your templates.
chart, err := client.Charts.Copy(ctx, "c_template_arena")
if err != nil {
    return err
}
chartID := chart["meta"].(map[string]any)["id"].(string)
if _, err := client.Charts.Publish(ctx, chartID); err != nil {
    return err
}

// 2. Create an event on it.
event, err := client.Events.Create(ctx, seatlayer.EventCreateParams{
    ChartID: chartID,
    Name:    "Spring Gala",
})
if err != nil {
    return err
}
eventKey := event["meta"].(map[string]any)["key"].(string)

// 3. Sell four seats over the phone.
held, err := client.Inventory.HoldBestAvailable(ctx, eventKey, seatlayer.BestAvailableParams{Qty: 4})
if err != nil {
    return err
}
// … take payment against held["items"], which carry authoritative prices …
_, err = client.Inventory.Book(ctx, eventKey, seatlayer.BookParams{
    HoldID:     held["holdId"].(string),
    BookingRef: "order-8842",
})

Every method takes a context.Context. Cancelling it stops retries immediately rather than being treated as a transient fault to back off through.

Test vs live

Keys carry their own mode. sk_test_… keys can only touch test-mode events and sk_live_… only live ones; crossing them returns 403 mode_mismatch.

client, err := seatlayer.New(os.Getenv("SEATLAYER_SECRET_KEY"))
if err != nil {
    return err
}
if os.Getenv("ENV") == "production" && client.Mode() != "live" {
    return errors.New("refusing to boot production against test-mode seating data")
}

A publishable pk_ key is rejected by New with a message naming the mistake, rather than failing as a 401 three round-trips later.

The two selling flows

Buyer picks seats in the browser. Your frontend holds them; your backend confirms the price and books. Never price from what the browser sent you — RetrieveHold is authoritative.

hold, err := client.Inventory.RetrieveHold(ctx, eventKey, holdID)
// … charge the total of hold["items"] in hold["currency"] …
_, err = client.Inventory.Book(ctx, eventKey, seatlayer.BookParams{
    HoldID: holdID, BookingRef: charge.ID,
})

Your backend picks the seats. Phone orders, box office, comps.

// Payment already taken — book outright, so nothing is stranded if a second call fails.
_, err := client.Inventory.BookBestAvailable(ctx, eventKey, seatlayer.BestAvailableParams{
    Qty: 2, BookingRef: "phone-1183",
})

// Or name the seats yourself.
_, err = client.Inventory.BoxOfficeBook(ctx, eventKey, []string{"A-1", "A-2"}, "comp-14")

Private and partner sales

Channels reserve inventory for a partner, member group, presale, or other private allocation. A buyer access session is short-lived and origin-bound, so the browser receives only the allocation it is allowed to sell; your secret key remains on your server.

_, err := client.Channels.CreateChannel(ctx, eventKey, seatlayer.ChannelCreateParams{
	Name:         "Venue members",
	AccessIntent: "private",
})

_, err = client.Channels.UpdateAssignments(ctx, eventKey, seatlayer.ChannelAssignmentParams{
	Labels:            []string{"A-1", "A-2"},
	AssignmentVersion: 1,
	TargetChannelID:   "ch_members",
})

access, err := client.Channels.CreateBuyerAccessSession(ctx, eventKey,
	seatlayer.BuyerAccessSessionParams{
		ChannelIDs:    []string{"ch_members"},
		IncludePublic: false,
		AllowedOrigin: "https://members.example",
		MaxQuantity:   2,
	})

Pass the returned token to the buyer SDK. Trusted backend sale params accept ChannelIDs, an explicit privileged IgnoreChannelRestrictions flag, and an audit Reason.

Listing and pagination

List returns one Page plus a cursor. All is a range-over-func iterator that pages as you consume it — deliberately not a slice, because the point of paginating is to not hold an unbounded result set in memory.

// One page, your own paging.
page, err := client.Events.List(ctx, &seatlayer.EventListParams{Limit: 50})
page.Items
page.NextCursor   // "" once exhausted

// Or let the SDK walk it.
for event, err := range client.Events.All(ctx, nil) {
    if err != nil {
        return err
    }
    sync(event)
}

The error rides alongside each item so a failed page reaches you — an iterator that silently ended on error would look identical to a list that finished.

Listing events includes live availability counts by default, which costs the server one round-trip per event. All drops them automatically — walking a whole catalogue is exactly when you don't want that — and you can control it explicitly:

client.Events.List(ctx, &seatlayer.EventListParams{Limit: 50, NoCounts: true})

Keeping a hold alive

When an order takes longer than the checkout window — an invoice, a phone sale — extend rather than release and re-hold. Releasing first hands the seats to whoever is racing for them in between.

_, err := client.Inventory.ExtendHold(ctx, eventKey, holdID, 10*60*1000)

var conflict *seatlayer.ConflictError
if errors.As(err, &conflict) {
    // Gone, expired, or at its renewal cap — the buyer has to re-pick.
}

Embedding the control room

Your secret key never reaches a browser. Mint a scoped token instead.

session, err := client.Sessions.CreateManageSession(ctx, eventKey, seatlayer.ManageSessionParams{
    AllowedOrigin:    "https://box-office.yourplatform.com",
    Capabilities:     []string{seatlayer.CapabilityView, seatlayer.CapabilityBlock},
    ExpiresInSeconds: 3600,
})

Capabilities is required by this SDK even though the API defaults it. That default grants all four including event:cancel, which reverses paid bookings — not something that should arrive by forgetting a field. Grant the smallest set the page needs.

Webhooks

Verify every delivery against the raw body. Decoding and re-encoding changes the bytes — in Go specifically, encoding/json marshals map keys in sorted order while a real delivery arrives in the order we serialised it, so a round trip reorders it and verification fails.

func handleWebhook(w http.ResponseWriter, r *http.Request) {
    payload, err := io.ReadAll(r.Body)   // raw bytes, before any decoding
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    event, err := seatlayer.VerifyWebhook(
        payload,
        r.Header.Get("X-SeatLayer-Signature"),
        os.Getenv("SEATLAYER_WEBHOOK_SECRET"),
    )
    if errors.Is(err, seatlayer.ErrWebhookVerification) {
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    // The signed body carries "at", but nothing enforces a freshness window, so a
    // captured delivery stays valid indefinitely. Deduplicate on occurrenceId —
    // this is your replay protection, not an optimisation.
    if alreadyProcessed(event["occurrenceId"].(string)) {
        w.WriteHeader(http.StatusOK)
        return
    }

    process(event)
    w.WriteHeader(http.StatusOK)
}

Errors

Errors are values here, not exceptions — reach for errors.As:

_, err := client.Inventory.HoldBestAvailable(ctx, eventKey, seatlayer.BestAvailableParams{Qty: 6})

var conflict *seatlayer.ConflictError
var rateLimit *seatlayer.RateLimitError
var auth *seatlayer.AuthError

switch {
case errors.As(err, &conflict) && conflict.SoldOut():
    return offerAlternativeDates()          // a business outcome, not a bug
case errors.As(err, &rateLimit):
    return retryAfter(rateLimit.RetryAfter)
case errors.As(err, &auth) && auth.ModeMismatch():
    return errors.New("test key pointed at a live event, or the reverse")
case err != nil:
    return err
}
Type Status Means
AuthError 401, 403 Bad, revoked, or wrong-mode key
NotFoundError 404 No such resource for this organisation
ConflictError 409 Inventory moved, or a guard rejected the change
ValidationError 422 Understood and rejected
RateLimitError 429 Over budget; carries RetryAfter
ConnectionError No answer: DNS, TLS, socket, context deadline (unwraps)

Every API error carries Status, Code, Body, and RequestID — quote the request id in support requests.

Reliability

Retries. 429, 408 and 5xx are retried with exponential backoff and full jitter; Retry-After wins when the server sends it. 4xx is never retried — it will not start succeeding.

Idempotency. Every mutating request carries an Idempotency-Key, generated if you do not supply one, and reused across retries so a retried booking cannot become two bookings. Pass your own order id for end-to-end deduplication:

client.Inventory.Book(ctx, eventKey, seatlayer.BookParams{
    HoldID: holdID, IdempotencyKey: "order-" + orderID,
})
client, err := seatlayer.New(
    os.Getenv("SEATLAYER_SECRET_KEY"),
    seatlayer.WithMaxRetries(3),
    seatlayer.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
)

Client is safe for concurrent use.

Escape hatch

For surface this SDK does not wrap yet — same auth, retries, idempotency and error mapping:

client.Do(ctx, http.MethodPost, "/v1/events/ev_1/some-new-route", nil, map[string]any{"qty": 2}, "")

API surface

Service Methods
Charts List All Create Retrieve Update Delete Copy Archive Unarchive Publish
Events List All Create Retrieve Update Delete UpdateChart Close Reopen Archive RetrieveHoldTTL UpdateHoldTTL RetrieveReport RetrieveLog
Channels ListChannels CreateChannel UpdateChannel UpdateAssignments ListAllocation RetrieveAccessPreview RetrieveReport Pause Unpause Archive CreateBuyerAccessSession ListBuyerAccessSessions RevokeBuyerAccessSession
Inventory Hold HoldBestAvailable BookBestAvailable ExtendHold RetrieveHold Release Book BoxOfficeBook Unbook Block Unblock UnblockAll RetrieveAvailability UpdateAvailability ListBookings RetrieveBooking
Sessions CreateManageSession RevokeManageSession CreateDesignerSession RevokeDesignerSession
Webhooks List Create Update Delete ListDeliveries
Workspaces List Create Retrieve Update

Full reference: docs.seatlayer.io/server-sdk

Other SeatLayer SDKs
Surface Package
Browser (vanilla) @seatlayer/js
React @seatlayer/react
React Native @seatlayer/react-native
iOS seatlayer-ios
Android seatlayer-android
Flutter seatlayer
Node.js (server) @seatlayer/server
Python (server) seatlayer
PHP (server) seatlayer/seatlayer-php
Java (server) io.seatlayer:seatlayer-java
Go (server) github.com/seatlayer/seatlayer-go
Ruby (server) seatlayer
.NET (server) SeatLayer

Development

gofmt -l .          # must be empty
go vet ./...
go test -race ./...

License

MIT

Documentation

Overview

Package seatlayer is the official Go server SDK for the SeatLayer reserved-seating API.

Server-side only: this package authenticates with your secret key. Never embed it in anything a ticket buyer can reach — browser surfaces get short-lived, origin-bound tokens that you mint with Sessions.

client, err := seatlayer.New(os.Getenv("SEATLAYER_SECRET_KEY"))
if err != nil {
	return err
}
held, err := client.Inventory.HoldBestAvailable(ctx, "summer-gala",
	seatlayer.BestAvailableParams{Qty: 4})

Index

Constants

View Source
const (
	// DefaultBaseURL is the public API.
	DefaultBaseURL = "https://api.seatlayer.io"
	// DefaultMaxRetries counts total attempts, not extra ones.
	DefaultMaxRetries = 3
	// DefaultTimeout applies per attempt.
	DefaultTimeout = 30 * time.Second
)
View Source
const (
	CapabilityView    = "event:view"
	CapabilityBlock   = "event:block"
	CapabilityCancel  = "event:cancel"
	CapabilityReports = "event:reports"
)

Capabilities a manage-session token can carry.

Variables

View Source
var ErrWebhookVerification = errors.New("seatlayer: webhook verification failed")

ErrWebhookVerification means the delivery did not come from SeatLayer. Respond 400 and do not process it.

Functions

func VerifyWebhook

func VerifyWebhook(payload []byte, signature, secret string) (map[string]any, error)

VerifyWebhook checks a delivery's signature and returns its decoded payload.

payload must be the RAW request body — in net/http that is io.ReadAll(r.Body) before any decoding. Re-serialising a decoded body reorders keys and changes whitespace, so verification fails; the usual "fix" for that is to disable verification, which is why this takes bytes and does the work for you.

Errors wrap ErrWebhookVerification, so callers can test with errors.Is.

NOTE ON REPLAY: deliveries are signed over the body, which carries an "at" timestamp — but nothing enforces a freshness window, so a captured delivery stays valid indefinitely. Replay protection is yours: every event carries an occurrenceId, and the correct pattern is to record processed ids and ignore repeats. Do not skip this.

Types

type APIError

type APIError struct {
	// Status is the HTTP status the API answered with.
	Status int
	// Code is the machine-readable slug: body "code", falling back to "error".
	Code string
	// Message is the human-readable message, when the API sent one.
	Message string
	// Body is the decoded error body, for fields this SDK does not model.
	Body map[string]any
	// RequestID comes from X-Request-ID. Quote it in support requests.
	RequestID string
}

APIError is the base error returned for any non-2xx response.

Go has no exception hierarchy, so the pattern here is errors.As against the specific types below rather than catch blocks. A sold-out seat is a business outcome that belongs in an if, not lumped in with a bad key:

var conflict *ConflictError
if errors.As(err, &conflict) && conflict.SoldOut() {
	return offerAlternativeDates()
}

func (*APIError) Error

func (e *APIError) Error() string

type AuthError

type AuthError struct{ APIError }

AuthError is a 401 or 403 — bad key, revoked key, or a live key used against a test event.

func (*AuthError) ModeMismatch

func (e *AuthError) ModeMismatch() bool

ModeMismatch reports whether the key's mode and the event's mode disagree. This is the most common cause of a "works locally, 403s in production" report.

type BestAvailableParams

type BestAvailableParams struct {
	// Qty is clamped to the server maximum rather than rejected.
	Qty         int
	CategoryKey string
	ZoneID      string
	// TTLMs overrides the event's checkout window. Ignored by BookBestAvailable.
	TTLMs int64
	// BookingRef is required by BookBestAvailable and ignored by HoldBestAvailable.
	BookingRef     string
	IdempotencyKey string
	ChannelIDs     []string
	// IgnoreChannelRestrictions is a privileged backend override.
	IgnoreChannelRestrictions bool
	// Reason is written to the audit trail for channel use or an override.
	Reason string
}

BestAvailableParams asks us to choose the objects.

type BookParams

type BookParams struct {
	// HoldID books a previously held selection…
	HoldID string
	// …or Labels books outright, with no prior hold.
	Labels         []string
	BookingRef     string
	IdempotencyKey string
	ChannelIDs     []string
	// IgnoreChannelRestrictions is a privileged backend override.
	IgnoreChannelRestrictions bool
	// Reason is written to the audit trail for channel use or an override.
	Reason string
}

BookParams books either a held selection or labels outright.

type BookingListParams added in v0.2.0

type BookingListParams struct {
	Query  string
	State  string
	Limit  int
	Cursor string
}

BookingListParams filters and pages booking lifecycle records.

type BuyerAccessSessionListParams added in v0.2.0

type BuyerAccessSessionListParams struct {
	State  string
	Limit  int
	Cursor string
}

BuyerAccessSessionListParams filters and pages buyer access sessions.

type BuyerAccessSessionParams added in v0.2.0

type BuyerAccessSessionParams struct {
	ChannelIDs       []string
	IncludePublic    bool
	AllowedOrigin    string
	ExpiresInSeconds int
	MaxQuantity      int
	BuyerRef         string
	PartnerRef       string
	ClientRequestID  string
	IdempotencyKey   string
}

BuyerAccessSessionParams defines the security boundary of a buyer token.

type ChannelAssignmentParams added in v0.2.0

type ChannelAssignmentParams struct {
	Labels            []string
	AssignmentVersion int64
	TargetChannelID   string
	Reason            string
	IdempotencyKey    string
}

ChannelAssignmentParams moves inventory between public and private allocation.

type ChannelCreateParams added in v0.2.0

type ChannelCreateParams struct {
	Name           string
	Color          string
	Marker         string
	ExternalRef    string
	AccessIntent   string
	Reason         string
	IdempotencyKey string
}

ChannelCreateParams defines a private allocation channel.

type ChannelUpdateParams added in v0.2.0

type ChannelUpdateParams struct {
	Name                  string
	AccessIntent          string
	AcknowledgeLiveAccess *bool
	Reason                string
}

ChannelUpdateParams defines mutable channel fields.

type ChannelsService added in v0.2.0

type ChannelsService struct {
	// contains filtered or unexported fields
}

ChannelsService manages private allocations, reporting, and buyer access.

func (*ChannelsService) Archive added in v0.2.0

func (s *ChannelsService) Archive(
	ctx context.Context, eventKey, channelID, destination, reason string,
) (map[string]any, error)

Archive retires a channel and moves its inventory to destination.

func (*ChannelsService) CreateBuyerAccessSession added in v0.2.0

func (s *ChannelsService) CreateBuyerAccessSession(
	ctx context.Context, eventKey string, p BuyerAccessSessionParams,
) (map[string]any, error)

CreateBuyerAccessSession mints a short-lived, origin-bound buyer token.

func (*ChannelsService) CreateChannel added in v0.2.0

func (s *ChannelsService) CreateChannel(
	ctx context.Context, eventKey string, p ChannelCreateParams,
) (map[string]any, error)

CreateChannel creates a private allocation channel.

func (*ChannelsService) ListAllocation added in v0.2.0

func (s *ChannelsService) ListAllocation(
	ctx context.Context, eventKey, afterLabel string, limit int,
) (map[string]any, error)

ListAllocation returns the current allocation ledger.

func (*ChannelsService) ListBuyerAccessSessions added in v0.2.0

func (s *ChannelsService) ListBuyerAccessSessions(
	ctx context.Context, eventKey string, p BuyerAccessSessionListParams,
) (map[string]any, error)

ListBuyerAccessSessions returns one page of buyer access sessions.

func (*ChannelsService) ListChannels added in v0.2.0

func (s *ChannelsService) ListChannels(
	ctx context.Context, eventKey string, includeArchived bool,
) (map[string]any, error)

ListChannels lists an event's allocation channels.

func (*ChannelsService) Pause added in v0.2.0

func (s *ChannelsService) Pause(
	ctx context.Context, eventKey, channelID, reason string,
) (map[string]any, error)

Pause temporarily disables a channel.

func (*ChannelsService) RetrieveAccessPreview added in v0.2.0

func (s *ChannelsService) RetrieveAccessPreview(
	ctx context.Context, eventKey string, channelIDs []string, includePublic *bool,
) (map[string]any, error)

RetrieveAccessPreview shows the inventory visible to a buyer access scope.

func (*ChannelsService) RetrieveReport added in v0.2.0

func (s *ChannelsService) RetrieveReport(
	ctx context.Context, eventKey string,
) (map[string]any, error)

RetrieveReport returns channel allocation totals.

func (*ChannelsService) RevokeBuyerAccessSession added in v0.2.0

func (s *ChannelsService) RevokeBuyerAccessSession(
	ctx context.Context, eventKey, sessionID string,
) (map[string]any, error)

RevokeBuyerAccessSession revokes a buyer token before it expires.

func (*ChannelsService) Unpause added in v0.2.0

func (s *ChannelsService) Unpause(
	ctx context.Context, eventKey, channelID, reason string,
) (map[string]any, error)

Unpause restores a paused channel.

func (*ChannelsService) UpdateAssignments added in v0.2.0

func (s *ChannelsService) UpdateAssignments(
	ctx context.Context, eventKey string, p ChannelAssignmentParams,
) (map[string]any, error)

UpdateAssignments changes the allocation owner of inventory labels.

func (*ChannelsService) UpdateChannel added in v0.2.0

func (s *ChannelsService) UpdateChannel(
	ctx context.Context, eventKey, channelID string, p ChannelUpdateParams,
) (map[string]any, error)

UpdateChannel updates a private allocation channel.

type ChartCreateParams

type ChartCreateParams struct {
	Name        string
	Doc         map[string]any
	ExternalRef string
	WorkspaceID string
	// IdempotencyKey makes a retried create collapse into the original.
	IdempotencyKey string
}

ChartCreateParams describes a new chart.

type ChartListParams

type ChartListParams struct {
	WorkspaceID string
	ExternalRef string
	Archived    bool
	// Limit is the page size. Clamped server-side; asking for more is not an error.
	Limit int
	// Cursor continues a previous page. Leave empty to start.
	Cursor string
}

ChartListParams filters and pages a chart listing.

type ChartsService

type ChartsService struct {
	// contains filtered or unexported fields
}

ChartsService covers seat-map definitions that events are created from.

Even when organisers draw their own venues in the embedded Designer you need this: CreateDesignerSession requires a chart id that already exists, so the usual platform flow is copy a template here, then hand over a session.

func (*ChartsService) All

All walks every chart, paging transparently.

for chart, err := range client.Charts.All(ctx, nil) { ... }

func (*ChartsService) Archive

func (s *ChartsService) Archive(ctx context.Context, chartID string) (map[string]any, error)

Archive moves a chart to the archive.

func (*ChartsService) Copy

func (s *ChartsService) Copy(ctx context.Context, chartID string) (map[string]any, error)

Copy duplicates a chart — the usual way to provision a venue from a template.

func (*ChartsService) Create

func (s *ChartsService) Create(ctx context.Context, p ChartCreateParams) (map[string]any, error)

Create makes a chart. Pass Doc to import an existing document.

func (*ChartsService) Delete

func (s *ChartsService) Delete(ctx context.Context, chartID string) error

Delete removes a chart.

func (*ChartsService) List

func (s *ChartsService) List(ctx context.Context, p *ChartListParams) (Page, error)

List returns one page of charts.

func (*ChartsService) Publish

func (s *ChartsService) Publish(ctx context.Context, chartID string) (map[string]any, error)

Publish publishes the draft. Events can only be created from a published chart.

func (*ChartsService) Retrieve

func (s *ChartsService) Retrieve(ctx context.Context, chartID string) (map[string]any, error)

Retrieve fetches a chart and its document.

func (*ChartsService) Unarchive

func (s *ChartsService) Unarchive(ctx context.Context, chartID string) (map[string]any, error)

Unarchive restores a chart from the archive.

func (*ChartsService) Update

func (s *ChartsService) Update(
	ctx context.Context, chartID string, doc map[string]any, expectedUpdatedAt int64,
) (map[string]any, error)

Update replaces a chart document.

expectedUpdatedAt is required for optimistic concurrency and is not optional here either: without it two concurrent writers silently overwrite each other, and a seat map is exactly the document where that loses work. Read it from Retrieve immediately before writing.

The Designer is the authoring surface. Use this for bulk programmatic edits and migrations, not for drawing.

type Client

type Client struct {
	Charts     *ChartsService
	Channels   *ChannelsService
	Events     *EventsService
	Inventory  *InventoryService
	Sessions   *SessionsService
	Webhooks   *WebhooksService
	Workspaces *WorkspacesService
	// contains filtered or unexported fields
}

Client talks to the SeatLayer server API.

It is safe for concurrent use: the underlying http.Client is, and Client holds no mutable state of its own.

func New

func New(secretKey string, options ...Option) (*Client, error)

New builds a Client from a secret key.

It returns an error rather than panicking on a bad key, so a misconfigured deployment fails at startup with a message that names the problem.

func (*Client) Do

func (c *Client) Do(
	ctx context.Context,
	method, path string,
	query url.Values,
	body any,
	idempotencyKey string,
) (map[string]any, error)

Do is the escape hatch for surface this SDK does not wrap yet. It carries the same auth, retries, idempotency and error mapping as everything else.

func (*Client) Mode

func (c *Client) Mode() string

Mode reports "live" or "test", derived from the key prefix.

func (*Client) Ready

func (c *Client) Ready(ctx context.Context) (map[string]any, error)

Ready runs the dependency-aware readiness probe.

type ConflictError

type ConflictError struct{ APIError }

ConflictError is a 409 — the seats moved under you.

Normal in ticketing, not exceptional: two buyers wanted the same seat and one lost.

func (*ConflictError) Conflicts

func (e *ConflictError) Conflicts() []map[string]any

Conflicts returns the per-object conflicts, when the endpoint reports them.

func (*ConflictError) SoldOut

func (e *ConflictError) SoldOut() bool

SoldOut reports whether best-available could not find enough free inventory.

type ConnectionError

type ConnectionError struct {
	Op  string
	Err error
}

ConnectionError means the request never got an answer: DNS, TLS, socket, or a context deadline.

func (*ConnectionError) Error

func (e *ConnectionError) Error() string

func (*ConnectionError) Unwrap

func (e *ConnectionError) Unwrap() error

Unwrap lets errors.Is reach the underlying cause, so a caller can still test for context.DeadlineExceeded or a net error.

type DesignerSessionParams

type DesignerSessionParams struct {
	WorkspaceID string
	// ChartID must already exist — create or copy a chart first.
	ChartID       string
	AllowedOrigin string
	// Authority is "read-only", "edit", or "publish".
	Authority string
	// Mode is "normal" or "safe".
	Mode             string
	ExpiresInSeconds int
}

DesignerSessionParams scopes an embedded-Designer token.

type EventCreateParams

type EventCreateParams struct {
	// ChartID must reference a published chart.
	ChartID string
	Name    string
	Slug    string
	// StartsAt is epoch milliseconds.
	StartsAt    int64
	Venue       string
	ExternalRef string
	// Currency overrides the organisation currency for this event.
	Currency       string
	IdempotencyKey string
}

EventCreateParams describes a new event.

type EventListParams

type EventListParams struct {
	WorkspaceID string
	ExternalRef string
	// Limit is the page size. Clamped server-side; asking for more is not an error.
	Limit int
	// Cursor continues a previous page. Leave empty to start.
	Cursor string
	// NoCounts drops live availability counts, which cost the server one
	// round-trip per event. All sets this automatically.
	NoCounts bool
}

EventListParams filters and pages an event listing.

type EventsService

type EventsService struct {
	// contains filtered or unexported fields
}

EventsService covers event lifecycle, metadata and reports.

func (*EventsService) All

All walks every event, paging transparently.

Counts are dropped by default here — you are walking the whole list, so per-event availability is rarely what you want and always what it costs.

func (*EventsService) Archive

func (s *EventsService) Archive(ctx context.Context, eventKey string) (map[string]any, error)

Archive moves an event to the archive, preserving reporting.

func (*EventsService) Close

func (s *EventsService) Close(ctx context.Context, eventKey string) (map[string]any, error)

Close stops buyer sales. Existing holds keep their TTL.

func (*EventsService) Create

func (s *EventsService) Create(ctx context.Context, p EventCreateParams) (map[string]any, error)

Create makes an event from a published chart.

func (*EventsService) Delete

func (s *EventsService) Delete(ctx context.Context, eventKey string) error

Delete soft-deletes an event.

func (*EventsService) List

func (s *EventsService) List(ctx context.Context, p *EventListParams) (Page, error)

List returns one page of events, including live availability counts unless NoCounts is set.

func (*EventsService) Reopen

func (s *EventsService) Reopen(ctx context.Context, eventKey string) (map[string]any, error)

Reopen resumes buyer sales.

func (*EventsService) Retrieve

func (s *EventsService) Retrieve(ctx context.Context, eventKey string) (map[string]any, error)

Retrieve fetches an event with live counts.

func (*EventsService) RetrieveHoldTTL

func (s *EventsService) RetrieveHoldTTL(ctx context.Context, eventKey string) (map[string]any, error)

RetrieveHoldTTL reads the checkout window buyers get for this event.

func (*EventsService) RetrieveLog

func (s *EventsService) RetrieveLog(ctx context.Context, eventKey string) (map[string]any, error)

RetrieveLog fetches the event audit log.

func (*EventsService) RetrieveReport

func (s *EventsService) RetrieveReport(ctx context.Context, eventKey string) (map[string]any, error)

RetrieveReport fetches the event report.

func (*EventsService) Update

func (s *EventsService) Update(ctx context.Context, eventKey string, fields map[string]any) (map[string]any, error)

Update changes event metadata.

func (*EventsService) UpdateChart

func (s *EventsService) UpdateChart(ctx context.Context, eventKey string) (map[string]any, error)

UpdateChart moves a live event onto the latest published version of its chart.

func (*EventsService) UpdateHoldTTL

func (s *EventsService) UpdateHoldTTL(ctx context.Context, eventKey string, holdTTLMs int64) (map[string]any, error)

UpdateHoldTTL sets the checkout window, in milliseconds.

type HoldParams

type HoldParams struct {
	Labels []string
	// Selections is the alternative to Labels when you need a tier or a
	// quantity, e.g. a shared table or a GA area.
	Selections []map[string]any
	// TTLMs overrides the event's checkout window for this hold.
	TTLMs          int64
	ReplaceHoldID  string
	IdempotencyKey string
	// ChannelIDs grants access to private allocation inventory.
	ChannelIDs []string
	// IgnoreChannelRestrictions is a privileged backend override.
	IgnoreChannelRestrictions bool
	// Reason is written to the audit trail for channel use or an override.
	Reason string
}

HoldParams reserves specific objects by label.

type InventoryService

type InventoryService struct {
	// contains filtered or unexported fields
}

InventoryService covers holds, booking, blocking and availability.

Two complete flows, both first-class:

browser holds → RetrieveHold for authoritative pricing → charge → Book(holdId)
backend books labels directly — box office, phone sales, comps

Never price from what the browser tells you. RetrieveHold is the authoritative answer, which is why it is a separate call.

func (*InventoryService) Block

func (s *InventoryService) Block(ctx context.Context, eventKey string, labels []string) (map[string]any, error)

Block holds inventory back from sale (house seats, production holds).

func (*InventoryService) Book

func (s *InventoryService) Book(ctx context.Context, eventKey string, p BookParams) (map[string]any, error)

Book confirms a sale.

func (*InventoryService) BookBestAvailable

func (s *InventoryService) BookBestAvailable(
	ctx context.Context, eventKey string, p BestAvailableParams,
) (map[string]any, error)

BookBestAvailable picks and books in one call — the box-office shape.

Prefer this over hold-then-book when payment is already taken: a failure between two calls would strand inventory until the TTL expired.

func (*InventoryService) BoxOfficeBook

func (s *InventoryService) BoxOfficeBook(
	ctx context.Context, eventKey string, labels []string, bookingRef string,
) (map[string]any, error)

BoxOfficeBook books named objects as a box-office sale.

func (*InventoryService) ExtendHold

func (s *InventoryService) ExtendHold(
	ctx context.Context, eventKey, holdID string, ttlMs int64,
) (map[string]any, error)

ExtendHold pushes an active hold's expiry out by a fresh window.

Use this rather than release-and-re-hold when an order takes longer than the checkout window — invoiced sales, a phone order on hold. Releasing first hands the seats to whoever is racing for them in between. A hold that is gone, expired, or at its renewal cap answers 409 cannot_extend.

func (*InventoryService) Hold

func (s *InventoryService) Hold(ctx context.Context, eventKey string, p HoldParams) (map[string]any, error)

Hold reserves the named objects.

func (*InventoryService) HoldBestAvailable

func (s *InventoryService) HoldBestAvailable(
	ctx context.Context, eventKey string, p BestAvailableParams,
) (map[string]any, error)

HoldBestAvailable picks the best free objects and holds them.

The picker is the one the buyer widget uses, so a phone order and a web order get the same answer for the same inventory.

func (*InventoryService) ListBookings added in v0.2.0

func (s *InventoryService) ListBookings(
	ctx context.Context, eventKey string, p BookingListParams,
) (map[string]any, error)

ListBookings returns one page of booking lifecycle records, newest first.

func (*InventoryService) Release

func (s *InventoryService) Release(
	ctx context.Context, eventKey string, labels []string, holdID string,
) (map[string]any, error)

Release frees held objects before the TTL expires.

func (*InventoryService) RetrieveAvailability

func (s *InventoryService) RetrieveAvailability(ctx context.Context, eventKey string) (map[string]any, error)

RetrieveAvailability reads per-object availability rules.

func (*InventoryService) RetrieveBooking added in v0.2.0

func (s *InventoryService) RetrieveBooking(
	ctx context.Context, eventKey, bookingRef string,
) (map[string]any, error)

RetrieveBooking returns a booking lifecycle by its stable reference.

func (*InventoryService) RetrieveHold

func (s *InventoryService) RetrieveHold(ctx context.Context, eventKey, holdID string) (map[string]any, error)

RetrieveHold returns authoritative items and prices. Charge from this, not from what the browser sent you.

func (*InventoryService) Unblock

func (s *InventoryService) Unblock(ctx context.Context, eventKey string, labels []string) (map[string]any, error)

Unblock returns blocked objects to sale.

func (*InventoryService) UnblockAll

func (s *InventoryService) UnblockAll(ctx context.Context, eventKey string) (map[string]any, error)

UnblockAll returns every blocked object in an event to sale.

func (*InventoryService) Unbook

func (s *InventoryService) Unbook(
	ctx context.Context, eventKey string, labels []string, bookingRef string,
) (map[string]any, error)

Unbook reverses a booking. Requires a key with cancel authority.

func (*InventoryService) UpdateAvailability

func (s *InventoryService) UpdateAvailability(
	ctx context.Context, eventKey string, fields map[string]any,
) (map[string]any, error)

UpdateAvailability replaces per-object availability rules.

type ManageSessionParams

type ManageSessionParams struct {
	// AllowedOrigin is the https origin the token is bound to.
	AllowedOrigin string
	// Capabilities is required. See CreateManageSession for why.
	Capabilities []string
	// ExpiresInSeconds is 300–14400. Defaults to 3600 server-side.
	ExpiresInSeconds int
}

ManageSessionParams scopes a control-room token.

type NotFoundError

type NotFoundError struct{ APIError }

NotFoundError is a 404, including another organisation's resource.

Asking for something owned by a different organisation answers 404, never 403: a 403 would confirm the resource exists, which is not something one customer should be able to learn about another.

type Option

type Option func(*Client)

Option configures a Client.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL points the client at a different API host.

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) Option

WithHTTPClient supplies your own http.Client — for a custom transport, a proxy, or a test server. Its Timeout applies per attempt.

func WithMaxRetries

func WithMaxRetries(attempts int) Option

WithMaxRetries sets total attempts for retryable failures.

type Page

type Page struct {
	// Items are the rows on this page.
	Items []map[string]any
	// NextCursor is empty once the list is exhausted.
	NextCursor string
}

Page is one page of a list endpoint, plus the cursor for the next.

type RateLimitError

type RateLimitError struct {
	APIError
	// RetryAfter is how long to wait, in seconds.
	RetryAfter float64
}

RateLimitError is a 429. RetryAfter prefers the header over the JSON field.

type SessionsService

type SessionsService struct {
	// contains filtered or unexported fields
}

SessionsService mints short-lived, origin-bound browser tokens.

The governing rule: the SDK mints tokens, widgets consume them. Your secret key never reaches a browser.

func (*SessionsService) CreateDesignerSession

func (s *SessionsService) CreateDesignerSession(
	ctx context.Context, p DesignerSessionParams,
) (map[string]any, error)

CreateDesignerSession mints a token so an organiser can edit a chart inside your own UI.

func (*SessionsService) CreateManageSession

func (s *SessionsService) CreateManageSession(
	ctx context.Context, eventKey string, p ManageSessionParams,
) (map[string]any, error)

CreateManageSession mints a manage-session token for the control room.

Capabilities is required here even though the API defaults it. That default grants all four — including event:cancel, which un-books paid inventory. Granting the ability to reverse sales by forgetting a field is not a default worth inheriting.

func (*SessionsService) RevokeDesignerSession

func (s *SessionsService) RevokeDesignerSession(ctx context.Context, sessionID string) error

RevokeDesignerSession invalidates a designer token before it expires.

func (*SessionsService) RevokeManageSession

func (s *SessionsService) RevokeManageSession(ctx context.Context, eventKey, sessionID string) error

RevokeManageSession invalidates a manage token before it expires.

type ValidationError

type ValidationError struct{ APIError }

ValidationError is a 422 — the request was understood and rejected.

type WebhooksService

type WebhooksService struct {
	// contains filtered or unexported fields
}

WebhooksService manages webhook subscriptions. To VERIFY a delivery, see VerifyWebhook.

func (*WebhooksService) Create

func (s *WebhooksService) Create(ctx context.Context, targetURL string, events []string) (map[string]any, error)

Create registers a subscription. The response carries the signing secret once.

func (*WebhooksService) Delete

func (s *WebhooksService) Delete(ctx context.Context, webhookID string) error

Delete removes a subscription.

func (*WebhooksService) List

func (s *WebhooksService) List(ctx context.Context) (map[string]any, error)

List returns the webhook subscriptions.

func (*WebhooksService) ListDeliveries

func (s *WebhooksService) ListDeliveries(ctx context.Context, webhookID string) (map[string]any, error)

ListDeliveries returns recent delivery attempts for a subscription.

func (*WebhooksService) Update

func (s *WebhooksService) Update(ctx context.Context, webhookID string, fields map[string]any) (map[string]any, error)

Update changes a subscription.

type WorkspacesService

type WorkspacesService struct {
	// contains filtered or unexported fields
}

WorkspacesService manages workspaces, which isolate one tenant's charts and events from another's.

func (*WorkspacesService) Create

func (s *WorkspacesService) Create(
	ctx context.Context, name, externalRef, idempotencyKey string,
) (map[string]any, error)

Create provisions a workspace, typically one per tenant.

func (*WorkspacesService) List

func (s *WorkspacesService) List(ctx context.Context) (map[string]any, error)

List returns the organisation's workspaces.

func (*WorkspacesService) Retrieve

func (s *WorkspacesService) Retrieve(ctx context.Context, workspaceID string) (map[string]any, error)

Retrieve fetches one workspace.

func (*WorkspacesService) Update

func (s *WorkspacesService) Update(
	ctx context.Context, workspaceID string, fields map[string]any,
) (map[string]any, error)

Update renames, re-references, or disables a workspace.

The organisation's default workspace cannot be disabled — the API answers 409 default_workspace_required. Promote another one first.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL