SeatSquirrel
Deployment

Types Reference

All shared data structures and TypeScript types for SeatSquirrel

This page documents every data structure used by the Designer and Picker SDKs. Types are referenced from the Designer API Reference and Picker API Reference.


LayoutOutput

The root schema returned by the Designer's onSave callback and accepted by the Picker's loadLayout() method.

{
  type: 'seatSquirrelLayout',
  version: '1.0.0',
  layout: {
    sections: Section[],
    rows: Row[],
    areas?: Area[],
    tables?: Table[],
    pricingCategories: PricingCategory[],
    drawing?: Drawing,
    metadata: {
      name?: string,
      exportedAt: string,      // ISO 8601 timestamp
      dimensions: { width: number, height: number },
      currency?: string,       // ISO 4217 currency code (e.g., 'USD', 'EUR')
      locale?: string,         // BCP 47 locale code (e.g., 'en-US', 'de-DE')
      permissions?: DesignerPermissions  // Feature restrictions stored with layout
    }
  }
}

PricingCategory

Defines a pricing tier that can be assigned to seats, rows, sections, or areas.

PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: price_{16chars} (e.g., price_x7k2m9p4q1B2c3D4). Globally unique across all layouts.
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "Adult", "VIP", "Early Bird")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., pricing-vip, pricing-early_bird)
pricenumberYesPrice in your currency's smallest unit (cents)
colorstringYesHex color for visual representation
customerNotesstringNoNotes visible to customers during booking
{
  id: "price_x7k2m9p4q1B2c3D4",
  label: "VIP",
  slug: "vip",
  price: 15000,        // e.g., $150.00
  color: "#8b5cf6",
  customerNotes: "Includes complimentary drinks"
}

Section

Organizes rows and areas into named venue sections with optional hierarchy.

Full functionality coming coon

Sections are not fully implemented in SeatSquirrel yet and will be in a future version. Sections will eventually be able to recursively contain layouts eg:

//...
sections: [{
    sections: Section[],
    rows: Row[],
    areas?: Area[],
    tables?: Table[],
    pricingCategories: PricingCategory[],
    drawing?: Drawing,
}, { 
// ...
}]
//...
PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: section_{16chars} (e.g., section_a1B2c3D4e5F6g7H8). Globally unique across all layouts.
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "Orchestra", "Balcony", "Mezzanine")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., section-orchestra, section-balcony_left)
parentSectionIdstringNoParent section ID for nested hierarchy
bounds{ x, y, width, height }NoVisual bounds of the section on canvas
pricingCategoryIdsstring[]YesPricing categories for this section
entrancesstring[]NoEntrance identifiers for this section
isCollapsedbooleanNoWhether the section is collapsed in the UI
ordernumberNoDisplay order among sibling sections
colorstringNoSection color (hex)
metadataRecord<string, any>NoArbitrary key-value metadata

Row

A row of seats with positioning and labeling configuration. Seats are nested inside the row in the seats array.

PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: row_{16chars} (e.g., row_a1B2c3D4e5F6g7H8). Globally unique across all layouts.
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "A", "1", "AA")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., row-a, row-aa)
seatCountnumberYesNumber of seats in row
seatLabelType'numeric' | 'alphabetic-upper' | 'alphabetic-lower' | 'custom'YesHow seats are labeled
seatLabelStartnumber | stringNoStarting label (default: 1 or 'A')
seatLabelOrder'forward' | 'reverse'NoLabel direction
sectionIdstringNoParent section ID
entranceToUsestringNoPreferred entrance for this row
pricingCategoryIdsstring[]YesPricing categories (inherited by seats)
rowSeatsRowSeat[]YesArray of seats in this row
drawingRowDrawingYesPosition and curve data

RowDrawing

PropertyTypeRequiredDescription
startXnumberYesRow start X coordinate
startYnumberYesRow start Y coordinate
endXnumberYesRow end X coordinate
endYnumberYesRow end Y coordinate
curvenumberYesCurve factor (-1 to 1, 0 = straight)
anglenumberYesRow angle in radians
seatSpacingnumberNoCustom spacing between seats
rowLabelPlacement'start' | 'end' | 'both' | 'none'NoWhere to show row labels
seatDrawingSeatDrawingNoDefault seat color overrides

