Objects reference
The shapes that recur across the API, each with its full field reference. This page is the canonical definition of every object; endpoint pages link here instead of redefining shapes. How the objects relate: the object model.
Reading the tables
- A required badge marks fields the API rejects without; no badge means optional. Some fields are alternatives: the description names the choice.
- Enumerated values live once, in Enumerations. Open enums may grow; treat unknown values as pass-through.
- All timestamps are UTC. Local time ranges resolve against the seller's declared timezone at ingest.
product
The sellable unit: seller-defined, versioned, date-bounded. Selling-title definitions are versioned data with effective windows, never enums: the version is the taxonomy_version declared once on the catalog update envelope, which is atomic and publishes exactly one version, so the product itself carries no copy. The order pins the version in force at its creation. Concept: Products.
{
"product_id": "acme-prime",
"type": "daypart",
"network": "ACME",
"provider": "National ACME",
"definition": {
"selling_title": "Prime",
"days": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
"start": "20:00",
"end": "23:00",
"timezone": "America/New_York",
"sample_programming": ["Acme Tonight", "Prime Movie"],
"mirror": {
"offset_minutes": 240
}
},
"effective": {
"start": "2026-09-28",
"end": "2026-12-27"
},
"currencies": ["hh", "p2plus", "a25_54"],
"buy_types": ["preemptible", "non_preemptible", "fixed_position", "audience_guaranteed"],
"spot_lengths": [15, 30, 60],
"advertiser_classes": ["general", "dr", "tune_in", "competitive", "theatrical"],
"grains": ["day", "week"],
"reporting_dayparts": ["primetime", "weekend"],
"disclosure": {
"avails_policy": "published",
"pricing_policy": "published"
},
"market": {
"scheme": "nielsen_dma",
"code": "501",
"name": "New York",
"country": "US"
},
"distribution": "network",
"separation_policy": {
"min_separation_seconds": 900,
"scope": "break"
},
"posting_policy": {
"aggregation_weeks": 4,
"threshold_pct": 90
},
"visibility": "open"
}
| Field | Type | Description |
|---|---|---|
product_id required | string | Stable identifier. Maps to the EDI product code on delivered orders. |
type required | enum | One of the product types. Tentpoles are programs. |
network required | string | The channel. |
provider required | string | The bookable entity. Multi-network sellers carry both: provider books, network airs. |
definition required | object | What the product covers. Shape varies by type; fields below. |
effective.start, effective.end required | ISO date | The product's active window. Holiday variants are just versions. |
currencies required | array of string | The audience codes the product trades and measures in. Unit counts are not listed: every product books and settles spot counts by construction, and spots is a settlement basis rather than an audience, so it never appears here. May be empty on a product that trades on unit counts alone. |
buy_types required | array of string | Offered buy types. |
spot_lengths | array of integer | Supported creative lengths in seconds. |
advertiser_classes | array of string | Accepted advertiser classes. Seller-defined; open. |
grains | array of enum | The purchase grains this product instantiates at. Omitted reads as ["week"]. A line naming a grain absent from this list is refused 422 GRAIN_NOT_OFFERED: the seller decides what it is willing to sell a month of, and a buyer cannot mint the grain by asking for it. See period. |
reporting_dayparts | array of enum | How VAMOS files this product for comparison across sellers: one or more reporting dayparts, seller-selected at publish. Descriptive only. Nothing validates these against the product's own definition times and nothing prices on them: the definition is what the seller sells, this is how VAMOS categorizes it. Omitted means uncategorized. A value outside the six is refused at publish, named in the ingest report. |
disclosure | object | How much the product reveals: avails_policy (one of the avails policies) and pricing_policy (one of the pricing policies). Both default to published; overridable per agreement. See Disclosure. |
market | object | Geography. Omitted means national. Fields below. |
distribution | enum | The layer the inventory sits in: one of the distributions. Omitted means unstated. Independent of market: spot with no market is national spot, spot with a market is local. See Distribution. |
separation_policy | object | The seller's stated competitive-separation rule: min_separation_seconds and a scope of break, pod, or program. Recorded and surfaced, not scheduled around: advertiser_class prices, the advertiser record's category separates. See Competitive separation. |
posting_policy | object | When an audience shortfall owes a make-good; fields below. Overridable per agreement; the effective policy is resolved per line at order create and frozen by value with the order, exactly as cancellation_terms is, so a later product or agreement change never alters a booked order's terms. Never order-wide. See Posting policy. |
billboard | object | Only on type: "sponsorship": seconds (typically 3, 5, or 10) and position (open, close, or both). A billboard is a benefit attached to a schedule, not a spot with a short spot_length. Structured and informational: nothing validates, prices, or settles on it today, and the structure stays anyway because it identifies what is being sold at the approval gate; it earns validation the day a trafficking flow acts on it. See Sponsorships and billboards. |
unpriced | array of object | Read-side and derived, on catalog reads only: one {axis: value} pair per declared value (a spot_length, a buy_type, an advertiser_class, a currencies audience code) that no rate entry on the card as resolved for this buyer prices anywhere in the product's effective window, so a buyer can tell offered from merely declared. Read the axis, not just the field: an unpriced spot_length, buy_type, or advertiser_class cannot be ordered, while an unpriced currency only withdraws the audience guarantee in that currency and leaves whatever else the card prices orderable. The exact per-axis rule and the card-resolution rule live on the catalog page. Absent when everything declared is priced. Never written; the same fact reaches the seller as an UNPRICED_DECLARATION warning at catalog commit, checked against the standing open commit. |
external_ref | string | The seller's own key for this product, opaque to the platform and never validated. Unique per seller across its products: a publish whose resulting catalog puts one ref on two products is refused 422 DUPLICATE_EXTERNAL_REF naming both, as a whole-request refusal, because uniqueness is a property of the catalog rather than of any one entry. Seller-only: it is present on the seller's own reads and absent from every buyer-facing catalog read. Not a second product_id: product_id is the platform's stable handle, on every avail, rate entry, and order line, while this is the seller's mutable one, so reorganizing internal codes never invalidates a booked order's key. |
visibility | enum | open or by_agreement. Omitted reads as open, which lists the product for every buyer. by_agreement lists it only for a buyer whose agreement grants it, through that agreement's catalog_scope. See who can see a product. |
The product states the axis; the relationship states who. visibility says whether a product needs a relationship at all, and agreement.catalog_scope says which buyers have one. Two fields, one answer each, and neither can contradict the other because neither can say what the other says. Disclosure is a separate axis again: visibility decides whether a buyer may see a product, disclosure decides what they see of it once listed.
posting_policy
| Field | Type | Description |
|---|---|---|
aggregation_weeks required | integer | The window delivery totals over before shortfall is computed. Four is the industry-recommended figure; the field carries whatever the parties agreed. |
threshold_pct required | number | Delivery at or above this percentage of the guarantee owes no make-good. Inclusive at the edge. |
exclusions | array of string | product_id references the policy does not cover: the tentpole carve-out, where one event's delivery is negotiated on its own. |
definition, one variant per type
definition is polymorphic on the product's type, and each variant has its own requirements: a single field table marking only timezone required would be false of every variant (a daypart with no selling_title is a documented 422). Two fields are shared by every variant: timezone required (IANA, what local times resolve against at ingest) and optional mirror.offset_minutes (a paired mirror airing at a fixed offset, the "8P-12A with 12A-4A mirror" pattern; order lines opt in with include_mirror).
type | Variant fields |
|---|---|
daypart | selling_title required (the seller's own title; see Selling titles), days[] required (Mon through Sun), start, end required (local HH:MM), optional sample_programming[]. |
program | selling_title required, then one of two schedule shapes: days/start/end for a program airing on a weekly pattern, or occurrences[] ({date, start, end, label?}, each required but label) for event-dated programs. With occurrences, the product airs only on those dates. Tentpoles are programs. |
genre | genre_ref required: the content collection the product draws from, plus optional sample_programming[]. |
rotator | selling_title required, windows[] required (each {days, start, end}: the rotation's windows), sample_programming[] required, so buyers see representative titles behind a rotation. |
ron | sample_programming[] required; run of network needs no schedule shape, the network is the schedule. |
sponsorship | The daypart shape (selling_title, days, start, end, all required): a sponsorship attaches to a program's schedule. The billboard block rides on the product, not here. |
custom | Seller-defined: selling_title required, any schedule shape above. Includes agreement-scoped products minted from proposals. |
market
| Field | Type | Description |
|---|---|---|
scheme required | enum | One of the market schemes. |
code required | string | The market code within the scheme, for example DMA 501. |
name | string | Display name. |
country | string | ISO country code. |
period
One purchase period: the grain plus the period's own start token. The format of start is decided by the grain and nothing else, which is what makes the pair self-describing: no token can be read as two different grains, so a period cannot mean two things. A product says which grains it offers in grains; a line item and an avail entry each name exactly one period.
{ "grain": "week", "start": "2026-W41" }
| Field | Type | Description |
|---|---|---|
grain required | enum | One of the period grains. |
start required | string | YYYY-MM-DD at day, ISO YYYY-Www at week, YYYY-MM at month. A start in another grain's format is refused rather than coerced. |
Cards price by week; trades book by period. A rate card keys on (product, week) whatever grain a line books at, and a line locks exactly one rate holding across its whole period. That is why a product offering month has to price each month uniformly: a month whose weeks carry two prices for one cell has no single rate a month line could lock, and the catalog publish refuses it 409 GRAIN_CONFLICT.
rate entry
One priced cell of a rate card commit: (product, week) by advertiser class, length, buy type, clearance tier, and market class. Concept: Rates.
The write shape and the read shape differ over week, deliberately, and each has a name. A rate card entry input, what PUT /me/rate-cards takes, states week optionally: omit it and the entry holds across the commit's whole effective window. A rate entry, what every read surface returns and what this table defines, always carries its week: the platform materialises a spanning input into one entry per ISO week of the effective window at commit. The expansion's one precedence rule: where a spanning input and a week-specific input collide on the same rate key, the week-specific one wins for that week. Both shapes are defined here and only here; the rates page references this rule rather than restating it.
{
"product_id": "acme-prime",
"week": "2026-W41",
"advertiser_class": "general",
"spot_length": 30,
"buy_type": "preemptible",
"clearance_tier": "P2",
"market_class": "scatter",
"rate_basis": "per_unit",
"gross_rate_unit": 405.00,
"currency": "USD",
"locked_rate_id": "lr_88c1",
"commit": "acme-2026q4-v2",
"commit_kind": "standing",
"agreement_scope": null
}
| Field | Type | Description |
|---|---|---|
product_id, week required | string, ISO week | Cards price by week, whatever grain a line books at (see period). week is required on every read: a spanning input was materialised per week at commit (the shape note above). Only the write shape may omit it. |
advertiser_class required | enum | One of the advertiser classes. Seller-defined; open. |
spot_length required | integer | Creative length in seconds this rate prices. |
buy_type required | enum | One of the buy types. |
clearance_tier | enum | One of the clearance tiers; permitted only for preemptible. |
market_class required | enum | Market timing, one of the market classes. Named what every concept page already calls it; the old wire name class sat confusingly beside advertiser_class, which is a different axis. Political LUR is an advertiser class, not a market class; negotiated pricing is agreement-scoped, not a class; an upfront's commitment lives on the agreement, not here. |
rate_basis | enum | One of the rate bases; names the authoritative cost field. Emitted on every read, never accepted on a write: the platform derives it from which cost field is present, so a request cannot contradict itself, and a value sent anyway is ignored rather than validated. |
gross_rate_unit, gross_rate_cpm | number | Exactly one of the two, on the write and on the read alike: a write carrying both or neither is refused 422 INVALID_INPUT, and a read returns exactly the cost field the write carried, plus the derived rate_basis. An audience_guaranteed entry prices per_unit like any spot-cost buy type: gross_rate_unit is the fixed price of one guaranteed unit, and the entry carries no derived CPM; the equivalent CPM is gross_rate_unit / guaranteed_impressions x 1000, the reader's own arithmetic, not a field. cpm remains a rate basis of its own, priced by gross_rate_cpm, for a buy type that settles on an uncapped, buyer-named impression count rather than a fixed unit. Each creative length a card prices is its own entry with its own price: no rate is ever derived from another length's. |
guaranteed_impressions | integer | Required on audience_guaranteed only: the impressions this audience guarantees per unit bought, informational to pricing. A line's total guarantee is guaranteed_impressions x units. |
audience_code | string | Required on audience_guaranteed, and on any entry pricing cpm; one of the audience codes. |
currency required | ISO 4217 | Declared once per card commit and echoed per entry. One trade currency per commit and per order: locked at order time, carried, never converted. |
locked_rate_id required | string | What an order line cites to lock this price. See the price-clearance invariant. |
commit required | string | The versioned card commit this entry belongs to. |
commit_kind | enum | standing (default) or quote. A quote commit is minted per campaign inside a plan, or by a seller's counter at the review gate. It carries quote_expires_at, plus a proposal_ref when a plan minted it or the order and unit it answers when a counter did, and locks like any card on confirm. See Disclosure. |
quote_expires_at | ISO datetime | Set on quote commits: after it, the entry is a stale card and returns STALE_RATE_CARD. |
agreement_scope | string | null on open cards; an agreement id on buyer-scoped cards and quotes minted for one buyer alone. |
avail
One availability statement for one product and one period. A week-grain entry speaks for the whole week at the seller's own precision; a day-grain entry speaks for one date; a month-grain entry speaks for the month. The platform never invents per-date data from a week-grain statement. Concept: Currencies.
{
"product_id": "acme-prime",
"period": { "grain": "week", "start": "2026-W41" },
"state": "available",
"basis": "measured",
"spots": {
"available": 42
},
"impressions": {
"source": "nielsen",
"stream": "c3",
"hh": { "per_spot": 128000 }
},
"sellout_level": 0.62,
"as_of": "2026-10-01T12:00:00Z"
}
An audience-guaranteed product states the same entry in the denomination it sells in: units.available, and neither spots nor impressions.
{
"product_id": "simul-a25-54-ron",
"period": { "grain": "week", "start": "2026-W40" },
"state": "available",
"basis": "measured",
"units": {
"available": 40
},
"sellout_level": 0.29,
"as_of": "2026-10-01T12:00:00Z"
}
| Field | Type | Description |
|---|---|---|
product_id required | string | What the statement covers. |
period required | object | The period this entry states availability for. Its grain has to be one the product's grains offers. The avails read keeps its weeks window: a month entry comes back when a requested week falls inside its month. |
state required | enum | One of the avail states. |
basis required | enum | measured or modelled: whether the figures come from live inventory data or a forward projection. Renamed from actual/projected so the value never shares a token with state: "projected", which is a different axis (clearability, not figure provenance). |
spots.available | object | Spots available for this period: the number an order's units validates against. Present on every product except one that sells nothing but audience_guaranteed, which states units.available instead: exactly one of the two counts is on an entry, and the product decides which. There is no published total in either denomination: no single denominator is true of a product sold several ways, and a total nothing validates against can only mislead. |
units.available | object | Bookable units of this product open in this period, on a product whose buy_types is exactly ["audience_guaranteed"], where spots.available would be a count of something the seller never promised. A unit is what an order books one of, priced at the rate line's gross_rate_unit; what one delivers is that line's guaranteed_impressions, which is a per-line figure and not a per-week one, so the entry carries no impressions figure at all. The count is a seller statement the platform publishes and never enforces: an audience-guaranteed line is not validated against it. There is no units.total, and there is no unit_type field declaring the denomination, because which of the two keys is present already says it. |
impressions | object | source (the measurement basis) and stream (c3, c7, live_sd) once per entry, beside one key per audience code carrying per_spot. The read shape is the write shape: the pair is stated once because per-audience measurement sources are not expressible. The platform carries these figures; it never computes them, and it publishes no per-audience rollup: total available impressions is per_spot x spots.available, the reader's own arithmetic. Absent on a product that sells nothing but audience_guaranteed: a per-spot estimate there would need a spots-per-unit conversion the platform does not have, and what a unit delivers is the guaranteed_impressions on the rate line. |
sellout_level | number | 0.0 (empty) to 1.0 (sold out): the seller's declared sell-through of its own sales plan for this product and week. The denominator is the seller's plan, which is not published, so the figure is not the complement of spots.available and cannot be recomputed or cross-checked from it. A yield and urgency signal for opportunistic buying, never a booking denominator: orders validate against spots.available alone, and never against units.available, which is published and not enforced. |
as_of required | ISO datetime | Staleness marker for the two-phase availability pattern. |
order
The transaction. Price locks at order time; later card changes never invalidate an accepted price. Concept: Orders; lifecycle: the state machine.
Every field on this object has exactly one source. It is echoed from the create request (seller, buyer_metadata, flight, attachments, the lines' booked fields), read from the platform's create-time record (order_id, buyer_entity, workflow, settlement_mode, taxonomy_version, cancellation_terms, each line's posting_policy, revision.version and .supersedes, issued_at), or folded from a named event (status, substatus, last_seq, line results and allocation, artifacts, cancellation, revision.superseded_by, the seller view's approvals). A field with none of the three sources cannot exist, which is why the snapshot can always be trusted over any single delivery: it is the fold of everything recorded, not a copy maintained beside it.
{
"order_id": "ord_9f3a12c4b7e1",
"external_order_id": "q4-campaign-042",
"buyer_entity": "yourco",
"seller": "acme",
"workflow": "catalog",
"status": "placed",
"substatus": null,
"last_seq": 5,
"rate_version": "acme-2026q4-v1",
"taxonomy_version": "acme-2026q4-v1",
"settlement_mode": "direct",
"buyer_metadata": { "advertiser_id": "adv_4c1f7a2b9e03" },
"issued_at": "2026-09-10T09:00:00Z",
"flight": { "start": "2026-10-05", "end": "2026-10-11" },
"revision": { "version": 1, "supersedes": null },
"line_items": [
{
"unit_id": "u-0001",
"product_id": "acme-prime",
"provider": "National ACME",
"network": "ACME",
"week": "2026-W41",
"units": 10,
"spot_length": 30,
"rate": {
"market_class": "scatter",
"advertiser_class": "general",
"buy_type": "preemptible",
"clearance_tier": "P2",
"rate_basis": "per_unit",
"unit_cost": 405.00,
"locked_rate_id": "lr_88c1",
"currency": "USD"
},
"status": "accepted",
"num_accepted": 10,
"allocation": [
{
"date": "2026-10-05",
"units": 4
},
{
"date": "2026-10-07",
"units": 3
},
{
"date": "2026-10-09",
"units": 3
}
]
}
],
"totals": {
"gross": 4050.00,
"currency": "USD"
}
}
| Field | Type | Description |
|---|---|---|
order_id required | string | Platform-minted, ord_ plus 12 hex. |
external_order_id required | string | Your idempotency key, echoed on every event. Byte-identical resubmission replays the stored response; 409 only on a changed payload. |
buyer_entity | string | The acting buyer the order was booked under. Server-derived from the credential, never from the request body: a body value that disagrees is refused with 403 TENANT_MISMATCH rather than trusted. Echoed on every read. See acting-buyer identity and the tenant roster. |
seller required | string | The counterparty. |
workflow | enum | One of the workflows. Stored and echoed on every read (the plan endpoint's precondition reads it), and derived at create, never accepted: the create body carries exactly one of line_items, request, or document, and that member is the workflow. A workflow sent anyway is ignored; the body member decides. |
status, substatus | enum | One of the order statuses. Switch on status and on typed fields (cancellation.late_notice, error.error_code, artifact.name); substatus is an informational step marker, will change, and is never the only carrier of a fact. |
last_seq | integer | The latest event sequence, for replay via GET /events. |
rate_version required | string | The card commit the order prices against. See the price-clearance invariant. |
taxonomy_version | string | The selling-title taxonomy version in force at create, pinned by value exactly as the rate lock is: a later catalog publish never changes it, so a definition change between plan and order can never silently break reconciliation. Platform-set, never accepted from the request. |
settlement_mode | enum | One of the settlement modes. The agreement's property, resolved server-side at create from the presented agreement_id (direct when none is presented) and echoed on every read: the CREDIT_LIMIT fail-fast path reads the resolved value, never a request field. A value sent at create that matches the resolution is a no-op; one that contradicts it is refused 422 INVALID_INPUT with details.field: "settlement_mode", because which mode governs money is the agreement's fact, not the request's. |
issued_at | string | When the buyer's system issued the order, as distinct from when the platform received it. Present on every order: it defaults to created_at when the create stated none, so a lead-time calculation never has to branch on its absence. |
flight | object | The window the order states for itself, {start, end} as ISO dates. Absent when the create stated none. When present, every date the order's lines can land on falls inside it: the create is refused otherwise. See POST /orders. |
cancellation | object | On canceled orders: the one cancellation block, identical on the cancel response, the cancellation event, and this snapshot, because all three are the same recorded fact: {reason, actor, late_notice, notice?}, where late_notice is the typed verdict (never recoverable only from substatus) and notice carries {notice_days, days_remaining} when terms were attached and a window applied. Defined field by field at the cancel reference. |
revision | object | The order's place in its own lineage. version is platform-assigned, 1 on an original. supersedes names the order this one replaced, null on an original. superseded_by appears on an order a revision has replaced, alongside status: "canceled" and cancellation.reason: "superseded_by_revision". See revisions. |
line_items required | array of object | One line item books one product for one period. Fields below. |
attachments | array of object | Paper the buyer sent alongside the lines, echoed verbatim on both order reads: {upload_id, format, role, filename, sha256} per entry. Never parsed and never a source of any field above; the lines stay authoritative. Absent when the create carried none. See attachments[]. |
buyer_metadata required | object | This is the canonical key list, closed, defined here and referenced everywhere else. The keys: advertiser_id (required at create: an order cannot be placed without naming who the buy is for, because separation, category conflict, and political compliance are all undecidable without it), campaign_id, brand, agency, estimate_id, estimate_sequence, notes, buyer_contact. An unknown key is refused 422 INVALID_INPUT with details.field naming it: these values are echoed on EDI delivery, where an unrecognised key is silent data loss rather than a harmless extra. The closure is top level only, at create time: nested objects keep their own contracts, so an unrecognised field inside buyer_contact stays valid and is carried verbatim, and an order booked before the list closed keeps its custom keys on every read. The first two keys are references, into your own registries, and what they resolved to is echoed beside them in advertiser_snapshot and campaign_snapshot rather than inside this bag: this object is your own input, echoed verbatim, so nothing the platform derives is folded into it. There is no advertiser_class key: class prices, lives on the line's rate, and would duplicate it here. There is no key here for the advertiser's category or for either name: all three are properties of the records these two ids name, so one advertiser cannot end up with two spellings of its category across two orders. estimate_id is the agency estimate number echoed on EDI delivery; estimate_sequence is the per-network sequence beside it, a string, so "001" reads back as "001"; without them, agency billing systems cannot match the record. |
advertiser_snapshot | object | Read only. The name and category that were true of the referenced advertiser when this order was created. Absent on an order booked before the registries existed. It is what competitive separation and a seller's compliance desk read, and it never moves again: editing the record reaches future orders and changes nothing about this one. |
campaign_snapshot | object | Read only. The campaign's name at create, on the same terms, when the order names a campaign. The seller sees this and the id, and nothing else about the campaign: its flight, its budget, and which other sellers sit in the plan stay on the buyer's side. |
buyer_metadata.buyer_contact | object | Optional. A human the seller's desk can reach, as three optional strings: name, email, phone. Echoed unchanged on both the buyer's and the seller's read. Neither the email nor the phone is format-checked, and nothing is sent to either. |
buyer_requests | object | Optional. What the buyer asked the seller for, as distinct from what the seller states it enforces: {min_separation_seconds, scope}, where scope takes only campaign. Echoed unchanged on both reads so the ask is a field at the approval gate rather than prose in notes. Recorded and surfaced, never scheduled around; the mirror-image field is the product's separation_policy. |
agreement_id | string | The agreement presented at create, echoed so the terms governing the order stay resolvable from the snapshot. Absent when none was presented. Its posting-policy overrides were read once, at create, into each line's frozen posting_policy; nothing resolves against the live agreement when a post lands. |
cancellation_terms | object | Snapshotted by value at create from the presented agreement: {notice_days, notes?}. Absent when the create presented no agreement_id. A later agreement change never alters it, exactly as a locked price. See Cancellation and posting terms. |
totals.gross, totals.currency, totals.impressions | object | Gross total in the order's one trade currency, plus impressions, a map keyed by audience code: the order's contracted guarantee, summed over audience_guaranteed lines as the rate entry's guaranteed_impressions times the line's booked units (requested units while a line is still pending). Seller-sourced from the locked rate entries and frozen at create; never a buyer estimate, and never what anything settles on: settlement stays on delivery posts, and this is the goal side of that comparison. Absent entirely on an order with no guaranteed lines: spot-cost impressions are estimates, not contract. |
line_items[]
| Field | Type | Description |
|---|---|---|
unit_id | string | Platform-assigned per line; how results and counters reference lines. |
product_id required | string | From the seller's catalog. |
provider, network | string | Bookable entity and channel, on every read: derived from the line's product_id, never accepted on a write. They are the product's own facts, so a buyer-sent copy could only agree with the catalog or contradict it; a value sent anyway is ignored and the catalog's values are echoed. |
period required | object | The period this line books. A day period pins the air date, daylocked by construction; a week or month period books across the period's dates and the seller distributes the units. The grain has to be one the product offers, or the create is refused 422 GRAIN_NOT_OFFERED. |
units | integer | Required on every catalog line, every buy type, audience_guaranteed included: a unit is a fixed-price, seller-published guarantee block, not a buyer-named impression count. Which of units and impressions_goal a line carries is keyed by workflow, never by buy type. |
impressions_goal | integer | For impression currency (proposal and document workflows; see Proposals). A catalog line never sets this, and one that does is refused 422 INVALID_INPUT: the seller's own catalog has no cell priced against a buyer-chosen impression count. |
spot_length required | integer | Seconds; must be a length the rate entry prices. |
include_mirror | boolean | Books the product's paired mirror airing too. Default: false. |
rate required | object | {market_class, advertiser_class, buy_type, clearance_tier?, unit_cost or cpm, locked_rate_id, currency}: the priced cell the line locks, citing its rate entry. Exactly one of unit_cost or cpm; rate_basis is derived from which one is present and emitted on every read, never accepted on the write. |
rc_impressions | object | Impression estimates at order time, per audience code, kept for buysheet parity. |
creative_id | string | The creative this line airs, by reference into your own registry. Optional at every state; the creative can follow after placement as a traffic instruction. See the create reference. |
creative_snapshot | object | Read only. The creative_code, name, and length_seconds that were true of the referenced creative when this line's reference was persisted. creative_code is the Ad-ID or ISCI style industry code a traffic desk keys on, treated as an opaque string. |
do_not_air | array of ISO date | Optional. Dates inside the line's window the buyer asked not to air on, echoed as sent. Recorded and surfaced to the seller, never enforced: a line carrying one of these dates can still be allocated on it, and nothing validates them against the order's flight. See line_items[]. |
traffic_instructions | object | Optional. How the line's creatives rotate: rotation (equal or weighted) and creative_splits, an array of {creative_id, pct?}. rotation decides the shape: equal omits every pct and reads back with the evenly computed shares filled in, weighted states every pct summing to exactly 100, and any other combination is refused at create. creative_id above stays the single primary reference and has to be one of the splits. Recorded and surfaced, never scheduled around: nothing enforces, verifies, or reconciles a rotation. See traffic_instructions. |
status | enum | Result, one of the unit statuses. A line accepted below its ask is accepted with num_accepted below the line's units: the numbers carry the shortfall, and there is no separate partial value for a consumer to branch on. |
num_accepted | integer | Units the seller booked, on decided lines. Compare against the line's own units: a catalog line carries no second copy of its request, so units: 10, num_accepted: 6 is the whole story. |
num_requested | integer | Only on lines the buyer did not book in units: the proposal and document workflows, where the ask arrived as an impression count or a document and the unit count is the seller's plan. Never on a catalog line (its request is units), and never on a seller-minted countered line (its offer is units, from the counter's num_offered). |
posting_policy | object | Read-side: the line's effective posting policy, resolved through the override chain once at create and frozen by value, exactly as cancellation_terms is (the resolution rule). {aggregation_weeks, threshold_pct, exclusions?}; absent when the resolution was unstated. Never accepted on a write; reconciliation reads this, never the live agreement. |
allocation | array of object | Authoritative air dates once decided: {date, units} entries summing to num_accepted. Slot lines have a single entry; week lines may spread across the product's weekday pattern. A multi-unit week line never collapses to one date. |
reason | string | Populated on rejected and countered lines; persisted. |
in_response_to | string | On countered lines: the unit_id this counter answers. Counters are additive result lines; see Negotiation. |
order_event
The append-only record of everything that happens to an order: the envelope of order.status_changed, and of it alone. Every other type, the order-linked drift notice catalog.stale_rate_card included, carries its own envelope defined with the type table; only the two common fields (event_type, occurred_at) are shared by every type. Delivery semantics: the event envelope.
{
"event_type": "order.status_changed",
"order_id": "ord_9f3a12c4b7e1",
"external_order_id": "q4-campaign-042",
"buyer_entity": "yourco",
"seq": 5,
"status": "placed",
"prior_status": "seller_review",
"substatus": null,
"units": [
{
"unit_id": "u-0001",
"status": "accepted",
"num_accepted": 10,
"allocation": [
{ "date": "2026-10-05", "units": 4 },
{ "date": "2026-10-07", "units": 3 },
{ "date": "2026-10-09", "units": 3 }
]
}
],
"artifact": {
"name": "placement_receipt",
"seller_order_id": "ACME-77120"
},
"approval": {
"gate": "seller_review",
"actor": "sales@acmebroadcasting.example",
"decision": "approve"
},
"error": null,
"occurred_at": "2026-10-02T14:41:09Z"
}
| Field | Type | Description |
|---|---|---|
order_id, external_order_id required | string | Both ids on every event. |
event_type required | string | One of the six event types, the same to both sides. Every lifecycle transition is order.status_changed; the transition itself is status plus prior_status, fields rather than type names. |
buyer_entity | string | The acting buyer, carried on the envelope so a seller can attribute an event when one connection serves several buyer organisations. Absent on an order booked before the field existed. |
seq required | integer | Strictly increasing per order. Retries reuse the seq; dedup on (order_id, seq). |
status required | enum | One of the order statuses. |
prior_status | enum | The status the transition left, on order.status_changed. Platform-computed, so a single delivery names its whole transition without a replay. |
substatus | string | Informational step marker. |
units | array of object | Per-unit results when the transition carries them: the transition's complete record, down to each entry's allocation and, on countered entries, the counter itself. Entry fields are defined once, at the event envelope; the snapshot's line results fold from these entries, last write per unit. |
artifact | object | Attached document or receipt, by name: placement_receipt (the booking receipt: the seller's order ID and placed_at, its only facts of its own; the daylocks rows it serves are flattened from the same event's units[].allocation, never recorded twice), parsed buysheets, delivery posts. |
approval | object | The decision record on the transition a gate decision produced, absent otherwise: {gate, actor, decision, reason?}. The event is where an approval is recorded; the seller view's approvals[] is its projection. |
creatives | array of object | The creative per line: {unit_id, creative_id, creative_code?, name?}. On every order.status_changed event, so a consumer following the stream always knows which spot each line names. Absent when no line references a creative. The code and the name are the snapshotted values, taken when the line's reference was persisted, so a rename on the buyer's side never rewrites a stream you have already replayed. It rides the envelope rather than units because units carries the results of a transition and is absent on the events that carry none. Like every other envelope field, it survives replay exactly as delivered; replay removes only the two order identifiers it hoists to the response top level. |
attachments | array of string | The upload_id list of the order's attachments, on the event that moves the order to seller_review and nowhere else, so a traffic desk knows paper exists before opening the order. That event is order.status_changed with status: "seller_review", the same to both sides. IDs only: the hashes and filenames are on the order. Not an artifact: an artifact is something the platform produced, an attachment is something the buyer sent. |
cancellation | object | Required on every status: "canceled" event, absent otherwise: the identical cancellation block {reason, actor, late_notice, notice?} carried by the cancel response and folded onto the snapshot; the event is where it is recorded. |
superseded_by | string | On the cancellation event a revision produces (order.status_changed to canceled), naming the revision that replaced this order. Absent on every other cancellation, and there is no separate substatus for a supersede: the cancellation reads like any other, and the lineage is here. |
error | object | The canonical error envelope, defined once at Errors: {error_code, error_message, stage, recoverable, details}. That page is authoritative; this table does not restate it. |
occurred_at required | ISO datetime | UTC. |
approval
One decision taken at a gate. Recorded exactly once, on the order event the decision produced: a seller's decide records it on the resulting transition with gate: "seller_review", and a buyer's confirm on its transition with gate: "needs_confirmation". The seller view's approvals[] is the projection of the seller-gate records in seq order, each carrying the seq and occurred_at of the event that recorded it; there is no separately stored approval ledger to disagree with the stream.
{
"gate": "seller_review",
"actor": "sales@acmebroadcasting.example",
"decision": "approve"
}
| Field | Type | Description |
|---|---|---|
gate required | enum | seller_review or needs_confirmation: the gate the decision was taken at. |
actor required | string | The deciding organization's own assertion of who or what decided: a display value, recorded verbatim, never an authenticated identity. Validation is exactly two checks: valid UTF-8, and at most 256 Unicode scalar values (code points, not bytes); a longer value is refused 422 INVALID_INPUT with details.field: "actor" and details.max_length: 256. Verbatim means verbatim: leading and trailing whitespace is preserved, never trimmed. The authenticated fact is the side: the platform verified the deciding credential holds that gate's grant on this order before accepting the decision, and gate plus the order's counterparties name that organization; no actor value can widen, reassign, or forge it. What crosses the tenant boundary is therefore the deciding organization's statement, its own choice of a name, a desk alias, or an automation id, exactly as a signed confirmation carries whatever signature the signer wrote; treat it as their claim, not a platform-verified person. An automated decision records its policy: an auto-accepted plan records the acceptance band. |
decision required | enum | approve, reject, or counter: the outcome derived, totally, by gate, never the request's headline. At seller_review it derives from the per-unit actions, covering every mix: any countered unit makes the decision counter; otherwise any accepted unit makes it approve (a mixed accept-and-reject books what was accepted, so the gate approved); otherwise every unit was rejected and it is reject. A body sending approve with a countered unit records counter, because that is what happened. At needs_confirmation there are no per-unit actions and the mapping is the action itself: confirm records approve (an acceptance-band auto-confirm identically, with the band as actor), reject records reject; counter never appears at this gate, because countering a plan goes through respond, not confirm. |
reason | string | The note the deciding request sent, when it sent one. Distinct from a per-unit reason and never derived from one. |
negotiation
The offer and counter history of one order. The order parks in negotiating between rounds. Concept: Negotiation.
{
"negotiation_id": "neg_33a7",
"order_id": "ord_9f3a12c4b7e1",
"state": "countered",
"rounds": [
{
"actor": "seller",
"counter": {
"unit_id": "u-0002",
"week": "2026-W42",
"unit_cost": 392.00,
"num_offered": 8
},
"expires_at": "2026-09-30T20:00:00Z"
}
]
}
| Field | Type | Description |
|---|---|---|
negotiation_id, order_id required | string | One negotiation per order. |
state required | enum | One of open, countered, accepted, expired, withdrawn. |
rounds required | array of object | Each round: {offer, counter, actor, expires_at}. Counters surface on the order as additive lines with in_response_to. |
proposal_request
The buyer's open ask: carried on POST /orders with workflow: "proposal" in the request field instead of line items. No product IDs required. Concept: Proposals.
{
"request_type": "audience_plan",
"audience": {
"definition": {
"demo": "A25-54",
"segments": ["auto_intenders_q4"]
},
"currency_goal": {
"unit": "a25_54",
"target": 42000000
}
},
"anchor_product_ids": ["acme-prime"],
"budget_gross": 500000,
"flight": {
"start": "2026-10-05",
"end": "2026-12-27"
},
"constraints": {
"spot_lengths": [15, 30],
"max_unit_cost": 450.00
},
"acceptance_band": {
"metric": "delivery",
"tolerance_pct": 2,
"action": "auto_accept"
},
"brief": "Reach auto intenders in the Northeast; avoid overnight rotations."
}
| Field | Type | Description |
|---|---|---|
request_type required | enum | One of the request types. |
audience.definition | object | An inline audience definition. Set one of definition, audience_id, or upload_id. |
audience.audience_id | string | A shared audience reference. |
audience.upload_id | string | An uploaded plan or audience file. |
audience.currency_goal | object | {unit, target}: the audience code and impression goal the plan should hit. |
anchor_product_ids | array of string | Optional starting points. |
budget_gross required | number | Gross, in the trade currency. |
flight.start, flight.end required | ISO date | The flight window. |
constraints | object | Spot lengths, max unit cost, copy splits, daypart mix. |
acceptance_band | object | Optional auto-accept tolerance: metric (delivery or budget), tolerance_pct (a percentage; 2 means 2%), and action (auto_accept or flag). The platform evaluates it deterministically against the request target when the plan returns; the comparison is one-sided per metric. The exact math, boundary, and missing-metric rules, with worked examples, are on Proposals. |
brief | string | Free text for the seller's planners. |
The seller's plan_proposal response prices line items off their card and may mint custom products scoped to your agreement: each gets a real product_id and books through the same rails. Rates it mints per campaign are quote commits. Where the seller cannot meet the whole ask, the plan returns the shortfall as unmet[] rather than a silent gap. Nothing books until you confirm, or until an acceptance_band you set fires.
plan_proposal
The seller's answer to a proposal order: the assembled first-pass plan, attached as an artifact when the order enters needs_confirmation. The seller writes it with POST /me/orders/{id}/plan; the buyer confirms, counters, or declines. Concept: Proposals.
{
"name": "plan_proposal",
"plan_id": "plan_5b2e",
"proposal_ref": "ord_c19a44e2f0b1",
"line_items": [
{
"product_id": "acme-auto-q4-9f",
"minted": true,
"week": "2026-W40",
"impressions_goal": 21000000,
"spot_length": 30,
"rate": {
"market_class": "scatter",
"buy_type": "audience_guaranteed",
"rate_basis": "cpm",
"cpm": 11.90,
"locked_rate_id": "lr_q_2f7a",
"currency": "USD",
"commit_kind": "quote"
}
}
],
"plan_totals": {
"gross": 499800.00,
"currency": "USD",
"projected_delivery": {
"a25_54": 41800000
}
},
"unmet": [
{
"requested": "overnight rotations",
"reason": "held for a committed buyer"
}
],
"expires_at": "2026-09-30T20:00:00Z",
"created_at": "2026-09-23T15:10:00Z"
}
| Field | Type | Description |
|---|---|---|
plan_id required | string | The plan's id; referenced when the buyer confirms or counters. |
proposal_ref required | string | The order_id of the proposal order this plan answers. |
line_items required | array of object | The proposed buy. Same shape as an order line, each citing a locked_rate_id; minted: true marks a product minted for this request (scoped to your agreement and reorderable next quarter). The lines are the whole plan: which products were minted is the set of lines carrying minted: true, and which quote commits the plan locks against is the set behind the lines' locked_rate_ids, both the reader's own filter rather than a second copy the plan restates. |
plan_totals required | object | {gross, currency, projected_delivery}. projected_delivery is a map keyed by audience code; it is the figure an acceptance_band with metric: delivery is checked against. |
unmet | array of object | The availability counter: what the seller could not fill, each {requested, reason}. Empty when the plan meets the whole ask. |
expires_at required | ISO datetime | The plan offer's validity; after it, the order lapses. Enforced at plan post to be no later than the earliest quote_expires_at among the quote commits the lines cite, because an offer that outlives its prices is decorative: the effective expiry would silently be the quote's. One expiry, and it is this one. |
created_at required | ISO datetime | When the seller returned the plan. |
delivery_post
Seller-supplied actuals, attached to an order as an artifact. Audience guarantees reconcile against it; the platform carries the numbers and never computes them. Concept: Reconciliation.
{
"name": "delivery_post",
"order_id": "ord_9f3a12c4b7e1",
"week": "2026-W41",
"units": [
{
"unit_id": "u-0001",
"aired": 10,
"delivered": {
"hh": 1260000,
"p2plus": 1910000,
"a25_54": 804000
},
"source": "nielsen"
}
],
"currency_of_record": "a25_54",
"shortfall": null
}
| Field | Type | Description |
|---|---|---|
order_id, week required | string, ISO week | Posts are week-grain per-unit counts today. |
units required | array of object | Per unit: aired count, delivered impressions keyed by audience code, and source. |
currency_of_record required | string | The audience the guarantee settles on. |
shortfall | object | Populated when a guarantee under-delivers. Whether it owes a make-good is decided by the line's effective posting_policy; where none is stated, the shortfall is reported and the decision stays with the parties. |
capability_profile
What a seller's connection can do. The orchestrator never calls what the profile does not advertise; it degrades gracefully instead. Endpoints: Capabilities. Concept: Connections.
{
"seller_id": "acme",
"conformance_level": 2,
"transports": {
"result_delivery": ["callback", "poll", "sqs", "console"],
"formats": ["json", "csv", "xlsx"]
},
"capabilities": {
"realtime_availability": true,
"counter_proposals": false,
"reservation_hold": false
},
"rate_management": {
"rates": "frozen_quarterly"
},
"tenant_policy": {
"mode": "open"
},
"sla": {
"standard": {
"min_lead_minutes": 2880,
"max_decision_latency_minutes": 240
}
}
}
| Field | Type | Description |
|---|---|---|
seller_id required | string | The tenant the profile describes. |
conformance_level | integer | 0 through 4, computed from the declared capabilities per the decision table, never accepted on a profile write: the level is the highest unbroken rung the declarations support. On every read, and published to buyers as level on GET /v1/sellers. A summary only: the orchestrator and every feature gate route on the individual declarations (counter_proposals, reservation_hold), never on the level. See Seller levels. |
transports.result_delivery required | array of string | Delivery rungs offered: callback, poll, sqs, console. |
transports.formats | array of string | File formats accepted and produced. |
capabilities.realtime_availability | boolean | Live avails vs declared cadence. |
capabilities.counter_proposals | boolean | Level 3 counters on decide. |
capabilities.reservation_hold | boolean | Level 4 holds with TTL. |
rate_management.rates | enum | frozen_quarterly or live: how the seller's rates move. The old mode enum wore two facts at once (how avails move and how rates move); avails movement is capabilities.realtime_availability alone, so a profile can no longer claim both frozen_quarterly and live avails with no stated winner. There is no pricing_modes list: how a product prices is its disclosure.pricing_policy, per product, and a hand-maintained seller-level restatement in a second vocabulary was two names for one fact. |
tenant_policy.mode | enum | How you treat an acting buyer you have not allowlisted. open (default): its order reaches seller_review like any other and you decline there. allowlist: it is refused at intake with 403 and no order is created. Either way, suspension refuses regardless. See the tenant roster. |
sla | object | Per service class: min_lead_minutes and max_decision_latency_minutes. One unit, minutes, on both. |
tenant_roster_entry
One acting buyer as a seller sees it. A connection can carry several buyer organisations; this is how a seller tells them apart and stops one without disturbing the rest. Endpoints: the tenant roster.
{
"buyer_entity": "yourco",
"status": "active",
"allowlisted": false,
"first_seen_at": "2026-10-01"
}
| Field | Type | Description |
|---|---|---|
buyer_entity required | string | The acting buyer, as it appears on every order from it. An authorization principal, not a database key: it may stand for an agency, an advertiser, or another buyer organisation. |
status required | enum | active or suspended. A suspended tenant's POST /v1/orders is refused with 403 and creates nothing. |
allowlisted required | boolean | Whether the seller admitted this tenant explicitly. Consulted only under tenant_policy.mode: "allowlist"; see capability_profile. |
reason | string | The seller's note from the suspension. Absent on an active tenant. |
first_seen_at required | date | When this tenant first appeared on the connection, whether by sending an order or by being allowlisted ahead of one. |
status and allowlisted are independent fields and no operation touches both. All four combinations are legal, and they resolve by one rule: suspension refuses regardless of the allowlist, and under allowlist mode a tenant that is not allowlisted is refused regardless of status.
agreement
The relationship, made explicit: functionally a deal ID. Presenting it unlocks the catalog scope, buyer-scoped rate cards, permitted buy types, and the settlement mode. The record is created implicitly the first time a seller grants a buyer anything: there is no separate "new agreement" step, because a seller granting a product is stating the relationship, not minting a contract first. Concept: Agreements.
{
"agreement_id": "agr_71c0d2",
"buyer": "yourco",
"seller": "acme",
"catalog_scope": "*",
"external_ref": "CRM-9001",
"rate_card_refs": ["acme-yourco-2026q4"],
"permitted_grains": ["week", "month"],
"permitted_buy_types": ["preemptible", "non_preemptible", "fixed_position", "audience_guaranteed"],
"settlement_mode": "direct",
"disclosure_overrides": [
{ "product_id": "acme-prime", "avails_policy": "published", "pricing_policy": "agreement" },
{ "product_id": "*", "avails_policy": "on_request" }
],
"cancellation_terms": {
"notice_days": 14
},
"posting_policy_overrides": [
{ "product_id": "acme-prime", "posting_policy": { "aggregation_weeks": 4, "threshold_pct": 95 } }
],
"effective": {
"start": "2026-10-01",
"end": "2027-09-30"
}
}
| Field | Type | Description |
|---|---|---|
agreement_id required | string | What rate_entry.agreement_scope and minted proposal products reference. |
buyer, seller required | string | The two parties. |
catalog_scope | "*" or array of string | Which products this relationship grants the buyer. "*" grants the seller's whole catalog; a list grants exactly the products named. Omitted reads as "*". It gates visibility: "by_agreement" products only: an open product lists for every buyer whatever this says, because open is the seller declaring the product needs no relationship to be seen. The grant is the union across a buyer's agreements with one seller. |
external_ref | string | The seller's own key for this relationship, opaque to the platform and never validated. Unique per seller across its relationship records: a second record reusing one is refused 422 DUPLICATE_EXTERNAL_REF naming the colliding record, because a non-unique external key is worse than no external key for the reconciliation it exists to serve. |
rate_card_refs | array of string | Buyer-scoped card commits only this buyer can transact. |
permitted_grains | array of enum | Which purchase grains this buyer may book, narrowing the product's own grains. Omitted or empty is no restriction. Resolution is intersection and the relationship can only narrow: the effective set is product.grains ∩ permitted_grains, so a grain named here that the product does not offer is a no-op rather than a grant, and nothing on the relationship can sell what the product does not. An empty intersection means the buyer cannot book that product at any grain, and it does not list for them. A line naming an excluded grain is refused 422 GRAIN_NOT_OFFERED, with details.permitted_grains present when the relationship is what excluded it. Like catalog_scope, the permission is the union across a buyer's agreements with one seller. |
permitted_buy_types | array of string | Which buy types this buyer may book, by the same intersection rule as permitted_grains: it narrows the product's own buy_types and never widens them, omitted or empty is no restriction, and a buy type the product does not sell is a no-op. A product a buyer can book in no buy type does not list for them. |
settlement_mode required | enum | One of the settlement modes. |
disclosure_overrides | array of object | Seller-authored, optional. Each entry is {product_id, avails_policy?, pricing_policy?}, where product_id may be "*" for all products in scope. For a buyer presenting this agreement, the effective policy per field resolves as override(product_id) ?? override("*") ?? product.disclosure ?? published (avails and pricing independent; an omitted field inherits the product default). This is how a seller publishes to a trusted buyer while withholding from the open catalog. Buyers never set disclosure; an override naming a product outside catalog_scope is a no-op. See Disclosure. |
cancellation_terms | object | notice_days (integer) and optional notes. Orders snapshot these by value at create, so a later change to the agreement leaves booked orders alone. See Cancellation and posting terms. |
posting_policy_overrides | array of object | Seller-authored, optional. Each entry is {product_id, posting_policy}, where product_id may be "*". The effective policy for a line resolves as override(product_id) ?? override("*") ?? product.posting_policy ?? unstated, the same precedence as disclosure_overrides. See Posting policy. |
effective.start, effective.end required | ISO date | The agreement's window. |
Enumerations
Every enumerated value in the API, defined once. Field tables across the docs link here; lifecycle and business meaning live on the linked concept pages. Enums marked open may grow: treat unknown values as pass-through, never as errors.
product.type
| Value | Meaning |
|---|---|
daypart | A selling title over a weekday pattern and local time range. |
program | A named program; event-dated programs use occurrences. Tentpoles are programs. |
genre | A genre reference. |
rotator | Rotation rules across dayparts or titles. |
ron | Run of network. |
sponsorship | All or part of a program bought by one advertiser. Carries an optional billboard block. Not a buy type: it composes with one. |
custom | Seller-defined; includes agreement-scoped products minted from proposals. |
Semantics: Products. Roadblock, piggyback, bookending, and infomercial are deliberately not types: the first is a multi-product booking, the middle two are trafficking arrangements, and an infomercial is a spot_length of 1800 with the dr advertiser class.
distribution
| Value | Meaning |
|---|---|
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. |
spot | Time sold by an individual station or system. |
Optional; omitted means unstated. Geography stays on market, so spot plus a market is local spot and there is no local_spot value. Semantics: Distribution.
buy_type
| Value | Meaning |
|---|---|
preemptible | Pay for what airs; the seller may preempt. |
non_preemptible | The spot airs; the seller chooses placement within the product. |
fixed_position | The spot airs in the position bought. |
audience_guaranteed | Audience guarantee; shortfalls trigger the make-good policy. |
Semantics: Buy types and guarantees.
workflow
| Value | Meaning |
|---|---|
catalog | Line items against published products. Default. |
document | A document reference; parsed, validated, and confirmed at needs_confirmation. |
proposal | An open proposal request; the seller returns a plan. |
Semantics: Submit a document order and Proposals.
rate_basis
| Value | Meaning |
|---|---|
per_unit | gross_rate_unit prices one spot, at the entry's own spot_length. |
cpm | gross_rate_cpm prices one thousand impressions. |
rate_basis is a read-side field: every read surface emits it, and no write accepts it. The platform derives it from which cost field the write carried (gross_rate_unit or gross_rate_cpm on a rate entry, unit_cost or cpm on an order line), exactly one of which is required.
audience_guaranteed requires per_unit, priced and booked the same way every spot-cost buy type is: a fixed price per unit, with the guaranteed audience stated per unit on the rate entry (guaranteed_impressions) rather than driving the price. cpm is its own rate basis, for the proposal and document workflows' uncapped, buyer-named impression counts (see Proposals); no catalog cell prices on it.
There is no per-second basis. Creative length is a key axis of the rate card, so a card states a price for each length it sells and the platform derives none of them: a :15 is whatever you priced it at, not a fraction of your :30. A length your card does not price has no rate entry and no locked_rate_id, so it cannot be ordered from the catalog; the proposal path is where a buyer asks for one.
market_class (market timing)
| Value | Meaning |
|---|---|
scatter | At the card's rate, whatever card: open or agreement-scoped, in-quarter or drawing down a season's commitment. The default, and the value every non-discounted cell carries. The old gloss "in-quarter" existed to contrast with the retired upfront value; with the commitment on the agreement, an upfront draw-down cell is a scatter cell on an agreement-scoped card, priced at that card's negotiated rate. |
discounted | Near-air marked-down inventory, preemptible, carrying a window and an optional signal. Whether it went unsold on a standing cadence or opened up late is a story about why it became cheap, which prices and behaves identically either way and which no seller can classify reliably; the prose keeps the trade's words (remnant, opportunistic), the wire keeps one value. |
Two values, because two behaviours. There is no upfront value: an upfront's commitment lives on the agreement (commitment_gross, the pacing read) and its pricing on the agreement-scoped card, exactly as negotiated pricing is agreement-scoped rather than a class. Migration is a relabel, not a rejection: a cell published under the retired upfront value reads back as scatter on its agreement-scoped card, because at-card is what it always was, and the deprecated ?rate_class=upfront alias maps to scatter for the same reason. Timing, not geography; political LUR is an advertiser class. Semantics: The deal model.
clearance_tier
| Value | Meaning |
|---|---|
P1 | Highest clearance priority; last to be preempted. |
P2 | Standard priority. |
P3 | Lowest priority; first to be preempted. |
Semantics: Guarantees.
advertiser_class
| Value | Meaning |
|---|---|
general | General market. |
dr | Direct response. |
tune_in | Network tune-in and promotional advertisers. |
competitive | Category-competitive rates. |
theatrical | Studio and entertainment releases. |
political_candidate_lur | Candidate buys at lowest unit rate. See Political buying. |
political_issue | Issue advertising; LUR does not apply. |
Open enum, seller-defined: a seller's card may carry classes beyond these. Semantics: Rates.
period.grain
| Value | start format | Meaning |
|---|---|---|
day | YYYY-MM-DD | One air date. Booking it pins the date: daylocked by construction. |
week | ISO YYYY-Www | One broadcast week. The seller distributes the units across it. |
month | YYYY-MM | One calendar month. Only offerable where the card prices that month uniformly. |
A product says which of these it offers in grains; omitted reads as ["week"]. Semantics: period.
reporting_daypart
The VAMOS categorization, closed and plural: a rotator lists several, run of network lists all six, and there is no all sentinel. Descriptive only. The windows below are reference, not validation: nothing checks a product's definition against them, and nothing prices on the categorization. The definition is what the seller sells; this is how VAMOS files it so buyers can compare across sellers. Omitting the field means uncategorized, which is legal: a window the six do not cover, early fringe and prime access among them, is better left uncategorized than filed under a neighbour the seller did not choose.
| Value | Reference window |
|---|---|
early_morning | 06:00 to 09:00 |
daytime | 09:00 to 16:00 |
primetime | 20:00 to 23:00 |
late_night | 23:00 to 02:00 |
overnight | 02:00 to 06:00 |
weekend | Saturday and Sunday, any hour |
avail.state
| Value | Meaning |
|---|---|
available | Clearable now. |
unavailable | Sold out or blocked. |
projected | Quotable, not firmly clearable. |
Semantics: Avails.
order status
| Value | Meaning |
|---|---|
draft, submitted, validating | Intake. |
needs_confirmation | The buyer confirms an artifact before it books: a document workflow's parsed interpretation, or a proposal's seller-returned plan_proposal. |
confirmed | Validated and confirmed. |
negotiating | Parked between rounds: the negotiated workflow, or a proposal counter. |
seller_review | The seller's approval gate. |
placed, completed | Booked; done. An order with a mixed unit set completes like any other: the per-line numbers carry the mix, and there is no order-level partial status. |
rejected, canceled, failed | Terminals. |
Semantics: The state machine.
unit status
| Value | Meaning |
|---|---|
pending | Not yet decided. |
accepted | Booked. num_accepted carries the count, which may be below the line's units: a partial acceptance is accepted with a smaller number, not a separate status, because every consumer handles the two identically and reads the count either way. |
rejected | Declined; reason populated. |
countered | An additive counter line; in_response_to names the unit it answers. |
Semantics: Orders.
settlement_mode
| Value | Meaning |
|---|---|
direct | You invoice each other; the platform carries the paper trail. Default. |
cleared | The platform clears the trade. Optional; per agreement. |
Semantics: Settlement.
proposal request_type
| Value | Meaning |
|---|---|
audience_plan | An audience definition and goal in; a priced plan back. |
specs | Concrete constraints in; a plan that satisfies them back. |
open | A brief; the seller's planners propose. |
Semantics: Proposals.
disclosure.avails_policy
| Value | Meaning |
|---|---|
published | The tri-state avails feed is materialized and queryable. Default. |
on_request | No standing feed; a read returns 202 and the seller answers a scoped query. |
withheld | Availability is never exposed; a read returns 409 AVAILS_WITHHELD. Resolves at seller review or in a plan. |
Semantics: Disclosure.
disclosure.pricing_policy
| Value | Meaning |
|---|---|
published | An open rate card visible to any authorized buyer. Default. |
agreement | A buyer-scoped card, the deal-ID pattern, unlocked by presenting the agreement. |
quote | Priced per campaign as a quote commit inside a plan. |
Semantics: Disclosure.
market.scheme
| Value | Meaning |
|---|---|
nielsen_dma | Nielsen DMA codes. |
msa | Metropolitan statistical areas. |
cable_zone | Cable interconnect zones. |
country | National markets outside the US schemes. |
custom | Seller-defined geography. |
Open enum. Omitting market entirely means national. Semantics: Products: markets.
audience codes
| Value | Meaning |
|---|---|
hh | Household impressions. |
p2plus | Persons 2+. |
a25_54 and other demo codes | Standard demos. |
custom:<def> | Seller-declared custom audiences. |
Open enum. An audience code always names people being measured. spots is not an audience code: the unit count is the settlement basis of every spot-cost buy, carried by units and spots.available, and it never keys an impressions map or appears in a product's currencies, because "impressions per spot, in spots" is one spot per spot. The unit axis and the audience axis are separate by construction. Semantics: Currencies.