Packages
The sellable unit is a package: a seller-defined, versioned description of inventory. Switchboard never forces packages into a fixed vocabulary; it makes whatever the seller defines legible and safe to transact.
Package types
daypart (a selling title plus days and a time window, see Selling titles), program (a show or tentpole), genre (a content collection), rotator (rotation rules across windows), ron (run of network), sponsorship (all or part of a program bought by one advertiser), and custom. Each carries a type-appropriate definition and the same versioning; the full shape is the package object, and the wire values live at the package type enum. A program that airs on irregular dates (a game schedule, an awards night, a premiere) may define itself by explicit occurrences (date, start, end, optional label) instead of a weekly pattern; slots then exist only on those dates, and everything else about slots, weekly pricing, and ordering is unchanged.
Slots
A slot is a package on a date: the orderable instance. Slot IDs are constructed, never looked up: {package_id}:{date}, so acme-prime:2026-10-07 is Prime on October 7. A slot inherits the rate entries of its ISO week; there is no per-date pricing. The grain rule in one sentence: cards price by week, trades book by slot. Order a slot and the air date is pinned (daylocked by construction); order a package and week instead and the seller distributes your units across its slots, reported per date in the line's allocation.
Distribution
A package may declare the layer its inventory sits in: network (the national commercial load carried at once across owned-and-operated and affiliated stations), syndication (time inside a program licensed for national distribution that airs on individual local stations), or spot (time sold by an individual station or system). Omitted means unstated, which stays valid. Buyers filter catalog reads with ?distribution=syndication; the wire values live at the distribution enum.
Geography is not part of this enum, because geography is already on market. spot with no market is a national spot offering; spot with a market is local. That composition is why there are three values and not five, and it is why there is no local_spot: cross-producing distribution with geography would give two fields the same job and let them drift.
Competitive separation
Two fields, deliberately on different objects, and keeping them apart is the point: advertiser_class prices; advertiser_category separates. advertiser_class (general, dr, tune_in, competitive, theatrical, political) answers what rate and clearance policy applies. advertiser_category, a named key in the order's buyer_metadata, answers what the advertiser sells, which is what separation runs on. It is an open string: no category taxonomy is standard across sellers, and pretending otherwise would be worse than not trying.
A package states the seller's own rule in separation_policy: min_separation_seconds and a scope of break, pod, or program. Length-dependent rights (published policy commonly grants product protection to :30s and withholds it from independent :15s) ride the seller's stated rule, not a rule the platform imposes. Switchboard records and surfaces both facts so the seller can see them at the approval gate; it does not place spots within a break, so enforcement stays the seller's, exactly as it is today.
Sponsorships and billboards
A sponsorship is the purchase of all or part of a program by one advertiser. It is a package type rather than a buy type, because it says what is being bought, not what the seller stands behind: a sponsorship composes with non_preemptible or fixed_position like any other package.
A billboard is a sponsorship package carrying a billboard block: seconds (typically 3, 5, or 10) and position (open, close, or both). A billboard is not a spot with a short spot_length, and the difference is contractual: published seller policy ties billboard eligibility to the commercial weight a buyer has purchased and excludes :15s from earning them. It is a benefit attached to a schedule, not a small unit of time.
Roadblocks, piggybacks, and bookending get no type of their own. A roadblock is an all-or-nothing multi-package booking; piggyback and bookending are trafficking arrangements of two creatives inside one purchased unit. An infomercial is a spot_length of 1800 with the dr advertiser class.
The catalog integrity rule
On every catalog or rate-card update: for each network and week, no two packages in one seller's catalog in state Available may overlap in days-intersect-time, unless every package in the overlapping set declares the same shared pool. Overlapping definitions are legitimate (alternate packaging, quarter-over-quarter replacement); overlapping active coverage outside a shared pool is the error, and it rejects the update with a conflict report before it can ever produce an order error.
pool: acme-prime-breaks: legal, they share one capacity. Two different sellers overlapping on the same network and week: not an oversell, and not an error.Shared pools
Sellers often sell the same breaks through more than one package: a broad Prime rotator and a weekend sports carve-out of the same inventory, each entitled to only so much of it. A pool makes that legal and keeps it honest. The pool declares shared capacity on a network; each member package opts in with an inventory_pool block naming the pool_id and its own max_per_week cap. The full shape lives at the pool object.
{
"pool_id": "acme-prime-breaks",
"network": "ACME",
"unit": "spots",
"capacity": {
"grain": "week",
"per_week": 80
},
"effective": {
"start": "2026-09-28",
"end": "2026-12-27"
}
}
Member packages draw down one shared capacity. A package never sells past its own max_per_week, and the pool never sells past its capacity. Caps may add up to more than the pool (60 + 30 over a pool of 80 is the point: whichever package sells first gets the room). Avails on a pooled package report available as the smaller of the package's remaining cap and the pool's remaining capacity. An order that would breach either rejects with INVENTORY_UNAVAILABLE and names the pool in details.pool_id; there is no new error to handle. Packages that overlap without declaring the same pool still reject at ingest with DAYPART_CONFLICT.
The reference is validated, not trusted: inventory_pool.pool_id must resolve at ingest to a pool you have published on the same network, with a matching unit and an effective window covering the overlapping weeks. A nonexistent, expired, cross-network, or unit-incompatible pool reference rejects the update with a conflict report, the same way undeclared overlap does. A shared label with no real pool behind it never turns the integrity rule off.
Mirrors
Any package whose definition carries a day-and-time window (a daypart, or a sponsorship) may declare a paired mirror airing: a second window at a fixed offset from the primary, sold alongside it. A common rate-card shape is Prime 8P-12A with a 12A-4A mirror. The package definition carries an optional mirror attribute with offset_minutes; buyers opt in per line item with include_mirror. Mirrors do not change the integrity rule: the mirror window belongs to its package and is checked like any other coverage.
Markets
A package may carry a market block naming the geography it sells: scheme (an open enum: nielsen_dma, msa, cable_zone, country, custom), code, name, and country. A package with no market is national. A local station lists as its own network with its packages carrying the station's market; a station group lists every station under one provider; a cable interconnect is a bookable network whose zone-level packages carry scheme: cable_zone. Buyers filter catalog and avails with ?market=nielsen_dma:501. Market of sale and country of license are separate facts, so cross-border inventory declares both honestly.