SeatDrawing

PropertyTypeRequiredDescription
fillstringNoRow seat fill color
strokestringNoRow seat stroke color

RowSeat

An individual seat within a row.

PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: rowseat_{16chars} (e.g., rowseat_a1B2c3D4e5F6g7H8). Globally unique across all layouts.
rowIdstringYesParent row ID
indexInRownumberYesPosition index within the row (0-based)
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "1", "A", "12")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., rowseat-row_a-1, rowseat-row_b-12)
pricingCategoryIdsstring[]YesAvailable pricing categories for this seat
isAvailablebooleanNoWhether seat can be booked (picker mode)
isUnbookablebooleanNoPermanently unbookable (e.g., removed seat)
isAccessiblebooleanNoWheelchair accessible
hasRestrictedViewbooleanNoHas obstructed or limited view
drawingSeatDrawingNoOptional color overrides
{
  id: "rowseat_x7k2m9p4q1B2c3D4",
  rowId: "row_d5E6f7G8h9I0j1K2",
  indexInRow: 0,
  label: "1",
  slug: "rowseat-row_a-1",
  pricingCategoryIds: ["price_x7k2m9p4q1B2c3D4"],
  isAccessible: true
}

Area

A bookable area (general admission, tables, VIP sections) with flexible pricing models.

PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: area_{16chars} (e.g., area_a1B2c3D4e5F6g7H8). Globally unique across all layouts.
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "General Admission", "VIP Lounge", "Standing Room")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., area-general_admission, area-vip_lounge)
purchaseType'multiple-customer' | 'single-customer'YesMultiple tickets vs. exclusive booking
pricingMethod'per-person' | 'as-whole'YesPrice per person or flat rate for entire area
sectionIdstringNoParent section ID
pricingCategoryIdsstring[]YesAvailable pricing categories
minOccupancynumberNoMinimum people required
maxOccupancynumberYesMaximum capacity
displayUnit'seat' | 'standing' | 'sofa' | nullNoHow capacity is labeled
entranceToUsestringNoPreferred entrance
showMaxOccupancybooleanNoShow capacity to customers
showMinOccupancybooleanNoShow minimum to customers
showOccupancyInfobooleanNoShow current availability
isUnbookablebooleanNoPermanently unavailable
isAccessiblebooleanNoWheelchair accessible
hasRestrictedViewbooleanNoHas obstructed view
currentOccupancynumberNoCurrent bookings (for availability display)
availableCountnumberNoRemaining capacity
isAvailablebooleanNoSingle-customer area: is it available?
bookedByCustomerIdstringNoSingle-customer: who booked it
lockedbooleanNoPrevent editing in designer
drawingAreaDrawingYesShape and visual properties

AreaDrawing

PropertyTypeRequiredDescription
shape'rectangle' | 'circle' | 'polygon' | 'custom'YesShape type
shapeDataAreaShapeDataYesShape-specific dimensions
fillstringYesFill color (hex)
strokestringNoStroke color
strokeWidthnumberNoStroke width in pixels
opacitynumberNoOpacity (0-1)
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
labelstringNoLabel overlay shown on area
labelFontSizenumberNoFont size for label
labelXnumberNoLabel X position (% 0-100)
labelYnumberNoLabel Y position (% 0-100)
labelColorstringNoLabel color
labelAlign'left' | 'center' | 'right'NoLabel alignment

AreaShapeData

Properties vary by shape type:

PropertyTypeUsed ByDescription
xnumberAllX position
ynumberAllY position
widthnumberrectangleWidth
heightnumberrectangleHeight
radiusnumbercircle (if equal radii)Circle radius
radiusXnumbercircle (ellipse)Horizontal radius
radiusYnumbercircle (ellipse)Vertical radius
sidesnumberpolygonNumber of sides (3-20)
pointsnumber[]customArray of [x,y,x,y,...] points
cornerRadiusnumberrectangleRounded corner radius

Table

A table with seats arranged around its perimeter. Tables are a hybrid between rows (individual bookable seats) and areas (a visible shape on the canvas).

PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: table_{16chars} (e.g., table_a1B2c3D4e5F6g7H8). Globally unique across all layouts.
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "Table 1", "VIP Table", "Corner Booth")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., table-table_1, table-vip_table)
seatCountnumberYesNumber of seats around the table
seatLabelType'numeric' | 'alphabetic-upper' | 'alphabetic-lower' | 'custom'YesHow seats are labeled
seatLabelStartnumber | stringNoStarting label (default: 1 or 'A')
seatLabelOrder'clockwise' | 'counter-clockwise'NoSeat label direction around table
purchaseType'multiple-customer' | 'single-customer'YesMultiple individual seat bookings vs. exclusive whole-table booking
pricingMethod'per-person' | 'as-whole'YesPrice per person or flat rate for the whole table
pricingCategoryIdsstring[]YesPricing categories for this table
minOccupancynumberNoMinimum number of people required
showMinOccupancybooleanNoShow min occupancy in picker (single-customer)
showMaxOccupancybooleanNoShow max occupancy (seat count) in picker (single-customer)
sectionIdstringNoParent section ID
entranceToUsestringNoPreferred entrance for this table
isUnbookablebooleanNoPermanently unavailable
isAccessiblebooleanNoWheelchair accessible
hasRestrictedViewbooleanNoHas obstructed view
isAvailablebooleanNoSingle-customer table: is it available?
bookedByCustomerIdstringNoSingle-customer table: who booked it
lockedbooleanNoPrevent editing in designer
tableSeatsTableSeat[]YesArray of seats around this table
drawingTableDrawingYesShape and visual properties

TableDrawing

PropertyTypeRequiredDescription
shape'circular' | 'rectangular'YesTable shape
xnumberYesX position
ynumberYesY position
radiusnumberNoRadius (circular tables)
widthnumberNoWidth (rectangular tables)
heightnumberNoHeight (rectangular tables)
cornerRadiusnumberNoCorner radius (rectangular tables)
fillstringYesFill color (hex)
strokestringNoStroke color
strokeWidthnumberNoStroke width
opacitynumberNoOpacity (0-1)
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
labelstringNoLabel shown on table surface
labelFontSizenumberNoFont size for label
labelColorstringNoLabel color
seatDrawingSeatDrawingNoDefault seat color overrides

TableSeat

An individual seat belonging to a table.

PropertyTypeRequiredDescription
idstringYesMachine-generated unique identifier. Format: tableseat_{16chars} (e.g., tableseat_a1B2c3D4e5F6g7H8). Globally unique across all layouts.
tableIdstringYesParent table ID
indexInTablenumberYesPosition index around the table (0-based)
labelstringYesCustomisable display label visible to end users in the Picker (e.g., "1", "A", "Seat 3")
slugstringYesURL-safe identifier for API integrations. Auto-generated from the label but fully customisable. Must be unique within each layout. (e.g., tableseat-table_1-1, tableseat-vip_table-a)
pricingCategoryIdsstring[]YesAvailable pricing categories for this seat
isAvailablebooleanNoWhether seat can be booked (picker mode)
isUnbookablebooleanNoPermanently unbookable
isAccessiblebooleanNoWheelchair accessible
hasRestrictedViewbooleanNoHas obstructed or limited view
drawingSeatDrawingNoOptional color overrides

Drawing

Visual annotations that are not bookable (decorative shapes, labels, stage outlines).

PropertyTypeRequiredDescription
backgroundColorstringNoCanvas background color
linesLine[]NoLine elements
textElementsTextElement[]NoText labels
rectanglesRectangle[]NoRectangle shapes
circlesCircle[]NoCircle/ellipse shapes
polygonsPolygon[]NoRegular polygon shapes
customShapesCustomShape[]NoFreeform shapes

Line

PropertyTypeRequiredDescription
idstringYesMachine-generated ID
pointsnumber[]Yes[x1,y1,x2,y2,...] points
strokeWidthnumberYesLine width
strokeColorstringYesLine color
strokeStyle'solid' | 'dashed' | 'dotted'YesLine style
dashArraynumber[]NoCustom dash pattern
opacitynumberYesOpacity (0-1)
labelstringNoOptional label
lockedbooleanNoPrevent editing
closedbooleanNoConnect last to first point

TextElement

PropertyTypeRequiredDescription
idstringYesMachine-generated ID
xnumberYesX position
ynumberYesY position
textstringYesText content
fontSizenumberYesFont size
colorstringYesText color
boldbooleanNoBold text
italicbooleanNoItalic text
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
widthnumberNoText box width
align'left' | 'center' | 'right'NoText alignment
lockedbooleanNoPrevent editing
labelstringNoOptional identifier

Rectangle

PropertyTypeRequiredDescription
idstringYesMachine-generated ID
xnumberYesX position
ynumberYesY position
widthnumberYesWidth
heightnumberYesHeight
fillstringYesFill color
cornerRadiusnumberYesCorner radius
strokestringNoStroke color
strokeWidthnumberNoStroke width
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
opacitynumberNoOpacity (0-1)
lockedbooleanNoPrevent editing
labelstringNoDisplay label
labelFontSizenumberNoLabel font size
labelXnumberNoLabel X offset
labelYnumberNoLabel Y offset
labelColorstringNoLabel color
labelAlign'left' | 'center' | 'right'NoLabel alignment

Circle

Supports both circles (equal radii) and ellipses (different radiusX/radiusY).

PropertyTypeRequiredDescription
idstringYesMachine-generated ID
xnumberYesCenter X position
ynumberYesCenter Y position
radiusXnumberYesHorizontal radius
radiusYnumberYesVertical radius
fillstringYesFill color
strokestringNoStroke color
strokeWidthnumberNoStroke width
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
opacitynumberNoOpacity (0-1)
lockedbooleanNoPrevent editing
labelstringNoDisplay label
labelFontSizenumberNoLabel font size
labelXnumberNoLabel X offset
labelYnumberNoLabel Y offset
labelColorstringNoLabel color
labelAlign'left' | 'center' | 'right'NoLabel alignment

Polygon

Regular polygons (triangles, hexagons, etc.).

PropertyTypeRequiredDescription
idstringYesMachine-generated ID
xnumberYesCenter X position
ynumberYesCenter Y position
radiusnumberYesDistance to vertices
sidesnumberYesNumber of sides (3-20)
fillstringYesFill color
strokestringNoStroke color
strokeWidthnumberNoStroke width
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
opacitynumberNoOpacity (0-1)
lockedbooleanNoPrevent editing
labelstringNoDisplay label
labelFontSizenumberNoLabel font size
labelXnumberNoLabel X offset
labelYnumberNoLabel Y offset
labelColorstringNoLabel color
labelAlign'left' | 'center' | 'right'NoLabel alignment

CustomShape

Freeform shapes defined by arbitrary points.

PropertyTypeRequiredDescription
idstringYesMachine-generated ID
xnumberYesOrigin X position
ynumberYesOrigin Y position
pointsnumber[]Yes[x1,y1,x2,y2,...] points
fillstringYesFill color
strokestringNoStroke color
strokeWidthnumberNoStroke width
rotationnumberNoRotation in degrees
scaleXnumberNoHorizontal scale
scaleYnumberNoVertical scale
opacitynumberNoOpacity (0-1)
lockedbooleanNoPrevent editing
labelstringNoDisplay label
labelFontSizenumberNoLabel font size
labelXnumberNoLabel X offset
labelYnumberNoLabel Y offset
labelColorstringNoLabel color
labelAlign'left' | 'center' | 'right'NoLabel alignment

DesignerPermissions

Configuration object to control which features are enabled in the Designer. All fields are optional — omitted fields default to enabled (true).

Used with the permissions option in the Designer constructor to restrict functionality (e.g., pre-supply pricing categories and prevent users from creating/editing them).

Key Principle: Default to full access. Permissions are opt-in restrictions, not opt-in grants.

PropertyTypeDefaultDescription
readOnlybooleanfalseGlobal read-only mode — disables all editing
assignmentOnlybooleanfalsePricing assignment-only mode — blocks structural/visual edits while allowing pricing assignment
toolsobjectTool-level permissions (see below)
propertiesobjectProperties panel permissions (see below)

tools

PropertyTypeDefaultDescription
rowbooleantrueAllow seat row creation tool
tablebooleantrueAllow table creation tools
areabooleantrueAllow area creation tools
shapebooleantrueAllow shape tools (rectangle, circle, polygon, custom, line)
textbooleantrueAllow text creation tool
traceImagebooleantrueAllow trace image upload tool

properties

PropertyTypeDefaultDescription
showPropertiesbooleantrueShow greyed-out (non-editable) properties when an element is selected in readOnly or assignmentOnly mode. Set false to hide properties entirely (restoring pre-1.4 behavior).
settingsTabbooleantrueAllow access to the Settings tab in Properties Panel
pricingCategoriesCrudbooleantrueAllow creating/editing/deleting pricing categories
currencySettingsbooleantrueAllow changing currency and locale settings

warnings

PropertyTypeDefaultDescription
pricingCategoriesAssignmentSaveWarningbooleantrueShow warning when rows, areas, or tables don't have pricing categories assigned
pricingCategoriesAssignmentPanelWarningbooleantrueShow "Missing Pricing Categories" warning in the properties panel when nothing is selected
// Example: All permissions with defaults shown
{
  readOnly: false,
  assignmentOnly: false,
  tools: {
    row: true,
    table: true,
    area: true,
    shape: true,
    text: true,
    traceImage: true
  },
  properties: {
    showProperties: true,
    settingsTab: true,
    pricingCategoriesCrud: true,
    currencySettings: true
  },
  warnings: {
    pricingCategoriesAssignmentSaveWarning: true,
    pricingCategoriesAssignmentPanelWarning: true
  }
}

readOnly takes precedence over assignmentOnly when both are set to true.


SelectionData

The data structure returned by onSelectionChanged and onComplete callbacks. Each item in the selections array is one of four subtypes: RowSeatSelection, AreaSelection, TableSeatSelection, or WholeTableSelection.

PropertyTypeDescription
selectionsSelectionItem[]Array of selection items — see subtypes below
totalsobject{ count: number, amount: number }
{
  selections: [
    { type: 'row-seat', ... },
    { type: 'area', ... },
    { type: 'table-seat', ... },
    { type: 'whole-table', ... }
  ],
  totals: {
    count: 5,        // Total items selected
    amount: 25000    // Total price in cents (e.g., $250.00)
  }
}

RowSeatSelection

Returned when a user selects a seat.

PropertyTypeRequiredDescription
idstringYesUnique seat identifier
type'row-seat'YesDiscriminator for selection type
rowIdstringYesParent row identifier
rowLabelstringYesRow label (e.g., "A", "1")
seatLabelstringYesSeat label (e.g., "1", "12")
slugstringYesSeat slug
rowSlugstringYesRow slug
sectionIdstringNoSection identifier
sectionNamestringNoSection display name
sectionSlugstringNoSection slug
categoryIdstringYesSelected pricing category ID
categoryLabelstringNoPricing category display label
categorySlugstringNoPricing category slug
pricenumberYesPrice in cents

AreaSelection

Returned when a user selects spots in an area.

PropertyTypeRequiredDescription
idstringYesUnique area identifier
type'area'YesDiscriminator for selection type
areaLabelstringYesArea display label
slugstringYesArea slug
sectionIdstringNoSection identifier
sectionNamestringNoSection display name
sectionSlugstringNoSection slug
categoryIdstringYesSelected pricing category ID
categoryLabelstringNoPricing category display label
categorySlugstringNoPricing category slug
quantitynumberYesNumber of spots selected
pricePerUnitnumberYesPrice per spot in cents
totalPricenumberYesTotal price in cents (quantity x pricePerUnit)

TableSeatSelection

Returned when a user selects an individual seat at a table (multiple-customer purchase type).

PropertyTypeRequiredDescription
idstringYesUnique table seat identifier
type'table-seat'YesDiscriminator for selection type
tableIdstringYesParent table identifier
tableLabelstringYesTable display label
seatLabelstringYesSeat label within the table
slugstringYesTable seat slug
tableSlugstringYesTable slug
sectionIdstringNoSection identifier
sectionNamestringNoSection display name
sectionSlugstringNoSection slug
categoryIdstringYesSelected pricing category ID
categoryLabelstringNoPricing category display label
categorySlugstringNoPricing category slug
pricenumberYesPrice in cents

WholeTableSelection

Returned when a user books an entire table (single-customer purchase type).

PropertyTypeRequiredDescription
idstringYesUnique table selection identifier
type'whole-table'YesDiscriminator for selection type
tableIdstringYesTable identifier
tableLabelstringYesTable display label
tableSlugstringYesTable slug
sectionIdstringNoSection identifier
sectionNamestringNoSection display name
sectionSlugstringNoSection slug
categoryIdstringYesSelected pricing category ID
categoryLabelstringNoPricing category display label
categorySlugstringNoPricing category slug
quantitynumberYesNumber of people / units selected
pricePerUnitnumberYesPrice per unit in cents
totalPricenumberYesTotal price in cents (quantity x pricePerUnit)

Availability by ID

Set availability using machine-generated IDs. Used with setAvailability({ mode: 'by-id', ... }).

PropertyTypeDescription
rowSeatsRecord<string, boolean>Map of seat ID to availability (true = available)
areasRecord<string, number | boolean>Map of area ID to available count (number), or boolean (true = 1, false = 0)
tableSeatsRecord<string, boolean>Map of table seat ID to availability
tablesRecord<string, boolean>Map of table ID to availability (true = available)
picker.setAvailability({
  mode: 'by-id',
  rowSeats: {
    "rowseat_a1B2c3D4e5F6g7H8": true,
    "rowseat_h8G7f6E5d4C3b2A1": false
  },
  areas: {
    "area_j9K0l1M2n3O4p5Q6": 50,
    "area_x1Y2z3A4b5C6d7E8": false  // boolean: false = 0 (unavailable)
  },
  tables: {
    "table_x1Y2z3": false
  }
});

Availability by Slug

Set availability using user-defined slugs. Used with setAvailability({ mode: 'by-slug', ... }). Recommended.

PropertyTypeDescription
rowSeatsRecord<string, boolean>Map of seat slug to availability
areasRecord<string, number | boolean>Map of area slug to available count (number), or boolean (true = 1, false = 0)
tableSeatsRecord<string, boolean>Map of table seat slug to availability
tablesRecord<string, boolean>Map of table slug to availability (true = available)
picker.setAvailability({
  mode: 'by-slug',
  rowSeats: {
    "row-a-seat-1": false,
    "row-a-seat-2": true
  },
  areas: {
    "standing-room": 50,
    "vip-lounge": 0,
    "private-booth": false  // boolean: false = 0 (unavailable)
  },
  tables: {
    "vip-table-1": false
  }
});

Availability by Labels

Set availability using display labels. Used with setAvailability({ mode: 'dangerously-by-labels', ... }).

⚠️ Warning: Labels can clash if duplicated across sections. Prefer slugs.

SeatAvailabilityByLabel

PropertyTypeRequiredDescription
sectionIdstringNoSection ID (required if row/seat is ambiguous)
rowLabelstringYesRow label (e.g., "A", "1")
seatLabelstringYesSeat label (e.g., "1", "12")
isAvailablebooleanYesWhether the seat is available

AreaAvailabilityByLabel

PropertyTypeRequiredDescription
sectionIdstringNoSection ID (required if area name is ambiguous)
areaLabelstringYesArea label as defined in the layout
availableCountnumber | booleanYesNumber of available spots (0 = sold out), or boolean (true = 1, false = 0)

TableAvailabilityByLabel

PropertyTypeRequiredDescription
sectionIdstringNoSection ID (required if table name is ambiguous)
tableLabelstringYesTable label as defined in the layout
isAvailablebooleanYesWhether the table is available
picker.setAvailability({
  mode: 'dangerously-by-labels',
  rowSeats: [
    { rowLabel: "A", seatLabel: "1", isAvailable: false },
    { rowLabel: "A", seatLabel: "2", isAvailable: true }
  ],
  areas: [
    { areaLabel: "Standing Room", availableCount: 50 }
  ],
  tables: [
    { tableLabel: "VIP Table", isAvailable: false }
  ]
});

Pricing Category Partial Update by ID

Partially update pricing categories using machine-generated IDs. Used with updatePricingCategoriesById(). Merges provided fields into matching categories — unmentioned categories are untouched. All-or-nothing: if any ID doesn't match, the call fails with no changes.

PropertyTypeRequiredDescription
pricingCategoriesArray<{ id, ...fields }>YesArray of category partial updates

Partial Update Object (by ID)

PropertyTypeRequiredDescription
idstringYesCategory ID (must match existing category)
labelstringNoNew display label
slugstringNoNew slug
pricenumberNoNew price in cents
colorstringNoNew hex color
customerNotesstringNoNew customer notes
picker.updatePricingCategoriesById({
  pricingCategories: [
    { id: "price_a1B2c3D4e5F6g7H8", price: 7500, label: "Standard (updated)" },
    { id: "price_h8G7f6E5d4C3b2A1", color: "#10B981" }
  ]
});

Pricing Category Partial Update by Slug

Partially update pricing categories using user-defined slugs. Used with updatePricingCategoriesBySlug(). Recommended. Merges provided fields into matching categories — unmentioned categories are untouched. All-or-nothing: if any slug doesn't match, the call fails with no changes.

Note: The slug field is used only for matching — it is not merged into the category. To change a slug, use updatePricingCategoriesById and pass slug as an update field.

PropertyTypeRequiredDescription
pricingCategoriesArray<{ slug, ...fields }>YesArray of category partial updates

Partial Update Object (by Slug)

PropertyTypeRequiredDescription
slugstringYesCategory slug (used for matching only, not merged)
labelstringNoNew display label
pricenumberNoNew price in cents
colorstringNoNew hex color
customerNotesstringNoNew customer notes
picker.updatePricingCategoriesBySlug({
  pricingCategories: [
    { slug: "standard", price: 7500, label: "Standard (updated)" },
    { slug: "vip", color: "#10B981" }
  ]
});

AssignPricingCategoriesInput

Input for assignPricingCategories() on both the Designer and Picker APIs. Allows programmatic assignment of pricing categories to layout objects. Uses a mode discriminator to control how objects and categories are identified.

Atomic semantics: If any assignment fails validation, none are applied.

PropertyTypeRequiredDescription
mode'by-id' | 'by-slug' | 'dangerously-by-labels'YesHow to identify objects and categories

Mode: 'by-id'

Each property is a Record<objectId, categoryId[]> map:

PropertyTypeRequiredDescription
rowsRecord<string, string[]>NoMap of row ID to category IDs
rowSeatsRecord<string, string[]>NoMap of seat ID to category IDs
areasRecord<string, string[]>NoMap of area ID to category IDs
tablesRecord<string, string[]>NoMap of table ID to category IDs
tableSeatsRecord<string, string[]>NoMap of table seat ID to category IDs

Mode: 'by-slug'

Same shape as 'by-id', but keys are user-defined slugs for both objects and categories.

Mode: 'dangerously-by-labels'

Each property is an array of label-based entries. Categories are always referenced by slug.

PropertyTypeRequiredDescription
rowsArray<{ sectionId?, rowLabel, pricingCategorySlugs }>NoRow assignments by label
rowSeatsArray<{ sectionId?, rowLabel, seatLabel, pricingCategorySlugs }>NoSeat assignments by label
areasArray<{ sectionId?, areaLabel, pricingCategorySlugs }>NoArea assignments by label
tablesArray<{ sectionId?, tableLabel, pricingCategorySlugs }>NoTable assignments by label
tableSeatsArray<{ sectionId?, tableLabel, seatLabel, pricingCategorySlugs }>NoTable seat assignments by label
// By slug (recommended)
{
  mode: 'by-slug',
  rows: {
    'row-a': ['vip', 'standard'],
    'row-b': ['standard'],
  },
  areas: {
    'vip-lounge': ['vip'],
  }
}

// By ID
{
  mode: 'by-id',
  rows: {
    'row-uuid-1': ['cat-uuid-1', 'cat-uuid-2'],
  },
  areas: {
    'area-uuid-1': ['cat-uuid-2'],
  }
}

// Dangerously by labels
{
  mode: 'dangerously-by-labels',
  rows: [
    { rowLabel: 'A', pricingCategorySlugs: ['vip', 'standard'] },
    { sectionId: 'section-uuid', rowLabel: 'A', pricingCategorySlugs: ['economy'] },
  ]
}

AssignPricingCategoriesResult

Result returned by assignPricingCategories(). Uses atomic semantics — if any assignment fails validation, none are applied and all errors are returned.

PropertyTypeDescription
successbooleantrue if all assignments applied, false if any validation failed
errorsstring[]Present when success is false. Lists all validation errors (e.g., unknown object slug, unknown category ID)
// Success
{ success: true }

// Failure — no assignments applied
{
  success: false,
  errors: [
    'No object found with slug "nonexistent-row"',
    'No pricing category found with slug "unknown-category"'
  ]
}

Complete Example

A full LayoutOutput JSON showing all structures together:

{
  type: 'seatSquirrelLayout',
  version: '1.0.0',
  layout: {
    sections: [{
      id: 'section_a1B2c3D4e5F6g7H8',
      label: 'Orchestra',
      slug: 'section-orchestra',
      pricingCategoryIds: ['price_v1I2p7R8s9T0u1W2', 'price_s3T4d5A6n7D8r9E0']
    }],
    rows: [{
      id: 'row_d5E6f7G8h9I0j1K2',
      label: 'A',
      slug: 'row-a',
      seatCount: 10,
      seatLabelType: 'numeric',
      seatLabelStart: 1,
      sectionId: 'section_a1B2c3D4e5F6g7H8',
      pricingCategoryIds: ['price_v1I2p7R8s9T0u1W2'],
      drawing: {
        startX: 100,
        startY: 200,
        endX: 400,
        endY: 200,
        curve: 0.1,
        angle: 0
      },
      seats: [
        {
          id: 'rowseat_x7k2m9p4q1B2c3D4',
          rowId: 'row_d5E6f7G8h9I0j1K2',
          indexInRow: 0,
          label: '1',
          slug: 'rowseat-row_a-1',
          pricingCategoryIds: ['price_v1I2p7R8s9T0u1W2']
        }
        // ... more seats
      ]
    }],
    areas: [{
      id: 'area_g1H2i3J4k5L6m7N8',
      label: 'General Admission',
      slug: 'area-general_admission',
      purchaseType: 'multiple-customer',
      pricingMethod: 'per-person',
      pricingCategoryIds: ['price_s3T4d5A6n7D8r9E0'],
      maxOccupancy: 200,
      displayUnit: 'standing',
      drawing: {
        shape: 'rectangle',
        shapeData: { x: 500, y: 100, width: 300, height: 200 },
        fill: '#e5e7eb'
      }
    }],
    tables: [{
      id: 'table_t1A2b3L4e5S6e7A8',
      label: 'Table 1',
      slug: 'table-table_1',
      seatCount: 6,
      seatLabelType: 'numeric',
      seatLabelStart: 1,
      purchaseType: 'multiple-customer',
      pricingMethod: 'per-person',
      pricingCategoryIds: ['price_s3T4d5A6n7D8r9E0'],
      sectionId: 'section_a1B2c3D4e5F6g7H8',
      drawing: {
        shape: 'circular',
        x: 600,
        y: 400,
        radius: 40,
        fill: '#d1d5db'
      },
      seats: [
        {
          id: 'tableseat_p1Q2r3S4t5U6v7W8',
          tableId: 'table_t1A2b3L4e5S6e7A8',
          indexInTable: 0,
          label: '1',
          slug: 'tableseat-table_1-1',
          pricingCategoryIds: ['price_s3T4d5A6n7D8r9E0']
        }
        // ... more seats
      ]
    }],
    pricingCategories: [
      { id: 'price_v1I2p7R8s9T0u1W2', label: 'VIP', slug: 'vip', price: 15000, color: '#8b5cf6' },
      { id: 'price_s3T4d5A6n7D8r9E0', label: 'Standard', slug: 'standard', price: 5000, color: '#3b82f6' }
    ],
    drawing: {
      backgroundColor: '#ffffff',
      rectangles: [{
        id: 'rect_j1K2l3M4n5O6p7Q8',
        x: 200,
        y: 50,
        width: 200,
        height: 60,
        fill: '#1f2937',
        cornerRadius: 4,
        label: 'STAGE',
        labelColor: '#ffffff',
        labelFontSize: 24,
        labelAlign: 'center'
      }],
      textElements: [{
        id: 'text_m1N2o3P4q5R6s7T8',
        x: 50,
        y: 400,
        text: 'EXIT',
        fontSize: 16,
        color: '#ef4444'
      }]
    },
    metadata: {
      name: 'Main Theater',
      exportedAt: '2024-01-15T10:30:00.000Z',
      dimensions: { width: 800, height: 600 },
      currency: 'USD',
      locale: 'en-US',
      permissions: {
        properties: { pricingCategoriesCrud: false }
      }
    }
  }
}