Everything that has shipped, and what it cannot do
Dated to the day the code landed, written from the code rather than from a commit message, and carrying the limits — a release note that only lists wins is an advertisement.
- Updates
- 218
- Areas
- 6/ 6
- Shipping days
- 9
46 updates
Which contest your plan will refuse, and when
HighlightYour plan runs a set number of contests at once, and until now the only place that ever came up was the moment somebody pressed Activate. Build a contest in June for a September start and you found out on the September morning, after the poster went out. Promotions now walks the next quarter over the dates already in your record — what is live, and what is scheduled to go live — and names the first day more contests are due on air than the plan holds. It also names the contests still marked live past their own end date, which are holding slots and doing nothing with them.
It forecasts nothing: every date comes from a contest already built. Paused contests are not counted as needing a slot, because they hold none and only you know whether one is coming back — they are reported separately instead. Nothing is archived or activated for you.
Promotions#Paused, and the clock kept running
Pausing a contest stops it going out. It does not stop its closing date arriving. Promotions now lists the contests that have been paused long enough to be losing a real share of their own run, and — separately — the ones whose end date passed while they were off the air, which nothing was going to mention until the close-out list picked them up weeks later.
Days paused are counted from the last edit to the contest, because nothing records the moment a pause began — so the figure is a floor and the panel says so. A recent pause, or a long pause on a contest that has barely started, is not listed: pausing for a morning is a normal thing to do. Nothing is resumed or archived for you.
Promotions#Take a finished contest's liners off in one press
HighlightFlight check has listed copy that is still switched on for something that finished since the day it shipped, and the only way to act on it was to open each piece and toggle it. The list now has tick boxes and a button. Switching a liner off leaves its flight dates alone — the record of what was booked stays — and putting one back is a single press on the liner itself.
Liners only. A finished imaging spot is carted in your playout system, which this cannot reach, so those rows stay on the list with their cart number for whoever rings traffic — a tick box that changed nothing on the air would be worse than none. Up to 40 liners at a time.
Production#Apply your claim deadline to every prize that has passed it
HighlightYour rules page tells entrants a prize not claimed inside your claim window may be forfeited. Doing it was one button on one win, so in practice it happened to whichever wins somebody happened to open — which is two entrants treated differently under one published rule. The handover queue now has a section for everything past its date, with tick boxes, and forfeits them in one act. Each row shows whether that winner was ever chased before the deadline ran out.
It records the reason as “not claimed in time”, which is the one your rules describe — there is no other reason a run like this can honestly assert about several people at once. A prize already posted or collected is never included. A workspace with no claim window set cannot use it at all, because there is no published deadline for anything to be past. Putting one back is a press on that win's own page, and it can refuse if the unit has since gone to somebody else. Up to 50 at a time, admins only.
Winners#The liner is booked past the day the contest closes
HighlightFlight check has always told you what is on the air and should not be — the morning after, when the fix is a phone call to traffic. It now tells you the day you can still fix it with a date. Any liner or carted spot whose flight runs past the close of the contest it sells is listed while the contest is still running, along with every carted spot attached to a contest that has no end date on it at all, which is the one nothing will ever take off the air.
Copy that STARTS before the contest opens is never on the list — teasing a contest for a week before entry opens is how the job is done. A contest that has already finished stays on the first list instead, so nothing appears twice. Nothing here changes a date or switches anything off: running a promo a few days past the close while the winner is announced is ordinary.
Production#The crew is called for after the doors open
A crew call is not the door time, and the run sheet has recorded both since the crew panel shipped without ever comparing them. Staffing now does: anybody due at the venue at or after the remote starts, and — worse and separately — anybody due there after it has finished. It handles a remote that runs past midnight, which is where every simple comparison of two clock times goes wrong.
A crew row with no call time on it is not on the list: blank means “arrive at the doors”, which is what the sheet already prints. Because a call time and a door time carry no date, a call typed more than six hours before the doors reads as early and is never reported — so this can only under-report. It re-times nobody.
Promotions#Did the finished contests come in on budget
Insights could tell you what a quarter cost and, separately, whether a running contest's shelf was worth more than its budget. What it could not tell you was the first thing anybody asks after a contest ends. Every contest that closed in the range now appears against its budget, with what it actually cost — the price frozen on each win rather than today's — and the retail value delivered beside it.
A prize with no cost recorded is not free, so a contest carrying one can be shown to be over budget and can never be shown to be under one — those are marked rather than guessed at. A contest with no budget recorded is at the bottom and in no total. Internal: none of it reaches a sponsor recap.
Promotions#The draw is about to pick people the award will refuse
HighlightA prize's per-winner limit is on the rules page you publish and is enforced the moment you award. The draw has never read it — so a pool can be full of people who already have their one, the draw picks them, and each one is refused after the name has gone out. The shelf page and the contest's own pool page now say so: which prizes, how much of the eligible pool is already at the limit, and how many entries the draw actually has left to pick from.
Only contests that have really drawn or judged from their pool are compared — a contest with a form whose prizes go out to callers on air is never reported. An entrant is only counted where the record can match them to a past winner the way the draw's own filters match, so this can only under-count. Nothing is removed from a pool and no limit is changed: a per-winner limit is a published term, and the two fixes are opposite decisions about what the contest is.
Promotions#The places you keep going back to
Nine years of first-Saturday remotes at one shopping centre are fifty-four unrelated rows in a diary. Events now has a Venues page: every place you have been booked into, how many times, how many of those were written up as held or missed, which signals worked it, when you were last there — and the address the record usually carries for it, so a booking that has no address is a copy and a paste rather than a phone call.
Places are grouped on the venue name folded for case, spacing and punctuation and nothing else, so two spellings of one venue stay apart rather than two venues being merged. Where one venue carries several addresses the page says so and picks neither — that is either a typing difference or two different places sharing a name, and only you can tell. Bookings that name neither a venue nor an address are counted apart. Nothing on the page edits a booking.
Promotions#Who the appearances page says is presenting
A remote carries a “Hosted by” line that gets published — on the appearances page, in the diary widget, on the feed and in the calendar file a listener downloads — and a crew sheet that never leaves the building. Nothing had ever compared them, so a roster change six weeks out left the public page naming somebody who is not working it. Staffing now lists the remotes where the two disagree.
A remote with nobody on the crew at all is on the panel above it instead, so nothing is reported twice. The name match is deliberately generous — anyone on the crew whose name appears inside the “Hosted by” line counts, whatever their role — so “Dave & Kelly” with only Dave rostered is not a finding, and this can only under-report. Neither answer is assumed to be the right one and nothing is rostered or rewritten for you.
Promotions#Closed, and nobody drawn since
HighlightClosing a drawn pick records that you rang three times and got nobody, and it deliberately does not put that entry back in the pool. What happens next is a redraw — and nothing anywhere could tell you which closed picks never got one. The still-to-reach page now carries them: the pick, the prize it was drawn for, how many units of it are still unclaimed, how long the gap has been open, and the redraw button on the row.
A pick is left alone for three days first, because closing and redrawing are usually two presses in the same afternoon. It only reports a pick whose prize still has units nobody has won — if somebody else took the last one, the record owes nobody a redraw. A pick where a person chose the entry is counted separately and is not on the list: there is no draw for a replacement to stand in for, and the second choice is made on the judging sheet.
Promotions#Who said they were old enough
The minimum age is on every rules page you publish and every entrant ticks a box about it. That box was written on every entry, carried on the API and put in the export, and nothing had ever read it back. The contest rules settings now count it: how much of the pool came through the form and affirmed it, how much was typed in or uploaded — and, the part worth having, every prize that was awarded from an entry with no affirmation behind it, with a link to the win.
An affirmation is not proof of age and the entry form says so. Nothing is refused or voided here — the list is there so you can find the row. Entries typed in by your team or loaded from a spreadsheet carry no box by design, so they are counted apart and are in none of the shares. The share is over form entries only, so a workspace whose qualifiers all arrive on a file is never reported as having asked nobody.
Promotions#Whose voice is on the air
Every take this product has ever cut recorded which voice read it, and nothing ever asked. The voices page now shows the copy that is in flight right now by whoever read its newest finished take — liners and imaging counted apart, with a share each. The finding it exists for is the one archiving a voice creates and nothing said out loud: when an engagement ends and the voice comes off the picker, everything it read keeps playing.
A reading, not an alarm — one voice reading everything is how a station with one imaging voice works. There is no re-cut button: a re-render spends your plan's characters, and whether last quarter's promo is worth cutting again is a producer's call. Copy with no audio at all is in no share, because a liner read live by the host is not a gap in anybody's voice usage. A house voice you cannot restore is marked as one.
Production#What sales asked for, added up
HighlightThe promo request queue had two readings and both were work lists: what is still waiting, and what was approved and never delivered. Neither could answer the first question either department asks — how many did we file, how many got a yes, and how long did an answer take. The insights page now carries the whole intake: the decision mix, the median days to an answer and how many were answered the same day, by client, by signal and by month.
A reading with nothing to press, and it names no colleague — who filed a request and who answered it stay on the request. A request still waiting has no answer time yet, so it is counted on its own and is in none of the shares or medians. The approval rate is over decisions and not over everything filed, so a busy week of new requests never drags it down. A request sold across two signals is counted on both, so the signal rows deliberately do not add up to the total.
Promotions#Who has actually been working the road
Everything the diary knew about the crew looked forward or at one booking: who is on this remote, who is double-booked, which Saturday has nobody on it. The staffing page now carries the other half — every crew call over the last quarter and everything still to come, by the person it went to, with weekends counted on their own axis, how many different signals each person covered and how much of the load each is carrying.
A reading, not a score: it counts the work each person was given and nothing about how it went. It groups on the linked account and never on a typed name, so street-team calls with no login are reported as a figure with the number of names behind it rather than as rows — folding two people called Dave would report one person carrying twice the weekends. A remote that was called off is counted separately and is in nobody's total.
Promotions#On the shelf, and nothing is saying so
HighlightThe flights page already reported copy naming a prize that has gone. This is the same question the other way round: a prize on the live shelf that no liner and no carted spot names. Every other check on that page starts from a piece of copy, so a prize nobody wrote a spot for was invisible to all of them — the dates are right, no day is dark, every signal is covered, and the most expensive thing on the shelf is never mentioned on air. It is on the flights page and on the copy sweep endpoint.
It only asks the question where a contest already writes copy prize by prize and has named most of its shelf — a contest advertising one headline prize is never on it, and neither is a one-prize contest. Running contests only. A prize counts as live when it is unarchived, has units left and is inside its own dates; the day of the week and the daypart are deliberately not read, so a weekday-only prize is not reported as a copy fault on a Sunday. Social posts are not in it: a post carries no prize.
Production#Who had already entered when the rules changed
HighlightA published rules page is generated from the contest, which is its best property and also means it forgets: add a prize in week three and everybody who entered in week one was told something else. The rules ledger has recorded every version since it shipped and each entry records the version it was served under — and nothing had ever put the two together across the workspace. Rules amendments does: which contests changed their published terms after people were already in the pool, how many of those people there are, what moved, and a link straight to the version they read. A prize that is on an earlier version and not on the current one comes first, because that is the amendment somebody rings up about.
It proposes and there is nothing to press — nothing here can un-tell somebody what they were told, so there is no acknowledge button and no note. A contest only appears when somebody had actually entered under the terms that changed; amending before anybody entered is ordinary and is not reported. A prize that was renamed reads as one no longer listed, which the page says out loud: over-reporting is answered by one glance at the version diff, and the opposite would hide the case the board exists for. Entries carrying no served version — a hand-typed entrant, an import — are counted apart. Finished contests stay on it for 180 days.
Promotions#What the claim deadline actually did
The claim window is the one rule on the settings page that your rules page publishes to the public and that takes a prize back off a listener — and it was the only one with nothing read back off the record. This is that reading: of the handovers and forfeits recorded in the last six months, how many landed inside the deadline each win carried, how many after it, how many ended as a forfeit for it, and where in the window a prize typically changes hands. Three findings rather than a score: the window costing prizes, the window nobody enforces, and the sharp one — both at once, which is two entrants treated differently under one published rule.
A reading with no button: it cannot shorten a window, forfeit anything or release anything. Completed handovers are measured over the window they completed in; prizes still waiting are as of today and are in none of the shares, because a prize won yesterday has not failed to be claimed. Where a prize carries its own use-by date that falls first, that is the deadline used — the same rule the queue and the chase email already use. Fewer than 12 outcomes and every share is marked as read off a small sample rather than hidden.
Winners#What your integration is actually doing
The API keys page showed the last forty calls, each with a different id in its URL, and the key review asks one narrow question about the credential itself. Neither could say that a partner's nightly job has been answered 422 four hundred times this week with a perfectly valid key. This groups the week's calls by the endpoint they actually hit — matched against the published reference rather than guessed at — with the error codes each one answered with and how long it took. Calls are marked by whose problem they are: erroring is ours, refused is the credential, rejected is the caller's payload, and only you can tell them.
A reading, not an alarm: nothing here revokes a key, disables an endpoint or rate-limits anybody. A small share of rejections is left alone, because a documented conflict answer is a retry working as the reference describes. Calls to a path this API does not publish are counted as one figure and are worth a link to the docs rather than a fix. The board reads the most recent 4,000 calls and says when it hit that ceiling.
API#How big the audience actually is
HighlightThe listener directory has had a duplicate finder, a frequent-winner report, a household board and an exclusion register since long before it had a total. Audience standing is that total: how many people the workspace holds, when they arrived month by month, and — the half nobody could ask — how many of them can actually be reached. An email address, a telephone number and a postal address are counted as three separate things, because one buys a winner link, one buys a telephone call and one buys a parcel, and plenty of rows carry exactly one of the three. The API answers the same question at /workspace/audience.
A reading, not a work list, and it names nobody. Erased people are counted apart and are outside every share and every denominator — an anonymised row has no contact details by construction, and folding it in would make honouring your own retention policy look like a data-quality problem. Somebody typed in twice is two people here; the duplicate check is the page for that. The scan reads the 20,000 most recent rows and says so when it hits the ceiling.
Platform#Which suppliers actually hand the prize over
HighlightWhen a prize is fulfilled by the sponsor, the station never holds it: the winner is sent to the shop, the box office or the dealership, and from that point nobody at the station can do anything but ring. Until now that was measured in two places and neither could name the business — the workspace median folds every supplier into one row, and the transit sweep reports one late parcel at a time. Supplier handovers ranks the businesses: how many they completed and how long they took, how many they are sitting on right now, and which of those are past the claim window you publish to winners. The same panel appears on each client's own record.
It proposes and scores nobody — nothing is written to the client record, because whether to take another prize from a business is a commercial judgement with a relationship behind it. What completed is measured over your chosen window; what is outstanding is as of today, and the two are deliberately not added together. A business with fewer than five completed handovers is marked, because a service level read off two prizes is not one. A station that does not tick the collection box will read as slow whatever its suppliers do.
Winners#How much copy you wrote
HighlightTen sweeps watch the copy — dates, prizes, cart numbers, lengths, signals, dark days, audio that no longer matches its script — and every one of them says what is WRONG with a piece. None of them could answer the first question in a production meeting: how much did we write last quarter, in which lane, and how much of it got made. Insights now carries the total. Liners, imaging and social posts side by side, counted by when they were written rather than when they ran, with how many reached the air, how many carry a finished take, the month-by-month shape and the split by signal. The rows behind it download as a spreadsheet.
A reading, not a work list — nothing here proposes anything, and there is deliberately no per-person column. Voiced counts only the two lanes that can carry audio: a social post has no take and never will, so it is left out of that share rather than counted as one nobody cut. Copy with no signal on it means every signal the contest runs on, which is how most copy is written, and is labelled that way rather than as a gap. Each lane is read to a ceiling of 4,000 rows in the window, and the panel says when it hit one.
Production#Whether this listener may win, on their own page
The cooldown, the exclusion list and the per-winner limit decide every award in this product, and until now they could only be asked from the call screener — which takes a phone number, because it is built for somebody on the line. Open a listener from the directory and there was a win history, an exclusion pill and no answer to the question the front desk actually gets asked. Their page now says it outright: clear to win, inside the cooldown until a named date with the days left, or excluded since a named date. It reads the same rules in the same order as the screener and the award itself, so the three cannot disagree.
It does not list what they could take right now — that depends on the minute, because a prize can be restricted to a daypart, so it stays on the screener and there is a link. An exclusion has no release date and the panel says so: it is lifted by an admin, not by a clock. A record that has been erased at the listener's request shows that instead, because nothing can be awarded to it again.
Winners#The workspace, added up, on the API
GET /v1/workspace/board answers what a workspace has to do and takes no window, because a sweep is about today. There was no counterpart for how much of it there was: a reporting tool wanting last quarter's totals had to page the promotions, the events and all three copy lanes and add them up itself. GET /v1/workspace/summary is that answer — contests, remotes and copy over a date range, computed by the same functions the insights page draws from, so a dashboard built on it cannot disagree with the console.
Counts of records only: no money, no listener, no entrant, no colleague, and deliberately no per-owner cut. The three windows mean different things and the response says so — a contest is counted in every month its dates touch, a remote by the date it was worked, a piece of copy by the day it was written. Shares are null rather than zero where there is nothing to divide.
API#Which contests need a registration filing
HighlightA contest whose advertised prize value crosses a registration floor has to be filed for before it opens — New York wants thirty days' notice, Florida seven, both counted back from the start date. The console has totalled that shelf and worked out both deadlines since the feature shipped, and it only ever said so on one contest at a time, on that contest's own page. So finding the two contests out of forty that need something meant opening forty. There is now a board under Promotions: every contest still to finish that crosses a floor, worst first, with the total, the jurisdictions and the date each filing is counted back to.
It is a total and a date, not advice — whether a filing is needed depends on where a station broadcasts and how its counsel reads the contest, and nothing here records that one was made. A contest that has already finished is off the board, because moving the start date is the only remedy the console can point at and that has gone. Prizes nobody priced count as nothing, so every total is a floor; contests in that position are counted separately on the board rather than quietly left out.
Promotions#What your own rules took out of the draws
Every draw records how big the pool was and how many entrants the win cooldown and the exclusion list held out of it before the pick. Those three numbers have been printed under each draw since the pool shipped and nothing had ever added two of them together. The contest rules settings page now carries the total: across the last six months, how many people entered, how many the two rules removed, and how many could actually win — with the contests where they bit hardest listed underneath. It sits directly under the reading of who the cooldown is holding, because a projection about the directory and a record of what happened at the draw are different things and can differ a lot.
A reading, not an alarm: a ninety-day cooldown on a daily contest removes most of its pool on purpose. The figures are the ones recorded on each draw, so a pool that has changed since cannot move them, and a contest given away on air has no pool and never appears. Small pools are not reported as heavily thinned — one excluded staff member in a pool of four is twenty-five percent. The most recent 500 draws are read.
Promotions#Ask a whole draw to sign, once
HighlightSettling a draw makes twenty-five winners in one press and sends nobody anything — which is deliberate, because twenty-five automatic emails leaving a console while somebody is still checking the picks is not a thing anybody wants. The link that asks each winner to confirm their details and sign the release was then a separate visit to twenty-five pages, so in practice it did not get sent, and the releases queue filled up with wins under “Never asked”. There is now a panel on that queue listing exactly the wins with an email address and no link yet: tick them and each winner gets their own link to the prize they won and the release to sign.
It never replaces a link that already exists — a winner halfway through signing must not have the URL pulled out from under them, so those wins stay in the queue below with their own resend button. A win with no email address is skipped and counted rather than given a link nobody can be sent, and a release signed while you were ticking is skipped too. Up to 100 at a time, and the panel is for members and above.
Winners#How many contests did we actually run
Every reading in here about a contest has been either a list of what is wrong with one or a slice of them by market, by desk, by signal or by wins. Nobody could answer the first question in a planning meeting: how many did we run last year, in which months, and how were they won. Insights now totals them — on the air by month, split by status, with the contests you built and never activated counted separately — and it says something no screen here has ever said, which is the mechanic: how many took entries online, how many were settled by a draw, and how many had a winner chosen on merit.
A contest is counted in every month it was on the air, so the month rows deliberately do not add up to the total above them. Drawn and judged are read from the draws and the picks themselves and overlap each other, so they do not add up either. A contest archived after it ran counts as having run — archiving overwrites the status, so the record cannot tell it from a draft somebody tidied away.
Promotions#The draw ledger, as a file
The seed and the pool digest recorded against every draw exist for one purpose, which is to be handed to somebody who does not have to take your word for it — a station manager, a group compliance officer, a client's lawyer. Until now the only way to hand them over was a copy button, one draw at a time, on a screen none of those people can open. The ledger downloads, with the seed, the digest, the pool size, what was asked for, what the pool could give, and what became of every pick.
There is no verified column and there will not be one: the ledger recomputes nothing, it publishes what somebody else needs to recompute the draw themselves. No entrant is on it — the entry ids a verification needs come from the contest's own entry download, which is where the personal data belongs. The download carries whatever contest filter the page has on it.
Promotions#Whether the remote actually happened
HighlightA remote was booked or it was cancelled, and there was never a third answer — so the moment a date passed, the record treated the appearance as delivered. The sponsor recap did exactly that, because the date was the only fact it had. It is not a fact: a broadcast that was rained off, or that the client pulled on the Friday night, has a date in the past too, and it was printing on a proof-of-performance sheet as though the station had been there. You can now record what became of one, with a note — “van broke down”, “ran two hours over, big turnout” — on the run sheet itself. There is a panel listing the remotes nobody has closed off, the outcome is on the events download and on the events endpoint, and a remote recorded as not held comes off the client's recap and stays on your own sponsor file, where the conversation about it actually happens.
Recording that a remote did not happen does not cancel it and does not take anybody off the crew — a booking that was on until the morning it rained is a different fact from one that was called off. Until you record the first outcome, the recap prints exactly what it printed before, because silence in a workspace that has never used this means nobody presses the button rather than nobody went. The API can read an outcome and deliberately cannot write one.
Promotions#The campaign that credits nobody
A campaign is sold three ways at once: a flight, a list of signals, and the business it is for. The approved-not-delivered panel already watched the first two. It now watches the third, and the failure is quieter than either: approval copies the sponsor onto the draft contest, and then the business gets archived, or somebody edits the contest, and the credit goes. Every date is right and every signal is right, so nothing else says a word — while the published rules page names no sponsor, the poster prints none, and the client's own recap cannot see their contest at all, because it finds contests through exactly that field.
A request filed without a business named never appears — plenty of promotions are the station's own. The finding is carried on every approved request that has a contest, not only where it is the headline, and the panel says whether the contest credits somebody else or nobody at all, because those are different phone calls.
Promotions#What this workspace is holding
The usage page has always counted characters, because that is what the plan bills. It has never been able to say how much audio is actually sitting in storage — the size of every take and every winner attachment has been recorded since those features shipped, and nothing ever added two of them together. There is now a breakdown by lane: voice reads, produced promos, music beds, cleaned-up calls and winner attachments. It also says what keeping the take history costs, which is the one number on it worth acting on: a liner re-cut nine times is holding nine pieces of audio.
Nothing here is a limit and nothing warns — this is a reading, not a quota. Prize photographs are counted but not weighed, because the record does not store their size, so they sit beside the total rather than in it. The figure is counted from the record rather than from the bucket, so it is a floor. Nothing deletes an old take for you: which cut is current is worked out from the record, not set by anybody, and a sweep would eventually bin the one a producer was about to go back to.
Production#“All day” now says it in your language
A prize restricted to a daypart shows its hours; a prize with no restriction shows “All day”. On seven screens — the prize list, a prize's own page, the prep sheet, the contest page, the contest file, the run sheet and the published rules — that phrase rendered in English whatever language the console was set to, on the line directly beneath a day-of-week label that translated perfectly. The translation existed the whole time and nothing was calling it.
Fixes#Copy playing on a signal the contest is not on
HighlightThe flight check has asked since it shipped whether a contest is silent on one of its own stations. It has never asked the opposite, which is what actually happens when a contest is moved between signals or a liner is cut for the sister station out of habit: the piece keeps playing somewhere the contest is not running. Every date on it is right, the audio matches the script, the prize is on the shelf, the cart is its own and it fits the avail — so nothing else on the page can see it, while the published rules name stations that do not include the one it is on. There is now a panel for it, naming the signals and counting the pieces on each, and a `stray` lane on the copy-flights endpoint for the system that decides where a spot actually plays.
A liner or a spot with no station on it runs wherever the contest runs, so it can never be stray. A contest with no stations at all is a readiness note on its own page rather than a row here, and a station that has signed off is on neither list. Nothing is re-pointed for you: adding the signal to the contest and moving the copy are opposite claims about what was sold.
Production#The official rules, on your own website
HighlightFive surfaces here could be pasted into a station's own site and the sixth was the one a station is most often told to post: the contest rules. The choices were a link off to a page with our furniture around it, or — far more commonly — somebody retyping the terms into a CMS, which is a second copy that stops agreeing with the contest the first time a prize is added. That is exactly what a generated rules page exists to prevent. There is now an embed snippet beside the rules URL on every published contest, rendering the same document the public page renders, from the same record.
It publishes nothing new: it carries the contest's own publish flag, so an unpublished contest shows nothing inside a frame either. Reading it records a version in the rules ledger exactly as reading the page does — a widget that showed the terms and recorded nothing would leave a hole in the history the ledger exists to keep. The frame is not indexed; the canonical page is the address to give out.
Promotions#Two more ways into a pool
The pool could take a thousand people at once from a spreadsheet and could not take one. Both of the arrivals this business actually produces all day were left out: the caller who qualifies on air without winning anything, and the entry that comes in the post where a contest publishes a mail-in alternative. There is now a form for one entrant, on the pool itself. Beside it is the mechanic this format is built on — everybody who won on one contest, into another contest's draw, one entry each however many times they won, with what happened counted apart afterwards.
Both go into the same pool under the same rules as the public form: one person per period, and an email or a phone number is required, because that is what tells one entrant from another. Neither ticks the age box on somebody's behalf and neither records a rules version, because the person did not read one here. The contest's own questions are not asked, so a postal entry to a judged contest arrives with nothing for the judging sheet to read.
Promotions#The prize that left and was never seen again
HighlightThe winners page has shown what is on its way since the fulfilment columns shipped — the newest dozen, oldest first, with no state and no total. That answers whether anything is out. It does not answer the question somebody is asked when a listener rings to say their prize never came. There is now a list of every prize dispatched more than three weeks ago that nobody has recorded arriving, ordered by who can still be asked where it is: the sponsor who was handing it over and never had it packed by the station, the parcel with no carrier and no reference on it, and the one with a tracking number somebody can paste into a courier's page. The frozen value of the lot is at the top.
It only reports where the workspace demonstrably records receipts — at least one dispatched prize confirmed as received in the last year. Without that, a prize that never arrived looks exactly like a box nobody ticked, and the page says so rather than naming every parcel the station has ever sent. Nothing here chases anybody, and there is no "mark as lost": what happens next is a telephone call.
Winners#The handover sweep, for the system that does the posting
Listing winners could always be filtered down to the prizes that went out unsigned. What no filter could express is the judgement — which dispatch has been gone long enough to be a missing parcel, which undispatched prize cannot be sent at all and why, and which unsigned win is still recoverable by asking rather than evidence already lost. All three are now one call, classified exactly as the console classifies them, with each lane's denominator beside it so an empty answer can be told from a workspace with nothing awarded.
Read-only. Recording a handover stays the winner endpoint, which goes through the same rule the console does. The unconfirmed lane is empty by construction in a workspace that never records receipts, and the response carries a flag saying so — an empty lane there does not mean everything arrived.
API#Whether the engine is still answering
Every failed render has recorded what the engine said, on the row, since production shipped — and the only place it could be read was the piece of copy it belonged to. So a producer saw one red take, pressed the button again, got another, and shrugged; nobody could see that every render in the workspace had failed since Tuesday. The usage page now reads the last forty takes and says whether the machine is answering, with the newest error message and which kinds of work it fell over on, so a run confined to promos and beds reads as what it is.
Nothing is retried automatically — a re-render spends the month's characters, so the button stays where the copy is. A run of failures is counted at the head of the sample rather than as a rate, so an outage that ended is reported as an outage that ended. A workspace that has produced nothing is told the reading is empty rather than clear.
Production#What the shelf actually bought
The oldest question in promotions: we put a car up and got nine thousand entries, we put a t-shirt up and got two hundred — which was the better contest. Both halves have been in the record all along and never in the same sentence. Insights now ranks the contests whose entry form has closed by how much advertised prize value it took to pull one entry, with entries a day beside it, so a big pool and a long one are not read as the same thing.
Retail and never cost: what a station paid is not what pulled the entries, and most prizes in this format are donated. A contest still taking entries is on no row — a pool that has not closed has no final figure, and putting it beside one that has would report every new contest as a failure. Rows loaded from a spreadsheet are excluded and counted on their own line. Prizes carrying no value make every total a floor, and the panel says how many.
Promotions#Who may not win, and why, and since when
HighlightThe exclusion list has been enforced perfectly since it shipped — at the award, before every draw, before a judged pick, on the screener and on the eligibility endpoint — and every one of those answers is about one person. There was nowhere to look at the list itself. The directory now has one: everybody held out of contests, why, how long the decision has stood, and a count against every reason the workspace can record, including the ones nobody has used. It also reports the exclusion a draw cannot apply — a listener with no email and no phone is invisible to the pool filter, so they stay in the draw and are refused at the very end, after the name has been read out.
It reads and proposes nothing. An exclusion never expires and nothing on this page lifts one: that stays the admin control on the listener's own record, which leaves an audit row. Rows over a year old are flagged for review rather than reported as faults, because a permanent exclusion is usually correct. Records that have been erased at the listener's request stay on the list and are marked, since there is nobody left to ask.
Promotions#The remote, on the sponsor's recap
A live broadcast from the client's own forecourt is the most expensive line on a package in this format, and the one document here whose whole purpose is proof of performance had never read the diary. It could evidence three Facebook posts and not the four Saturdays the station spent in a car park. The recap now carries the appearances booked on the contests that sponsor bought — the date, the door times, the venue and the signal — and the sponsor file carries them too, with the cancellations the recap deliberately leaves off.
A cancelled remote is absent from the recap entirely, list and count alike: a proof-of-performance sheet must never imply the station turned up somewhere it did not. The objective, the promo items, the on-air mentions, the team notes, the venue's own contact, the host and the crew are on neither document. Only remotes linked to a contest the sponsor bought appear — supplying prizes to somebody else's contest buys no airtime and books no broadcast.
Promotions#Why THIS pool shrank
Two hundred duplicates across a quarter is a fact about a station; two hundred on one contest is a fact about one mechanic, and the person who can change it is looking at that contest's entries page. The workspace reading of why entries left a pool now has a per-contest half on that page — removals by reason on one axis, picks the station could not convert on the other — sharing both the arithmetic and the drawing with the workspace panel, so the two can never disagree about what a removal is.
It takes no date window: a contest is the window. The two axes are never summed — a removal is about the pool's hygiene and a closure is about the station's reach, and one rate over the pair is true of neither. Picks nobody has rung yet are in neither share. The panels render only once something has actually left the pool.
Promotions#Running, with nothing on the air about it
HighlightA contest runs the first of the month to the thirtieth and its liners were all flighted for the opening fortnight, because that is when the campaign was sold. On the fifteenth every check in this product goes quiet: the copy is not still running for a finished contest, nothing is due on air, no signal is missing its cut, and nothing is stuck in production. The contest simply stops being mentioned, and the first person to notice is a listener who does not hear it. Flight check now walks the next fortnight of each running contest and reports the days with no liner and no carted spot in flight at all — which days, from when to when, and how much copy the contest has. The copy sweep endpoint publishes the same lane.
A contest with no copy at all is never on it — that is a readiness note on the contest's own page, and reporting it here would flag every contest on the day it was created. A carted spot with no flight dates runs until somebody pulls it, so it covers every day and a workspace whose imaging carries no dates cannot appear. Running contests only, and it looks a fortnight ahead: a contest that goes quiet in October is a diary rather than a problem.
Production#Why the pool shrank
HighlightTwo columns have recorded why somebody left a contest since the pool shipped — the reason an entry was removed before the draw, and the reason a drawn pick never became a win — and both were printed on the row and added up by nothing. Insights now reads them: how much of the pool was removed and under which reason, and, separately, how many of the picks a draw or a judge made turned into a win against how many the station gave up on. The two are never summed. A removal is about the pool's hygiene and belongs to whoever wrote the contest rules; a closure is about the station's reach and belongs to whoever works the call list.
A pick nobody has rung yet is in neither figure and in no denominator — it is on the drawn-entries work list, and counting it against the station would report a collapse the morning after every draw. A window where nothing has settled has no reach rate at all rather than nought per cent. Every reason in each table is listed even at zero, because the zero is often the finding, and an entry removed with no reason recorded is its own row rather than being folded into “something else”.
Promotions#Switched on, and unable to run
An automation can be turned on and be incapable of ever doing anything. Claim reminders with no claim window have no deadline to count back from, so the sweep matches nothing for ever; a weekly brief in a workspace where every member is a viewer or has opted out has nobody to send to. The automations board used to report the first of those as simply off — a switch the settings page shows as on, described as though nobody had touched it — and the second as never run, which is a question about a schedule that has not come round yet and never will. Both now read as unable to run, above every other reading but off, and each row names the setting standing in the way.
It only says this where the record knows outright. An automation with nothing to do today is quiet, not blocked: a retention window with nothing old enough to empty and a receipt setting on a workspace that has not published an entry form yet are both working correctly and are left alone.
Platform#
3 updates
Does the copy fit the cart
HighlightA spot carries the length it was booked at, and every take produced here is timed by the encoder as it is cut. Both numbers have been on the record since those features shipped and nothing ever compared them, so a :30 with thirty-nine seconds of copy in it passed every check on Flight check: its dates were right, its prize was on the shelf, its cart number was its own, and its audio matched its script perfectly. It arrives at the studio and gets cut against the clock, and the tag — the phone number and the closing date — is the part that goes. Flight check now times every booked spot and says which way it is out, by how much, and whether the figure was measured off real audio or estimated from the script. The copy sweep endpoint publishes the same lane.
Imaging only: a liner has no booked length, a live read has no avail to overrun, and inventing an estimate for one would print arithmetic the station never asserted. A spot booked at no length is not on it either. A measured take is allowed half a second over, because a cart is trimmed to length; an estimate has to be fifteen percent out before it says anything, because that is the spread the characters-a-second figure was itself measured over. A measurement only counts where the audio was cut from the words the script carries now — otherwise the figure falls back to the estimate and says so.
Production#The signals the client actually bought
A request records where the client bought and approval copies that list onto the contest it mints. After that nothing ever looked at it again — so a campaign sold on three signals and built on one had correct dates, a live contest and nothing anywhere to say the buy was short. Approved, not delivered now reads the two lists against each other and names the signals the contest is not on. The names ride on every row it reports, not only that one, so a draft that is also missing two of the three signals it was sold on reads as the worse conversation it is.
One direction only: a contest running on MORE signals than were sold is the station delivering beyond the buy, and putting that in red would be reporting good news as a fault. It does not wait for the flight to be close, because the signal list is decided the moment the contest is built and that is while the client can still be told. Two cases are deliberately silent — a request that named no signal has nothing to be short of, and a contest with no signals at all is already a readiness note on its own page.
Promotions#Sort the handover queue by how often you have chased
The queue has counted every claim reminder since the chase button shipped and could only ever be read oldest-first. Three reminders and still nothing is a different decision from a prize nobody has written to yet, and there was no way to find those rows without opening the export. Prizes still to hand over now sorts by chase count as well as by deadline, and the count shows on the rows that have one.
The pack list and the labels stay in deadline order whatever the screen is sorted by — a printed sheet has one order, and a sort on a screen must not silently re-number a run somebody is halfway through. The page says so when the two differ.
Winners#
38 updates
The address that keeps winning
HighlightEvery eligibility rule here is about one person. The win cooldown holds one listener out, the per-prize limit counts one listener's wins, the exclusion list is a decision about one listener, and Frequent winners is the report those three imply. None of them can see two people at one address winning six times each — which breaks no rule, is on nobody's list, and is the complaint that arrives by email from everybody else. Listeners › Winning households reads the same window by door: one row per address with two or more different winners, the members underneath it with their own counts, what the household took in units and in value, and how many separate contests it came off. It exports as one row per member, for the meeting.
It groups on the address alone — never on an email or a telephone number, because two rows sharing one of those is usually one person entered twice, which is a merge and belongs on the duplicate check. An address is folded for case, spacing and punctuation and nothing more, so a household typed two ways shows as two rows rather than one wrong one, and an address with no postcode and no town is counted apart rather than grouped, since every town has a High Street. It decides nothing: a family that listens together is an audience, and the only action is the exclusion control on somebody's own record.
Winners#Cart collisions on the copy sweep endpoint
Two finished spots carrying the same cart number is one spot as far as a playout system is concerned, and which one plays is decided by whoever last dubbed over it. Every date on both rows is correct, so no other lane on the copy sweep can see it — and the system that has to be told which spot belongs on the number is the one calling. The flight sweep now returns a carts lane: one entry per collision with the spots nested under it, their stations, their windows and their production status.
Only imaging, because a liner has no cart number to read. A collision needs the same signal, overlapping windows or a spot with no dates at all, and at least one of the spots actually carted — a number pencilled onto two half-produced scripts is a plan, not a clash. Up to fifty collisions per response.
API#Signal load as a spreadsheet
The white-space board has downloaded as a file since it shipped; the congestion board beside it did not, because its rows nest — a busy run has a list of contests under it, which is not a line in a spreadsheet. It downloads now: one row per busy run, the signal's own figures repeated down its rows, the contests in the run in a single semicolon-separated cell, and the entry-form clash carried alongside.
A run names up to six contests and the count of any it could not list is its own column, so a truncated list never reads as a complete one. Signals with no busy run still get a row, so the file can be counted against the page. The window and both thresholds are footer rows, because a spreadsheet away from the page cannot infer either.
Promotions#What each signal is carrying at once
HighlightWhite space says which weeks a station has nothing on. It cannot say the opposite, and the opposite is a real question: a signal with no white space at all can be one running five contests in October and nothing in November. Stations › Signal load reads the same quarter from the other end — the most contests on the air together on any one day, when that day is, how long each busy run lasts and which contests are in it. It names one thing outright: the days when more than one published entry form is open on one signal, which is two entry addresses read out on one station on one morning, and an entrant who types the wrong one lands in the wrong pool and never finds out. The airtime endpoint carries the same board on request, so a sales stack can hold both halves of the quarter in one answer.
It is a reading and not an alarm — four contests at once is a good quarter, and nothing here is painted as a fault. Busy runs are listed from three contests upward, because two at once is how the job is normally done. Paused and draft contests are not counted as carried, and are reported on the row so a Monday resume is not a surprise.
Promotions#A client's whole relationship on one page
A sponsor's page listed the contests they bought and nothing else — so a shop that has supplied forty prizes and never booked airtime looked like a client with no history at all. The client file is the sheet you read before a renewal meeting: campaigns bought and prizes supplied together, units given away, what was supplied at retail and what the station paid for it, every request filed against them, and where the recap paperwork stands on each finished contest. It prints, like the contest file and the listener file.
Internal, and it says so on its face: it shows what prizes cost, which the sponsor's own recap deliberately never does — do not hand it to the client. The note somebody wrote when deciding a request is left off it, for the same reason.
Promotions#Handing back a switched-off account's work
Removing somebody from a workspace already unassigns their contests and takes them off upcoming run sheets. Switching an account off did neither — so a person on long leave kept owning nine contests and kept being expected in a car park on Saturday, and the only way to hand any of it back was to delete the membership outright. The team page now shows what a disabled account is still holding and offers one button to release it, with the counts read from exactly the rows the button moves.
Contests land unassigned; nobody is put in their place, because the record has no way to know who should be. Past run sheets keep their name. Admins only, and it refuses an account that can still sign in — handing over a working colleague's work stays on the member list.
Platform#The prizes with no value on them
HighlightA prize's approximate retail value is the number your rules page publishes, the number that freezes onto a winner's record at award time, the number the year-end tax export totals and the number a registration threshold is measured against. Skip the box when you add a prize and it is zero to all of them, and nothing anywhere said so. The prizes page now lists every prize carrying no value, worst first: the ones that have already been awarded, then the ones on a contest with a public page, then the rest. It also counts the wins that already froze a zero — a figure typing the value in now cannot repair, because freezing is the point of that column. A contest's registration panel says the same thing about its own total, and the readiness endpoint publishes the count beside it.
A value of zero and a value nobody typed in are stored the same way, so a prize that really is worth nothing stays on the list. Nothing is blocked by it and no value is ever written for you.
Promotions#What of yours opens without an account
Winner links, sponsor recap links and the two calendar feeds are unguessable addresses that answer to whoever holds them — no login, no expiry. Each was issued one row at a time from the page that owns it, and there was nowhere to see them together. Privacy settings now counts them: how many winner links are live and how many of those are on wins already signed for and handed over, how many recap links exist, whether the workspace calendar has been issued and how many members hold their own. It names one thing outright — a recap link still working for a sponsor you archived, because tidying the directory was never the same act as revoking a URL.
No address is shown, and there is no revoke-everything button: a winner looking for their tracking reference is exactly who that would lock out. Revoking stays on the record the link belongs to.
Platform#The sign-off reaches an integration
GET /v1/promotions/{id}/readiness now carries the contest's sign-off beside its readiness notes, dark-day calendar and registration filing: whether anybody approved it, whether the material terms have moved since, which ones, and the two digests to compare. A new promotion.signoff_recorded webhook fires the moment the standing changes — one event for both directions, so a subscriber that hears about approvals cannot silently miss somebody taking one back. The copy flight sweep gains a sixth lane too: the unfinished spots with no dates on them, which neither date lane could ever see.
Neither the endpoint nor the event names the person who approved it — a key is not a person, and that stays behind the console's own gate. The API cannot sign a contest off, deliberately: the act needs somebody accountable.
API#Who approved this contest — and whether it is still that contest
HighlightContests get run past a programme director, a compliance officer or a group lawyer before they go to air, and until now that conversation lived in an email thread. Every contest now carries a sign-off: an admin records who cleared it, with a note, and the approval is stored against the contest's material terms rather than against its name. So when a prize is added in week three, a closing date moves or a sponsor credit changes, the approval stops reading as current and says which terms moved. There is a workspace board beside the close-out list for the contests still to run.
It records and refuses. Nothing is blocked, paused or unpublished by it — a console that stopped an activation at ten to six on a Friday is one that gets worked around. Because an approval is against the whole published terms, editing the workspace's own general terms, contact details, cooldown or claim window will ask for a fresh approval on the contests that were signed off.
Promotions#The gift-card numbers that went out and cannot come back
HighlightA prize whose units are codes has a second shelf behind the first one, and forfeiting a win returns the unit but never the number — it has already been read out to somebody. Nothing in the product ever said so. The prizes page now sweeps every code pool in the workspace: which are short of the units still to give away, which have run dry, and how many codes are gone with wins that were later taken back. That last figure is money already out of the building, and it is the one shortfall that cannot be fixed by loading more.
Codes are never shown on it — a code is readable in exactly two places and this is not one of them, so each row links to the prize's own code page. It counts and proposes; there is deliberately no control that puts a burnt code back in the pool, because nothing here can un-send a number.
Winners#What time they entered, and which towns the prizes reached
Two readings on the insights page, both off columns that have been filled in since the shelf shipped and read by nothing. The entry clock shows what hour of the broadcast day entries arrive, drawn against the same five bands as the give-away clock above it — so "we give away in breakfast and they enter at lunchtime" is finally a sentence the record can produce. The reach board shows which towns the prizes actually landed in, by units and by people, which is the only evidence a station holds that its audience really is spread across the area it sells.
Both are readings and neither is an alarm: concentration in one town is completely ordinary. Imported entries are off the clock and counted beside it — an uploaded file arrives at the hour somebody pressed the button, not at the hour anybody entered. Wins with no town on the record, and those belonging to listeners who have been erased, are counted apart and are in none of the shares.
Promotions#Whether the pool will fill the draw
HighlightA contest that draws its winners out of an entry pool needs the pool to be bigger than the shelf, and nothing here compared the two. The pool page counted entries and said nothing about prizes; the readiness sweep asked before the contest opened, when the pool is empty by construction; the quiet-forms panel caught only a form taking nothing at all. So a hundred and twenty advertised winners against ninety entrants was discovered on the morning of the draw. Every contest with a published form now carries an entry-pace panel, and the insights page lists the ones worth a sentence — pools heading short while there is still time to ask for entries, pools that closed short, and forms whose intake has collapsed while still arriving.
It proposes and refuses nothing: a small pool is often exactly what a station planned. It will not call a contest short until something has actually been drawn or chosen out of that pool, because half the contests in this format carry a form and give the prizes away on air, and an alarm that is true forever is one nobody reads.
Promotions#What the win cooldown actually holds
The cooldown is a number somebody typed into a settings box once, and it is enforced perfectly — at the award, at the screener, on the API — one person at a time. Nothing ever counted it. The contest-rules settings page now shows how many people in the directory that number is holding right now, what share of everybody who has ever won that is, and how many come free week by week over the next month, with the contests running under their own rule named underneath.
A reading, with no button on it: nothing here lifts a cooldown. It counts people rather than wins, leaves out listeners whose details have been erased, and counts excluded listeners separately — an exclusion is a decision rather than a clock and has no release date.
Winners#The stock-take sheet as a spreadsheet
The stock-take sheet prints, which is right for walking the cupboards with a clipboard and wrong for what happens next — somebody typing the real counts into a spreadsheet for whoever orders the stock. There is now a download beside the print button, in the same shelf order, with the expected count, an empty column to write the real one in, and the unissued codes where a prize has a pool.
The file carries every row where the printed sheet carries the first four hundred: a cap exists to bound what a person can walk in a sitting, and a spreadsheet is not a person. It still records nothing — a short count is either a win nobody entered or stock that never arrived, and both are fixed elsewhere.
Promotions#What time of day the prizes went out
HighlightInsights could tell you what a station gave away, to whom, for which sponsor and at what cost, and could not tell you when — which is the one thing this format is actually sold in. There is now a panel on the insights page showing the same wins as everything else on it, laid out across the twenty-four hours of the broadcast day, with morning drive, middays, afternoon drive, evenings and overnight totalled underneath. "On air all day" is a claim a sales team makes, and this is where the record answers it.
It is a reading and not an alarm: nothing here calls an hour a problem, because most stations in this format give nothing away overnight on purpose. Shares are of UNITS rather than winners — one win of forty tickets and forty wins of one are very different hours to whoever was on air — and the hour is the one on the broadcast clock the deployment runs on, which the panel names.
Winners#Audio that no longer matches its script
HighlightThe flight check has always asked whether a piece of copy should still be running. It now also asks whether the audio says what the script says. Every take this product produces freezes the words it was read from, so a liner or a promo whose script has been edited since is now a row on the flight page — carted ones first — and a notice on the record itself, beside the Produce button.
It re-cuts nothing and proposes nothing: a corrected typo does not need a new take and a changed closing date does, and only a person can tell those apart. Re-wrapped lines and words put into capitals are not treated as changes; punctuation is. Copy produced somewhere else is invisible to it, and takes made before the script was recorded say so rather than claiming to match.
Production#Which API keys should still work
A key acts with the workspace's whole record, and the only thing this page ever said about one was whether it had expired. It now says three more things: the key belongs to somebody who has left the workspace, the key is being refused every time something tries to use it, and the key has never been used at all since it was created. Keys nobody has touched for a couple of months are marked on their own row.
It revokes nothing — every key on the list is still live until an admin turns it off. A key that has simply gone quiet is reported and never warned about, since a quarterly export is a real integration. Only outright refusals count as failing, so an integration sending bad requests is its own business, and a run of refusals with a successful call on top of it is a key that is working now.
Platform#The call list and the release queue, as files
Two work lists that could only be read on a screen can now be downloaded. "Still to reach" becomes a call sheet with a name, a number and how long each person has been waiting — for whoever is doing the ringing, who is often not at a desk. "Releases not on file" becomes a spreadsheet that sorts and totals, for the reader who is not in this console at all.
Each file is the same population as the page it comes from, cap and window included, rather than a second query that could quietly disagree with it. The call list carries no entry answers and no prize: a drawn entry has not been awarded anything yet. Neither file carries what the station paid.
Winners#Contests won on an answer, not a draw
HighlightA station has been able to ask its own questions on an entry form for weeks, and the only thing this console could do with the answers was count them. There is now a judging sheet on every contest: every entry still in the pool, oldest first, with what each person wrote, and a button that makes one of them the pick. It leaves the pool the way a drawn entry does, so it appears on the call list, can be closed out as unreachable and is awarded through the same screen as any other winner.
A judged pick is recorded as a judgement and never as a draw — a draw's seed and pool recompute its result and a choice made by a person recomputes to nothing, so the two are kept apart on the entry, in the export and on the API. The sheet marks the entrants a draw would have filtered out: somebody on the exclusion list cannot be chosen at all, and somebody inside the win cooldown can be, with an admin needed to award through it. Two hundred entries a sheet; the export carries the rest with every answer on it.
Promotions#The pool nobody has drawn yet
Entry closes on the 20th, the draw happens on the 21st, and until now nothing anywhere said a word in between — a forgotten pool only surfaced once the contest itself had ended, by which time the prize was late and the entrants had stopped expecting a call. The dashboard now carries the contests whose entry has closed with nobody picked since, and the ones ending within a few days whose pool has never been drawn from at all, with how long each has been waiting and how many people are in it.
It proposes and draws nothing: a station holding a pool back for a live draw at the end of the month looks exactly the same from in here. A judged pick counts as having drawn, so choosing a winner by hand silences the row. Contests that have already ended are left to the dashboard's loose ends rather than counted twice, and the card shows the six that have been waiting longest.
Promotions#What a contest's dates leave empty
The airtime board says which weeks a signal has nothing on. The promotion form now says it while somebody is typing: tick the stations, set the dates, and any signal left with a week or more of nothing over the next quarter is named underneath, with when the hole starts. It reads the contest as though it were live with the dates on screen, so the answer is about what is being typed rather than what is stored.
It refuses nothing and never blocks a save — a quiet fortnight is very often a decision somebody made. Runs shorter than a week are not reported, because a Friday-to-Monday gap is true of nearly every signal nearly always. Nothing is shown until at least one station is ticked and both dates are set, and a contest whose window falls entirely outside the next quarter is left to the airtime board itself.
Promotions#Whether the things that run on their own are still running
HighlightFive things happen in this console with nobody pressing anything: the weekly brief, the claim-reminder chase, the entry receipt, the entry-retention sweep and the condition sweep that pushes the board down a webhook. Each is opted into and each showed its blast radius before it was switched on — and afterwards nothing anywhere said whether a single one of them had ever happened. Settings now carries all five, with what each last did, how long it has been, and how much is waiting for it right now.
Silence on its own is never reported as a fault: most of these are allowed to do nothing, and a quiet week genuinely produces no brief and no reminders. A row is only flagged where the record can independently say there is work waiting at this moment — which the brief and the condition sweep never can, because both decide for themselves whether there is anything worth sending. Never run reads the same whether the switch went on an hour ago or has never once worked; nothing here records when a setting changed.
Platform#How the station came by what it gave away
Every prize has recorded how it was sourced — bought, traded for airtime, supplied by a sponsor, or already on the shelf — since the day the budget work shipped, and nothing had ever added it up. Insights now splits the window's giveaway four ways with the value beside each, so a department that spent forty thousand dollars is no longer indistinguishable from one that was given the lot. The per-win export carries the same column, so the split can be taken apart by hand.
Internal, like every other cost figure here: it never reaches a rules page, a sponsor recap, a proposal or any public surface. Prizes nobody has classified are counted apart and folded into neither total, because an absence is not a zero. And the sourcing is read as the prize stands today, so re-classifying a prize moves how an earlier month reads — the money beside it does not move, because that is frozen on the win.
Promotions#Every finished contest that still owes something
HighlightA contest's own page has said what it still owes since last week — a pool nobody drew, an entrant nobody rang, a prize in a cupboard, a client who was never sent their sheet. That answers for the contest somebody is already standing on. Promotions now carries the workspace list: every contest that has ended and is not finished with, oldest first, with each loose end linking to the screen that fixes it.
It proposes and does nothing: nothing is archived, closed or sent for you. Archived contests are not read at all, so archiving one takes it off the list without the work being done — a decision somebody takes, with an audit row behind it. The oldest fifty are shown and what is behind them is counted rather than the list quietly ending.
Promotions#Address labels for a post run
The pack list says what goes in each box. What went on the outside of it was an address copied off a screen by hand, forty times, or a mail-merge somebody rebuilt every time — and a mistyped postcode is a prize that comes back. The handover queue now prints the labels, in the pack list's own order, so label seventeen belongs to row seventeen.
Prizes marked for the post only: a prize being collected from the front desk, handed over by the sponsor or sent digitally does not get one. The prize is deliberately not printed on the label — a parcel with the contents on the outside is a parcel that goes missing. A win marked for the post with no address is not silently dropped; it is counted above the sheet, off the printed page, with a link to the queue. A hundred and twenty labels a sheet.
Winners#The weeks a signal has nothing on
HighlightEvery sweep in the console asks about a contest that exists. Nobody could ask the question a sales manager asks first, which is about one that does not: what has 96.3 got on in September? The record held the answer all along — a contest's dates and the signals it runs on — and there was no screen that laid a quarter out per station and pointed at the white. There is now, with the runs of a week or more listed by date, a strip of the whole quarter, and a spreadsheet of it.
It is what the record holds, not a forecast: a day is white because no active contest covers it on that signal, and it stops being true the moment somebody books something. Paused contests and drafts do not count as covering — a paused contest is not on the air — and both are counted on the row so a hole is never a surprise. Runs shorter than a week are counted and not listed: one contest ending on a Friday and the next starting on the Monday is ordinary scheduling. Stations that have signed off are not on it.
Promotions#Closing a contest out
HighlightA contest's page is forward-looking from top to bottom — what is unfinished before it starts, which days it cannot give anything away, how fast the shelf is going, what it has spent — and every one of those panels goes quiet on the day it ends, which is the day it stops being anybody's job. Now a contest that has finished carries a list of what it still owes: entrants drawn and never rung, prizes still in the cupboard, a client who never got their recap, a pool nobody drew, releases nobody collected, stock left on the shelf, and a plan slot it is still holding.
It proposes and refuses: nothing is archived, closed or sent for you, and an ended contest left active is often deliberate. It appears only after the end date — before that the same counts are ordinary states rather than debts — and never on an archived contest. The four with somebody waiting at the other end sort above the three that are only untidy.
Promotions#Whether anybody is still listening
An endpoint can stop working quietly. Somebody rotates a certificate or renames a route, and every event since is attempted six times over seven hours and thrown away while the console looks completely normal — the only evidence was a status column in a list of the last few dozen attempts across every endpoint at once. Each endpoint now carries its own state: delivering, quiet, failing, or not being reached at all, with how many events in a row have used up their retries and when one last arrived.
It reports and does nothing: no endpoint is disabled and no event is queued for later. A delivery still being retried is not counted as a failure, so an endpoint that broke twenty minutes ago reads as failing rather than dead. Quiet is not a fault — an endpoint subscribed to events that did not happen is silent for the right reason.
Platform#White space, through the API
The board a sales stack wants in the same place its rate card lives. GET /v1/airtime publishes each signal's unsold weeks — the date ranges, how many white days there are in all, and whether a gap runs to the end of the window or sits in the middle of a booked quarter. The window and the gap floor are both parameters, and the answer echoes back the ones it used.
A read, permanently: booking a week is creating a contest, and POST /v1/promotions is where that already lives. It carries no contest names — what is on a signal is GET /v1/promotions with a station filter, one call away — and the whole board comes from the same function the console page renders, so the two cannot disagree.
API#The hours with nothing to give away
HighlightA prize can be restricted to part of the day — breakfast only, or the tickets go at four — and every screen printed that beside the prize and never added it up. So a contest could be fully stocked, in window and on today's day mask while the midday jock had nothing for five hours and the overnight jock had nothing at all, and both found out with the microphone open. Show prep now lays the whole broadcast day out hour by hour for the station you are looking at, and names the stretches with nothing in them.
It reads the prizes that may already be given away today, across every contest on that signal — so it is the shelf, not a forecast. An hour counts as covered when any part of it is inside a prize's hours, which means it under-reports gaps rather than over-reports them. Nothing is shown on a day whose shelf is unrestricted, or on one with nothing to give away at all: the second is already on the contest's own page.
Promotions#The remotes a contest booked
A run sheet has always been able to name the contest it belongs to, and nothing ever read it the other way round: a campaign with three live remotes said so on three separate event pages and nowhere on its own. The contest page now lists them — venue, signal, date and door time — and so does the printable contest file, which is the document that exists to say how a contest was actually run and was silent about the half of it that happened in a car park.
Only remotes that were attached to the contest when they were created or edited; nothing infers the link from dates. A cancelled remote is listed and marked rather than dropped, because the record of how a contest ran includes what was called off. The crew, the objective and the team notes stay on the run sheet.
Promotions#Sponsor ids, through the API
Creating a promotion takes a sponsor id, editing one takes a sponsor id, and creating a prize takes a different one — the business that supplied the thing rather than the one that bought the contest. There was no way to learn any of them through the API, so a sales integration could not attach a contest to the client it was sold to and the field simply went unset. GET /v1/sponsors is that list, searchable by name, with the count of contests bought and prizes supplied on each row.
A read. It carries an id, a name and the two counts, and no contact details, notes or recap link — this answers about a business whose details your CRM already holds. There is no create half yet: a duplicate client halves the post-buy report, and there is nothing here to merge two of them back together with.
API#Contests by market, remotes by contest
Two filters the record could answer and the API could not ask. Listing promotions now takes a market, meaning every contest running on any signal in it, folded the same case-insensitive way the market board folds it. Listing events now takes a promotion id, and an event carries its promotion id back — creating one has always accepted the field and never returned it. The market board itself gained a spreadsheet download.
A market is a property of a station, so the promotions filter is a join: pass a station id as well and both have to hold. The market board's download carries the same double count the page warns about — a contest in two markets is on both rows — with the distinct totals on a footer row rather than left to be added up.
API#What is on, market by market
HighlightA station's market has been a box on the station form and a column on the directory since the day it shipped — printed everywhere and asked nothing, anywhere. Stations › Markets is the board it was always for: every signal grouped the way it is sold, with what is running, what is upcoming, what is paused and what ends inside the week on each row. The number it leads with is the one nobody had a screen for, which is how many of your markets have live signals and nothing running on any of them.
A contest running on signals in two markets is counted on both rows, so the column deliberately adds up to more than your running contests — the distinct figure is above the table. Markets typed two ways are grouped as one and the spellings are shown, rather than tidied up on your behalf. Nothing here decides anything: a market between contests is an ordinary state.
Promotions#The signals a contest is not reaching
A liner or a spot with no station on it runs on every signal the contest runs on — and one cut for a particular station runs only there. So a contest on five signals whose copy was cut for two of them is silent on three, and until now nothing said so: the copy list showed rows with station names on them and looked busy, and the contest's own readiness note asked whether there was any copy at all and answered yes. Flight check now names the contests that are on the air and saying nothing on some of their own stations.
Running contests only, and only where copy exists but was cut station by station — a contest with no copy at all is a readiness note on its own page rather than a row here. Stations that have signed off are not counted as silent.
Production#Station ids, through the API
Creating a promotion through the API requires station ids, creating an event takes one, and both list endpoints filter on one — and there was no way to learn a station id through the API at all. The answer was somebody opening the console and copying a cuid out of the address bar into a config file. GET /v1/stations is the directory: name, callsign, market and the workspace's own ordering, filterable by market.
Read-only, and staying that way: creating a station claims a plan slot and archiving one frees it, and neither is a decision a nightly sync should make on your behalf. Stations that have signed off are omitted unless you ask for them.
API#Stranded prizes on the dashboard
The prizes-with-nowhere-to-go list arrived on the winners screens, which are the screens you open when you are already doing handovers. It is now on the dashboard beside the claim-deadline queue, because the two are the same prize seen from either side — one is a winner who has not come in, the other is a prize that cannot be sent — and because the queue shows nothing at all in a workspace with no claim deadline set, which is exactly where this list is most likely to have something on it.
Six rows and the value they represent, with the handover queue a click away. It still refuses nothing and writes nothing.
Winners#
10 updates
Prizes with nowhere to go
HighlightEvery reading here about a handover has been about time — how long somebody has waited, how long you took, when the deadline falls. None of them asked whether the handover can happen at all, and it routinely cannot: a prize marked for the post to a listener who won on the phone and never opened their winner link has no address on it, and the record cheerfully says you are posting it. Winners and the handover queue now both carry the list — posted with no address, sent electronically with no email, a sponsor handing it over with no sponsor named, and the sharp one, a winner with no email and no phone number, who cannot even be asked.
It proposes and refuses nothing: no award is blocked, no prize is forfeited and nothing is written. New wins are left alone for three days, because the winner link usually fills the gap in by itself — except where there is no way to reach somebody, which no amount of waiting fixes and which is reported at once. It looks back a year.
Winners#Your diary, on your own website
HighlightThe appearances page had a link, a share card and a data feed, and no way to put it on a station's own site — the one thing every other public list here has had since the widgets shipped. Settings › Public pages now hands you the paste-once block beside the page's own address. It sizes itself, follows your site's light or dark theme, lists the next six appearances with venue, date, door times and host, and links through to the full diary.
It shows exactly what the page shows and nothing more: your crew list, the venue's own contact, the objective and every team note stay in the console. A cancelled appearance is simply absent from both.
Promotions#Add a remote to your calendar
"We'll be at the county show on Saturday" gets said once, at twenty to eight in the morning. Every appearance on your public page now carries Add to my calendar, which hands the listener the date, the venue as the location, the door times and a reminder three hours before — the same act the entry deadline already offered, about the half of the record that has somebody standing in a car park hoping people turn up.
It is a download rather than a subscription, so an appearance you cancel afterwards cannot be taken out of a calendar it is already in. The file says so and links back to the page, which is the only remedy there is.
Promotions#Ask the winners list a question
GET /v1/winners has always carried whether a release was signed, how the prize travels and whether it has gone — and had no way to ask for any of it, so finding the prizes that went out with nothing signed for them meant paging the whole award record and filtering at your end. Three filters now do it: status, acknowledgment and handover.
They filter on fields every row already carried, so nothing new is published. A value the endpoint does not recognise is refused rather than quietly ignored — a filter that got dropped would hand you a clean-looking list that answered a different question.
API#A sell sheet for a contest, generated
HighlightThe recap has proved what a sponsor got since it shipped. Nothing existed for the conversation before that one, so a contest went into a slide deck by hand — the name retyped, the dates retyped, the prize list from memory. Every contest now has a sell sheet at Sell sheet on its sponsor panel, and on every row of Unsold contests: the flight dates, the stations, the prizes and their values with the shelf totalled, how much copy is written in each of the three lanes, and the addresses a listener actually reaches. Print it or save it as a PDF.
It describes an offer and never results — no entry counts, no winners, no projections of any kind. It also never carries what you paid for a prize, where the prizes are kept, who supplied them, a cart number or your show-prep notes: this sheet leaves the building. If the shelf is empty or no copy is written, the sheet says nothing about it and the console tells you before you print.
Promotions#The contest that ended and whose client never got the sheet
Unsold contests asked what is left to sell. It now asks the other half too: which finished contests had a sponsor on them and no recap sent since they ended. Two answers rather than one, because they are two different phone calls — an account that has never been sent anything, and one whose last sheet stops short of what they most recently bought. The row says when the contest ended, how long ago that was, and whether the sponsor has a shareable link at all.
It reports and sends nothing. Contests are left alone for a week after they end, because when a client should hear from you is your call rather than a date, and the sweep looks back a quarter and no further — past that it is history rather than a job.
Promotions#The command bar reads your copy
HighlightSearch covered contests, prizes, listeners, sponsors, stations and remotes — and not one word of the copy the product exists to hold. All three lanes are now in it, and they match on the WORDS as well as the title: type a line you remember being in a script and the liner, the produced spot or the post comes back, whichever of them it was in. Every heading in the bar is also translated now, which none of them were.
It matches the text as it is stored, so a phrase you half-remember has to be a phrase that is actually in there. A liner that is switched off and a post nobody made are both still found — searching is how you look a record up, not how you list what is running.
Production#The diary previews properly, and reads as data
The public appearances page shipped without the two things a station does with it. Posting the link now shows a picture naming the next few remotes and their venues instead of a bare address, and /live/<your-slug>/feed.json serves the same diary as JSON so a site with its own front end can render it in its own layout. Both come from the page's own query, so neither can show something the page would not — and neither carries your crew.
The feed is cached for a minute and your visitors' own sites may cache it longer, so a remote you cancel is off the page at once and can still sit in somebody's copy for a while. The share card names places and dates and never a person, because a preview is fetched once and kept by whoever fetched it.
Promotions#
46 updates
Breakfast-show prizes stay on the breakfast show
HighlightA prize could be restricted to a day of the week and no finer, so the overnight jock's prep sheet listed drive-time's giveaway and drive-time's listed the overnight one. A prize now carries the HOURS it may be given away in — six presets for the standard dayparts, or type your own. The screener and the eligibility endpoint stop offering it outside them; the prep sheet, the run sheet and the published rules print the hours beside the days instead of hiding the prize.
Times are the deployment's one broadcast clock, named at every control that shows them — a group straddling markets gets one morning. Overnight windows that cross midnight are understood and said so at the control. The dark-day calendar deliberately does not read the hours: a day with a breakfast prize on it is a day with something to give away.
Promotions#The pick you could not reach, replaced on the record
HighlightClosing a drawn entry recorded that you rang three times and got nobody. What happened next was an ordinary draw with no link to the pick it stood in for, so a contest with four prizes and seven draws could not say which draw was for which. A closed pick now offers Draw a replacement: one name, the same prize, every filter an ordinary draw runs — and the new draw records who it stood in for, on both the pool and the API.
A closed pick is replaced once. If the replacement cannot be reached either, close that pick and redraw from it — the chain reads back one link at a time. Closing a pick still never returns that entry to the pool.
Promotions#Where to find us
HighlightYour diary held the venue, the address and the door times, and a listener heard about a remote once, at twenty to eight in the morning. There is now a public page at /live/<your workspace> listing the appearances coming up — the name, the venue, the address, the day and the times, and the station. One address for your site navigation, and it fills itself.
Your crew list, the venue's contact, the objective, the promo items and every team note stay in the console — the settings panel names them before you publish. Cancelled appearances never appear, only the next 90 days are listed, and taking the page down 404s it.
Promotions#What the rules said in March
HighlightThe contest file has listed every version of your published rules since the ledger shipped — a date, a reference and which terms changed. It could not show you the terms themselves. Each version now opens as its own printable sheet: the contest, the eligibility rules, the prize shelf and both free-text blocks exactly as they were served, with the previous value struck through beside anything that changed and any prize that stopped being listed named outright.
It shows the terms as recorded, not a screenshot of the page — the sentences around them belong to this product and change with a release. An empty ledger means nobody has loaded the public rules page, never that the terms are unchanged.
Promotions#The recap now carries the copy that ran
A sponsor recap has always counted the liners and imaging written for a contest and never showed one, which is the half a client actually asks for. Every script that carried the contests a sponsor bought is now on the sheet, in flight order, with its kind, its dates, its station and its length — on the console page and on the shareable recap link alike, because both render the same document.
Copy for contests the sponsor SUPPLIED a prize to is not on it: they did not buy the airtime. A piece the record cannot confirm went to air is marked rather than dropped, and cart numbers are never on it — that is your playout system’s reference, not the client’s.
Promotions#Finishing a handover through the API
POST /v1/winners could award a prize and nothing on the API could finish the job — how it travels, whether it has gone and whether the winner has it were writable only by a person on a console screen. PATCH /v1/winners/{winner_id} records all of it, and GET on the same path reads one win back. A warehouse system, a front-desk kiosk or a courier callback can now close the loop it opened.
It refuses a forfeited win, and neither timestamp is ever restamped: a retried message cannot claim a parcel left twice, and collected is write-once because reversing a handover is a decision a person makes. Carrier and tracking reference are writable and come back on no response, no webhook and no audit row.
API#An entry poster, generated
HighlightThe QR code has been downloadable since it shipped, which left somebody pasting it into Word beside a retyped contest name and a prize list they remembered. The poster is now generated from the record: the contest, the stations, the prizes and their values, the entry address in plain type, the code at scanning size, the closing date and the official rules URL in the footer. Print it, or save it as a PDF.
It needs the entry form published — a poster carries one address and it has to work when somebody scans it in a car park. It names the rules page rather than printing the terms: material terms in six-point type on a wall is the disclosure failure, not the fix.
Promotions#The request queue now tells you it is waiting
HighlightA promotion request has always been visible on exactly one screen, to whoever thought to open it — so a request filed for a flight a fortnight out could sit until the flight date arrived with no contest behind it. Requests waiting on a decision now appear on the dashboard, in the weekly brief and on the daily condition sweep, sorted worst first: the ones whose flight has already started, the ones starting this week, and the ones that have simply been open a while. The requests page marks them too.
It reports and refuses nothing. There is no auto-decline and no expiry — a request going quiet is usually a deal that went quiet, and the answer is one somebody gives a client.
Promotions#A decision reaches the person who asked for it
Approving or declining a request stored the answer and told nobody: the person who filed it saw the decline note only if they went back and opened the row. Both decisions now email the requester — the verdict, the note where one was written, and a link to the request. The confirmation on screen says which happened, including when nothing was sent.
Nothing is sent when the person who filed the request is the person deciding it, or when they have left the workspace. If the message cannot go out the decision still stands, and the console says so rather than implying it was delivered.
Promotions#The intake queue on the API, and a webhook for the answer
GET /v1/requests lists the promotion requests waiting on a decision, each with how long it has been open and how close its flight is — the same classification the console reads, so an integration cannot disagree with the station about which are late. The new promo_request.decided webhook fires when programming answers one, carrying the decision and the draft promotion an approval created.
The endpoint publishes the pending queue only: a decided request's outcome is already here as the promotion it minted. Neither the endpoint nor the webhook carries the decline note or names the colleague who filed the request.
API#What the prizes cost, across the whole workspace
Every money figure in Insights was value delivered — the number a sponsor is shown. What a station actually spends had no reading above one contest's own page. Insights now reports cash out the door beside value delivered for the chosen range, and lists the running contests whose shelf is worth more than the budget set for them.
Cost is optional on a prize and blank does not mean free — most prizes in this format are trade or sponsor-supplied. The cash figure is a floor, and the share of wins with a recorded cost is printed beside it. None of this reaches a rules page, a recap or any public surface.
Promotions#Carry a shelf over to the next contest
HighlightA contest ends with four t-shirts and two vouchers left, and they go on the next one. Until now that meant re-typing the prize on the new promotion and remembering to reduce the old one, which nobody does — so the finished contest reported stock it no longer had, forever. The prize page now moves whatever is unclaimed to another contest in one act: the units, the cost and sourcing, the supplier, the use-by date, the photograph, and any unissued codes.
The wins already recorded stay on the original prize, which is the point — a finished contest's record is not rewritten by tidying up. The availability window is not carried either: the new prize inherits the dates of the contest it lands on, because the old contest's days are in the past.
Promotions#A stock-take sheet for the prize cupboard
Every count in the console is worked out from the winner record, which is why it can be trusted — and it is why nothing here can tell you whether the eleven t-shirts it counts are eleven t-shirts. Prizes walk. The new sheet lists everything unclaimed in the order your shelves are in, with what the record expects and a blank box to write what is actually there, ready to print. Leftovers from contests that have already finished are on it and marked, because those are the ones nobody has looked at.
It records nothing. A short count is either a prize handed over without being logged — in which case add the winner, so the record still says who has it — or stock that never arrived, which is an edit once you have asked the supplier.
Promotions#Pull the whole board over the API
HighlightEverything that watches for trouble — a contest launching with unpublished rules, a prize nearly out, a claim past its deadline, a contest that ended and was never closed off, a remote with nobody on it, a day with nothing to give away, a promo still carted for a finished contest — could only reach a machine as a daily webhook. GET /v1/workspace/board is the same board, asked for instead of sent, for the script or the deploy gate that has no address for us to post to.
It is the identical payload the workspace.sweep webhook carries, with one extra field: a quiet flag first, so a caller can tell there is nothing to do without reading eight lists.
API#Your winners list, as data
The public contests index has been available as JSON for a station that would rather render its own cards than embed ours. The winners page now is too, at the same address with feed.json on the end — the same winners, under the same switch, from the same query, so it can never name somebody the page would not.
The feed carries initials where the page prints a first name. A page is rebuilt every time somebody opens it, so withdrawing consent takes it down at once; a feed is cached in your website's system, and every copy of it is somewhere a withdrawal cannot reach.
Promotions#What the contests pulled
HighlightInsights has always reported the giving-away half: value awarded, winners, prizes given. It now reports the other one. Entries and distinct entrants over the same range you already picked, with the period-on-period comparison the rest of the page carries, which contests pulled and how many different people that was, how entries arrived, and what became of them — drawn, won, removed, counted separately.
Entrants counts distinct contact details, so an entry the retention sweep has emptied counts as its own entrant — the page says so, and says how many of them there were, rather than quietly dropping them.
Promotions#The entry form that is open and taking nothing
A published, open entry form that has taken nothing for a week now says so on Insights. A URL read on air with a digit wrong, a link on the station site still pointing at last quarter, a window that closes on a date typed in the wrong year: all of them render a perfectly good page and an empty pool, and none of them used to be visible anywhere.
It proposes and changes nothing — a genuinely quiet week looks identical from here. The row carries the whole pool and the date of the last entry, so a form that has never taken anything reads differently from one that stopped.
Promotions#What everybody answered
HighlightYour own questions on the entry form now have their answers counted, on the pool's own page. Every option is listed including the ones nobody picked, a tick box reports both ways, and a free-text question lists its commonest answers with the number of different ones beside it. A question you have since reworded is headed by its wording today; the answers keep the wording people saw.
Counted over the whole pool up to 20,000 entries, and the panel says which. An entry that arrived before you added a question was never asked it, so a blank is not the same as a skipped answer — the panel says that too.
Promotions#Forty prizes out the door in one act
HighlightThe handover queue has a screen of its own. Work the queue opens the whole outstanding list, ticks the prizes that have gone, and records the run — one method, one date, one press — instead of forty page loads. Rows with nowhere to post to are marked, because a prize down for the mail with no address is the one worth seeing before you pack it.
Up to 100 at a time, and the button says so. Carrier and tracking stay on each win, because a tracking number identifies one parcel and stamping it across thirty would be writing something false into thirty records. A prize collected at the station is never dispatched, so that method is not offered here.
Winners#Still to reach — everybody a draw picked and nobody has rung
Drawn, no prize, no outcome recorded: that has been a number on the dashboard and a number on each contest's own page, and nowhere to work it. Now it is one list across every contest, oldest first, with the entrant's phone number and email on the row — award them, or say what happened, without opening three pool tables to find twelve people.
No bulk control. Closing a pick out is a statement about one person — you rang three times, or they said no thanks — and a button that recorded that against fifteen at once would be inventing fifteen phone calls. Closing one does not put it back in the pool.
Promotions#What is still on the air that should not be
HighlightFlight check is one page for the copy nobody is watching. It lists liners and imaging that are switched on past their own dates or attached to a contest that ended, was paused or was archived — with the cart number on the row, because pulling a spot means telling traffic a cart number — and, looking the other way, the spots due on air inside three weeks that are not finished, plus the ones marked complete with no cart number at all.
It reports and changes nothing: a station really does run image sweepers with no end date, and a paused contest is often paused for a day. Up to 200 rows each way, and the count of copy with no dates to judge is stated rather than hidden.
Promotions#The weekly brief now mentions the promo still running for last month's contest
“Still on the air” joins the Monday brief, naming the copy that outlived what it sells and how long it has been wrong for. A week with a dead promo in it is not a quiet week, so it counts against the all-clear that keeps a brief with nothing to say from being sent.
The backward half only — a spot due on air and not produced stays on Flight check, because that is a job with a date rather than something already wrong. As with every section, it names a handful and links to the rest.
Promotions#Liners and imaging on the API — the traffic handoff, from our end
HighlightGET /liners and GET /imaging publish what plays, on which station, between which dates and under which cart number — with the script on every row. Ask either of them `on=<date>` and you get what should be on the air that day, which is the question a scheduler asks: run it daily and copy that has come off stops being scheduled.
Read-only. Nothing writes a cart number back yet, because whether a cart is claimed before production or stamped after it is a decision about your integration rather than about us. A liner with no station airs on every station its promotion runs on, and filtering by station keeps those.
API#A prize is something you can open now, not just edit
HighlightEvery prize has its own page: units left against units claimed, whether it can be given away today and why not when it cannot, both of its clocks — the days you are prepared to hand it out and the date the thing itself dies — the code pool, who has won it, and the trail of what has been done to it. The audit trail, the weekly brief and the command bar all open it now instead of an edit form.
Everybody can read it, including viewers, and nothing on it changes anything. Cost, storage location and the supplying sponsor are on it and stay internal — no public page, no sponsor recap and no API response carries them — and no card number is rendered, only how many are left.
Promotions#Ask whether a caller can win, before you tell them they have
HighlightGET /eligibility answers from a phone number, an email or a name: is this person on your exclusion list, are they inside a cooldown, and which prizes could they take right now. It is the console's own call screener, reading the same rules in the same order the award enforces them — so your phone system, your text-to-win bridge or your own dashboard can check first instead of finding out from a refusal.
It writes nothing and holds nothing, so a clear answer is true at that instant and the award is still what enforces it. It is not a listener directory: a match carries a name and a town, never an email or a phone number.
API#Load your directory — and your staff exclusion list — from a file
HighlightImport listeners from a spreadsheet: a directory from another system, a club list, or the HR list of everybody who may not win. A row that matches somebody already here fills in their blank fields and never overwrites one you typed, so a staff list lands the exclusion on the record the award flow actually reads.
Admins and owners only, up to 2,000 rows a file. Every row needs an email or a phone number to be matched on, an unrecognised exclusion reason refuses the row rather than importing somebody as eligible, and a listener whose record you have erased is left untouched and reported.
Winners#Send the sponsor their recap
Email the recap link straight to the sponsor from the sheet itself, with an optional line of your own. What arrives is the live page rather than a snapshot, so a contest still running shows where it has got to whenever they open it — and the recap page says who sent it last and when.
Admins and owners, to the address on that sponsor's own record and nowhere else. There is no recipient box and no schedule: it goes when somebody presses it.
Promotions#Take your whole workspace with you
HighlightOne button, one archive: every contest, prize, winner, listener, entry, draw, sponsor, station, liner, imaging item, remote and audit row as a spreadsheet, plus a README explaining every column and how to recompute any draw from its seed. Take a backup, move to another system, or answer a licence renewal that wants the year in one place.
Admins and owners only, and every export is logged. Prize codes, live winner and recap links, and uploaded files are deliberately not in it — the archive lists what is attached rather than carrying it.
Platform#Show your prize shelf on your own website
HighlightA fourth widget, and the one people actually stop for: the prizes across every contest you are publishing, with their photographs and values, each linking through to the contest it belongs to. It comes on with your contests page and needs nothing else switched on.
Names, values and photographs only — never how many are left, what a prize cost you, or where it is kept. Up to eight prizes per contest, which is what your entry form already shows.
Promotions#What is left to sell
A page for the sales side of the desk: contests running or still to come with no sponsor on them and the retail value of what is on their shelves, and sponsors who have not backed anything for four months. Both are proposals — a station promotion with no sponsor was often never for sale.
It reports and does nothing: no row is a task, and the two lists are counted apart because selling a contest and ringing a quiet account are different jobs.
Promotions#Liners and imaging as a spreadsheet
Both copy lists now download as CSV, filters and all — with the scripts themselves, the word count on a live read, and the cart number on a produced item. They were the last two record types here with nowhere to go but the screen.
It is a spreadsheet, not a playout-system import format. Building one of those needs a real station's schema rather than a guess at it.
Production#Put your contests on your own website
HighlightThree widgets you paste once. The entry form itself, so a listener enters without leaving your site; a list of what is running now, which updates itself as contests come and go; and your recent winners. Each is a block of HTML the console writes for you, in dark or light, and each shows exactly what you have already published here — publish a contest and it appears, take it down and it goes.
A widget carries the same gate as the page it mirrors, so an unpublished contest shows nothing at all. The entry list is capped at a sidebar's worth, with a link through to the full page.
Promotions#Duplicate a remote, crew and all
The Saturday mall appearance and the Friday club night are the same run sheet every week — venue, address, contact, objective, promo items, and five people with their call times. Duplicate copies all of it to the same day next week, and lands you on the new sheet with the double-booking check already run.
The date moves seven days and the copy is scheduled even if you duplicated a cancelled one. Anything other than weekly is a date you change on the page you land on.
Promotions#Stock a shelf from a spreadsheet
A sponsor sends forty vouchers as a list. A promoter sends the ticket allocation as a list. Both used to be retyped one prize at a time. Prizes now import from a CSV — values, cost, stock, per-winner limits, supplier, location, expiry — and the columns are the ones this page already exports, so a file you downloaded, edited and saved goes straight back in.
An imported prize is available every day of the week: the days column exports as words for a person to read, and guessing them back would put a prize on the wrong days rather than fail. A prize whose name is already on that contest is skipped rather than updated, so importing the same file twice cannot double your stock.
Promotions#Award a whole draw at once
HighlightA draw for twenty-five t-shirts picks twenty-five names in one press, and handed them over one form at a time — twenty-five trips that asked you to decide nothing, because the draw had already decided it. Each draw now offers to award everything it picked and has not yet settled, onto one prize, and reports what happened to each name.
It never waives the cooldown. Awarding a repeat winner is a judgement about one person, and the single-award form is where it stays; picks held out by the cooldown, on the exclusion list, or past the end of the shelf are counted and left for you. Nobody is emailed — the winner link is issued on each row and sent from there.
Winners#A code people can scan
HighlightYour rules page, your entry form, your contests page and your winners page have all been addressable by a link you could copy. Nobody types a link off a poster. Each of those now comes with a QR code beside the URL and a download for print — and the run sheet for a remote carries the entry code large enough to cut out and tape to the front of the table.
Only pages you have actually published: a code is a printed thing, and a printed pointer to a page that is not up yet cannot be corrected afterwards. The winner link and the sponsor recap link deliberately have no code — those URLs are credentials, and a credential on a poster is a credential given to everybody who walks past.
Promotions#Entries close Friday, in their calendar
The one fact a contest loses entries to is the deadline, and every place this product stated it was a screen the listener had already walked away from. The entry form now offers to put it in their own calendar — the closing date with a reminder the day before, or, on a contest somebody may enter once a day, a daily note for as long as it runs.
Offered while entry is open and before it opens, and not after it has closed — a reminder about a date in the past is a broken link with a bell on it. It carries the contest name, the dates and your links, and nothing about the person downloading it: no account, no tracking, nothing written to the pool.
Promotions#What an erasure does not reach
Erasing a listener clears the name, the contact details, the address, the notes, the typed signature and their contest entries. It never touched the files uploaded against their wins, and it never said so. It now counts them before you press the button, in the confirmation, and in the audit entry.
It still does not delete them, on purpose: a signed release is your own record that a prize was lawfully awarded, and a scan of one is the same kind of row here as a photo of the handover — nothing can tell them apart. If a request should reach those files, open each win and remove them individually first.
Winners#Which prizes have a photo
A workspace with forty prizes had no way to see which of them had been photographed short of opening each one. The prizes list now marks the ones that have a picture, and the API's prize record carries the same fact.
The mark, not the picture: nothing here resizes an uploaded image, so forty thumbnails would be forty full-size photographs downloaded to answer a yes-or-no question. The image itself is still served from one address, behind the contest's own publish gate.
Promotions#The give-away clock
HighlightThree hundred t-shirts, four a week, and nobody notices until the last week of the contest — because every number on the screen was fine. The give-away clock reads the one thing none of them did: your rate against the days you have left. Insights lists every contest running now with the sentence that matters (“on this rate 240 units are still on the shelf at the close”, or the date it clears), and the contest's own page carries its own.
Live contests only — an upcoming one has no elapsed days to measure from and a finished one is already on the dashboard's loose ends. It reports and never acts: a contest deliberately holding stock back for a finale week looks exactly like one nobody scheduled, and the clock cannot tell them apart. The working is printed beside the forecast so you can check it.
Promotions#Compared to what
Insights has had a range picker since it shipped and never answered the question a range picker implies. Prize value, winners, prizes given and average value now each carry how they moved against the period before — and a month still running is compared against the SAME number of days of the month before it, not against the whole of it, so a partial month does not report a collapse every time you look at it.
All time has nothing before it, and a workspace with no comparable earlier period gets no percentages — in both cases the page says so rather than leaving four blanks that read as “no change”. A period that was zero shows nothing either: there is no honest percentage rise out of nothing.
Promotions#The winner sees what they won
HighlightPrize photos went onto the entry form and your contests page, and skipped the one page where “here is what you won” belongs. The winner's own link now leads with the picture, above the prize, the value and the date — including on contests you never published a rules page for.
Only the holder of that winner's own link, and only for the prize on it: the link cannot be pointed at another prize, and a win you have taken back loses the photo along with the page. Archiving a prize after the contest does not blank it — tidying your shelf is not the same as unpublishing somebody's prize.
Winners#Deleting a win takes its files with it
Removing an attached file from a win always deleted the file itself. Deleting the whole win did not — the record went and the scanned release, the affidavit and the handover photo stayed in storage. They are now removed with the win, and the audit entry records how many went.
It applies from here on. Files left behind by a win deleted before this are still collected when the workspace is deleted, as they always were.
Fixes#
4 updates
A prize you can see
HighlightEvery public page this product publishes described a prize in words and a number. Now a prize can carry a photo, and it appears where it does the work: on the entry form beside the name, and on your contests page. Upload it on the prize itself — JPEG, PNG or WebP — and it is published with the contest, so there is no second switch to remember.
A photo is public exactly when its contest is: publish the rules page or the entry form and the picture goes with it, and nothing is served for a draft. Files are stored as uploaded — up to 8 MB and 8,000 pixels a side — and nothing is resized, so a photo straight off a phone is worth scaling down first.
Promotions#The entrant hears back
HighlightSomebody entering a contest got a green line on a page and nothing else — no confirmation, and no copy of the rules they had just ticked a box about. Turn entry receipts on in Contest rules and every online entry with an email address on it gets one message: the contest, when entry closes, a link to the official rules where you have published them, and how to reach you.
One message per entry and never a second, and it only ever goes to somebody who typed their own address into your entry form. Entries you import from a file or post through the API are never written to. Off until you switch it on, and the panel says how many entry forms are live before you do.
Promotions#Send the recap instead of printing it
The sponsor recap has been printable since it shipped, and an account executive would rather send a link. Issue one from the recap itself and the sponsor opens the same sheet with no account and no sign-in — and because it is live rather than a PDF, somebody opening it next month sees where the contest actually got to.
It shows what the contests delivered: value awarded, value on the shelf, entries, winners and copy, by promotion. It never shows what a prize cost the station, and it names no winner and no entrant. Issuing and turning it off are admin acts, and a new link stops the old one working.
Promotions#Record a signed release without leaving the queue
Recording a release signed at the counter meant opening each win in turn, which is the wrong shape for somebody working down the handover list on a Saturday afternoon with a stack of signed forms. The control is now on the row, beside the chase button, and it is the same one — same refusals, same record of who typed it in.
It appears only on rows with nothing signed yet. Removing a recorded release stays on the win's own page, where the rest of that record is.
Winners#
4 updates
Is the weekend staffed?
HighlightThe console could tell you whether one remote had a double booking on it, and only if you opened that remote. Staffing asks it of the whole diary: every scheduled event for the next three weeks, the ones with nobody rostered, and everybody down for two in one day. It is on the events toolbar, the dashboard raises it when there is something to raise, and the Monday brief now carries it — so a Saturday with an empty run sheet stops being something you find out about on Saturday.
It reports and refuses nothing: one person genuinely can work a morning appearance and an afternoon remote. Clashes are checked on the account, so a typed street-team name is counted as crew but never as a double booking — and the page says how many rows it could not check.
Promotions#The winner who signs at the counter
HighlightA release could only ever be signed on the winner link, which is no use at all for the listener standing in reception. Every win now prints a release form — the prize, its value, the claim deadline and your own release wording, all generated from the record — and once it is signed you type the name in and the win carries a real signature. The publicity box is on the form, separately, exactly as it is online.
The record says which way it was signed: on the link by the winner, or on paper and typed in by a member of staff. They are deliberately not the same fact, and a recorded release can be taken back by an admin while one the listener signed themselves cannot.
Winners#Your own calendar feed
The workspace calendar feed carries the whole department's diary and only an admin can issue it. This is the other one: your remotes, at your crew call rather than the door time, plus the start and end of every contest you own. You create it yourself from the calendar page, subscribe from Outlook or Google, and turn it off whenever you like.
Anyone holding the URL can read what you are working without signing in, which is what makes a subscribable calendar work at all — issuing a new URL kills the old one immediately. It covers one workspace: switch workspaces and you get a separate feed.
Platform#Unload a code pool in one go
Codes could be loaded five thousand at a time and removed one at a time, so pasting the wrong block meant a very long afternoon. There is now one control that clears every code nobody has been given. The codes page also explains the sum that never used to add up: a forfeited win gives the unit back to the shelf and keeps the code, and the page now says how many are in that state.
It can only ever remove codes that have not gone to anybody. A code a winner has been shown is the record of what they were given and stays, forfeited or not.
Promotions#
3 updates
Who is working the remote
HighlightA run sheet said where the remote was, when the doors opened and who to ask for at the venue — and never once said who from the station was going. Every event now takes a crew: anybody with a login, or a typed name for the street team, each with what they are doing and their own crew call. It prints on the printable sheet, it is a column in the events CSV, the list filters to Mine, and if somebody is down for two things on one day the console says so on the row.
The double-booking warning reads the account, so it sees people who have a login and not a typed street-team name — matching names would be a guess. It warns and never refuses: one person genuinely can do the 10am mall appearance and the 4pm remote.
Promotions#The weekly brief says which of it is yours
The Monday brief posted one undifferentiated work list to everybody, and each person had to work out which lines were theirs. Now that contests have owners and remotes have crews, each copy sorts your own contests to the top and marks them, opens with the remotes you are personally down for this week, and says how many items it left out of each section instead of quietly stopping at five.
It reorders and marks; it never hides. Everybody still sees every outstanding contest, prize and overdue handover, because a work list that showed each person a different subset would be a team all believing they had seen the queue.
Promotions#Leaving a workspace hands the work back
Removing somebody from the team left their name on the contests they owned and on the run sheets they were down for, until the next time a person happened to edit one. Removal now unassigns their contests and takes them off upcoming remotes in the same step, and says how many of each it changed.
Contests land as unassigned rather than being handed to somebody automatically — the promotions list filters by Unassigned so they can be picked up. Past run sheets keep naming whoever worked them.
Platform#
11 updates
One public link for every contest you are running
HighlightEvery public URL this product issued was per-contest and carried an id nobody can read out on air, so the contests page on a station website had to be re-edited every few weeks. Publish the contests page under Settings → Contest rules and you get one address that never changes: it lists what is running now with the dates, the stations, the sponsor and the prizes, links each one to its official rules, and offers Enter where entry is open.
It publishes nothing new. A contest appears only where its own rules page or entry form is already published, so the switch adds an address rather than an audience — and a contest that is paused, in draft, or finished is not on it.
Promotions#Whose contest is this
A department of four with twenty live promotions had nowhere to write down who is running which one. Every promotion now takes an owner — anybody with a login to the workspace — shown on the card and on the promotion itself. The promotions list filters by Mine, by Unassigned, or by any member, the filter carries into the CSV, and a copy made with Duplicate keeps the same name on it.
It is a name, not a permission: every member can still edit and award on any contest, and nothing anywhere is refused because of it. If somebody's account is deleted, their contests stay and go back to unassigned.
Promotions#Read the audit trail where the record is
HighlightActivity showed the newest thirty events as raw ids and stopped. It now filters by area, by member and over a range up to everything ever recorded, names the record each event touched and links to it, pages backwards, and downloads as a CSV. Promotions and winners carry a History panel of their own, so “who changed this, and when” is answered on the record instead of by scrolling a feed.
A record's History shows what was recorded against that record: awarding a prize under a contest is recorded against the win, and appears there. The download carries the action, the target and who did it — never the free-form detail attached to an event.
Platform#Three more webhook events
winner.forfeited fires when a win is taken back and its unit returns to the shelf, with the reason — the other half of winner.recorded, and what stops a fulfilment system posting a prize the station has already given to somebody else. winner.dispatched fires when a prize leaves the building. promotion.rules_published fires when a contest's rules URL starts answering, which is the signal a station site waits for.
winner.dispatched fires once, on the transition, and never when the row is edited afterwards. Nothing fires when a win is restored or a rules page is taken down — both are deliberate, and the webhooks reference says why.
API#Ask your own questions on the entry form
HighlightThe entry form collects a name, a way to reach somebody and the age box — and every station wants to ask one more thing. Add up to five of your own questions on the promotion's Online entry panel: a short answer, a pick-one list, or a tick box, each optional or required. Answers show under the entrant in the pool, come through in the entry export as their own columns, and travel with Duplicate when you run the contest again.
Five questions, and an answer decides nothing: it is never used to dedupe an entrant, never used to filter a draw, and is not part of the published rules. Answers are personal data — the retention sweep empties them with the rest of the row, and so does erasing a listener.
Promotions#Which version of the rules each entrant agreed to
HighlightThe entry form's box says the entrant has read the contest rules — and the rules page is generated, so adding a prize in week three changed what everybody who entered in week one was told. Every entry now records the published version that was in force when it arrived. The pool page breaks the contest down by version, and the promotion's rules panel says how many people in the pool came in under terms the page no longer serves.
It records the version the public rules page had actually served. Entries taken before a station published its rules, or on a published page nobody has ever loaded, are counted and labelled as exactly that — and nothing is ever removed from a pool because of it.
Promotions#Everything you hold about one listener, on one page
HighlightThe console could erase somebody at their request and could not tell them what it held. Listener file prints the directory record, every prize won with its dates and frozen values, the handover and the release, every contest entry that matches their contact details with what they answered, and what has been recorded against the row — ready to print or save as PDF from the browser.
Admins and owners only, and opening one writes an audit entry. Entries are matched on the same contact details the entry form dedupes on, so somebody who entered under a different address will not appear — join the rows in Duplicates first. Which member of staff did what is deliberately not printed.
Winners#A prize can be the code itself
HighlightGift cards, download codes, ticket references — prizes where the prize IS a number that used to live in a spreadsheet. Load them against the prize, one per line, and each one becomes a unit of stock: the next win takes the oldest unissued code automatically, the shelf shows how many are left, and the winner sees theirs on their own winner link once they have signed. Anything after a tab or a comma on the line is kept as a note beside the code, so pasting two spreadsheet columns works.
Codes appear in exactly two places — the prize's own codes page inside your workspace, and the winner's link. They are on no export, no public page and no API response, and they are never put in an email. Forfeiting a win returns the unit to the shelf and does NOT return the code: a number somebody has already been shown is spent.
Promotions#Who supplied the prize, separately from who sponsored the contest
A contest has one sponsor and a shelf often has a dozen suppliers — the restaurant, the tyre place, the venue, none of whom bought the promotion. Name the business that put each prize up, and the sponsor recap gains a Prizes supplied section covering every contest they contributed to, whether or not they backed it: prizes, units, retail value, and how much of it has actually been won.
It is a sales record and stays inside the console. The published rules page still credits the promotion's own sponsor and does not name prize suppliers — nothing about who supplied a prize is a term of the contest.
Promotions#A forfeited win says why, and can be put back
HighlightForfeiting now asks for a reason — not claimed in time, could not reach them, declined, not eligible, the prize fell through, recorded in error. Insights gains a Wins taken back panel with the rate and the breakdown, which is the number that tells you whether your claim window is the right length. And a forfeit can be reversed: Restore win puts the row back exactly as it was, keeping the win date, the frozen value, the link and the signature.
A restore re-counts the shelf and is refused if the unit has gone to somebody else in the meantime — raise the stock first. Wins forfeited before this shipped keep no reason and are shown as not recorded rather than being guessed at.
Winners#Insights, by station
Every reading on Insights was by promotion, prize or sponsor. A group running several signals asks a different question every month, and there is now a panel for it: contests running in the range, value awarded, units, and entries received, per station.
A contest carried on two signals counts on both rows — it is one contest and neither station is wrong about what it ran. The rows do not add up to the workspace total above them, and the panel says so.
Promotions#
18 updates
A prize has its own clock, and now the product reads it
HighlightA prize already had dates: the days you are prepared to give it away. What it never had was its own — the night of the show, the last day of the season, the six months printed on the certificate. Add a Use by date to any prize and it travels everywhere the prize does: the shelf and the prize list flag it, the call screener shows it beside every prize a caller could take, the remote run sheet prints it against the event's own date, the published contest rules state it, and the winner is told it on their winner link. A new dashboard panel lists prizes still in stock that are close to their date, or past it, with the units left and what they are worth.
It never stops you awarding anything, and that is deliberate — a prize running out of time is one to give away sooner, not one the console should hide. An expired prize still appears on the screener and can still be awarded; what changes is that everybody can see it. Leave it blank for a prize that does not expire.
Promotions#The claim deadline no longer outlives the prize
A workspace that gives winners thirty days to claim would say exactly that about a pair of tickets for a show next Tuesday — on the rules page, in the handover queue, and in the reminder email it sends automatically. Where a prize carries a Use by date that falls first, that is now the date everything states: the queue counts down to it and says which clock set it, the reminder email uses it and explains why it is earlier, and the rules page says so in the claiming section.
Only applies where the prize actually has a Use by date; without one nothing changes. The automatic sweep stops chasing a prize that has already expired — hurrying somebody toward a date that has passed is the wrong message to send with nobody watching — while chasing one by hand from the queue still works, because a person looking at the row has decided to write.
Fixes#Where the prize actually is
The prize cupboard is real and nothing in the record had ever mentioned it. Every prize now takes a free-text location — a drawer, somebody's office, or the sponsor still holding it — and it shows on the shelf, on the prize list, beside every prize on the call screener, on the remote run sheet as a load-out note, and against each row of the handover queue.
Staff only. It is never on the contest rules, the winner link or any page a listener can reach: where a station keeps its prizes is its own business. It is free text on purpose, because a fixed list of places would be wrong within a week.
Promotions#The prizes still to hand over, as a file you can pack from
Forty prizes to post on a Thursday is a different job from a queue on a screen. Pack list on the handover panel downloads the whole queue — not a page of it — with the winner, how to reach them, the full postal address, the prize, where it is kept, how it is meant to travel, and three dates: your claim deadline, the prize's own use-by date, and the earlier of the two, which is the one worth sorting on.
It carries what the prize is worth and never what it cost — this file has somebody's home address on every line, so it answers as few questions as it can. Prizes already sent are not on it; those are in the list of prizes on their way. A winner whose details you have erased still appears, because the prize is genuinely still outstanding, with nowhere to send it.
Winners#The winner link tells the winner what happened next
HighlightIt used to end at “the station has your details and will be in touch”, which was all it could honestly say. Now, once you record a dispatch, the winner sees that their prize is on its way, the date it went, the carrier and the tracking reference where you entered one. And where the prize carries a Use by date, the page tells them — which is the single commonest reason a won prize never gets used.
It shows nothing about where the prize is kept, what it cost, or any other winner — the page is still only ever about the one prize whose link it is. The tracking reference is printed, not linked: it is your own text and this product will not guess a carrier's website from it.
Winners#A prize in the post is not a prize nobody collected
HighlightEvery win used to have one box — collected — and it stood for two different things: the winner has it, and the station is finished with it. Those are the same only when the prize is held at the front desk. Open a winner and the Handover panel now asks how the prize reaches them — collected at the station, posted, handed over by the sponsor, or sent electronically — and, for the three that travel, whether it has gone, with a carrier and a tracking reference. A prize you have sent leaves the queue of prizes still to hand over and appears in a short list of prizes on their way, with how long ago it left.
Sending it does not mark it collected and never will: those are the station's half and the winner's half, and a record that used one to mean the other is what this replaces. Both can be true on the same win. If you record a dispatch by mistake, clear the tick and the win goes back in the queue.
Winners#The claim reminder no longer chases a parcel
With automatic claim reminders switched on, a winner whose prize you had already posted could still be emailed asking them to come and collect it — because the only thing the reminder could see was that nothing had been marked collected. Recording a dispatch now takes the win out of the reminder's reach, out of the handover queue and out of the overdue count. Chasing one by hand from the queue refuses too, and says why.
It keys off the dispatch, so a posted prize with nothing recorded about it is still treated as sitting on the shelf. The overdue count on the dashboard changes the day you start recording dispatches — that is the number becoming correct, not dropping.
Fixes#Who has been winning all year
HighlightThe win cooldown holds somebody out for a set number of days after a win, and a thirty-day cooldown quietly permits twelve wins a year from one household. Listeners › Frequent winners lists everybody with three or more valid wins in the last thirty, ninety or three hundred and sixty-five days, with the wins, the units behind them (a five-pack of tickets is one win and five), how many different contests they won on, what it came to, and when they last won. Anybody already excluded is marked rather than hidden.
It decides nothing. Winning often is not misconduct — a small market with a keen audience produces this list honestly — so nothing here excludes anybody. Where you do rule somebody out, the control is on their own record and leaves an audit entry. Forfeited wins are not counted.
Winners#Search that can see past the last hundred records
HighlightThe command bar used to hold the hundred most recently touched promotions, prizes, listeners, sponsors, stations and events and filter them in your browser — so a listener who last won a year ago simply was not findable, and the bar said nothing to tell you apart from a workspace that had never heard of them. Typing two characters now searches the whole workspace: names, email addresses, phone numbers with or without their brackets and dashes, towns, callsigns, markets and venues. Archived promotions come back when you search for one by name, and a station row now opens that station.
Twenty rows of each kind per search — a query matching four hundred listeners wants narrowing, and the directory's own page is where a long list belongs. One character is not a search; the bar shows the recent records instead.
Platform#One page per signal
A station was a row in a list with a promotion count and an Edit button. Click the name now and you get the signal itself: what is running on it today, how many prize units are left across everything it carries, wins and their value over the last ninety days, remotes booked against it, the liner copy in flight and the imaging still in production.
Liner and imaging copy with no station of its own runs on every signal its promotion does, so it appears on each of their pages and is labelled as shared. Prize stock is counted across every promotion the signal carries, which means a prize on a two-station contest shows on both — it is one shelf, not two.
Platform#Erasing somebody the prize ledger will not let you delete
HighlightA listener with wins on record cannot be deleted here, and that is on purpose: the shelf's claimed count, the per-prize limits and last year's reportable totals are all read off those rows. It also left you with nothing to offer somebody who rings up and asks to be taken off your books. Open the listener and press Erase personal details: the name, email, phone, address, notes and the signature they typed on their winner link all go, any consent to be named publicly is withdrawn, the winner link is revoked, and the contest entries behind those wins are emptied at the same time. The winner rows stay, with their dates and their award-time values, so nothing you have reported moves.
Admins and owners only, confirmed by typing ERASE, and it cannot be undone — there is no copy kept to undo it from. Two consequences are shown before you do it: nothing can match that person to their history afterwards, so the win cooldown and per-prize limits stop applying to them, and if their winnings are at or above the reporting floor for the year, the name your tax export would file under is the one being removed.
Platform#Contest entries that empty themselves after the contest
HighlightA qualifier pool is the biggest pile of other people's contact details this product holds — thousands of names, emails and phone numbers per contest, nearly all of them belonging to somebody who never won anything — and until now nothing ever removed one. Settings › Privacy sets a window: entries are emptied a chosen number of days after the promotion they belong to ended. The panel shows how many entries you are holding, how many the next run would reach and how many have already been emptied, and there is a button to apply it now rather than waiting for tomorrow. A single entry can also be emptied on the pool page when somebody asks.
Off until you set it, and it EMPTIES rather than deletes: the row, its date, its period and the draw it belongs to stay, so a draw made from that pool still recomputes to the same winners for anybody who checks. It never touches a live contest — the pool is what enforces one entry per person — and never a drawn entry you have not settled, because that is somebody still owed a phone call.
Promotions#Worth a look before you draw
One entry per person is enforced on the contact somebody gives you, which means it cannot see the person who entered once with an email and once with only their phone number, or the three addresses that all reach one Gmail inbox. The entries page now opens with what that rule cannot: groups where one phone number, one mailbox, one name or one internet connection sits behind more than one entry, each with the entries listed and the reason it was flagged.
It proposes and never removes. A household shares a phone and a connection, so several of these will be perfectly innocent — removing an entry is still your decision and still carries the reason the entrant would be told. Two entrants from one connection are not flagged at all; three are.
Promotions#The week's outstanding work, in your inbox
Everything the dashboard tells you is time-sensitive, and all of it degrades quietly while the tab is closed. Pick a morning in Settings › Team and the workspace mails its own work list to the people who can act on it: contests starting this week with something unfinished, contests ending with stock still on the shelf, prizes running low, prizes past their claim deadline, and contests that ended and were never wrapped up. Every line links to the thing that fixes it.
Off until somebody picks a day, and it goes to members, admins and owners — not viewers, who cannot action any of it. Anyone can turn it off for themselves in Settings › Profile. Nothing is sent on a week with nothing outstanding: a weekly all-clear is a message people learn to ignore, and then the one that matters is ignored with it.
Platform#Check a caller before you put them to air
HighlightEvery eligibility rule this product enforces was enforced at the award — which is after the jock has already said the words. Call screener takes the number off the caller ID and answers the same questions twenty seconds earlier: is this person excluded, are they inside the win cooldown and for how much longer, how much have they won this calendar year against the reporting floor, and is their taxpayer form on file. Beside it is everything that can legitimately go out of the door right now — in stock, inside its window, allowed on today's day of the week — with the ones this caller may not have marked and the reason on each. Award straight from the row.
It reads and never writes: nothing is recorded, no award is reserved, and looking somebody up leaves no trace. A phone number matches on its digits however it was typed into the directory; a name is the loosest thing to match on and can return several people, in which case it asks you which.
Winners#What the rules said, and when that changed
HighlightYour rules page is generated from the contest, which is what makes every number on it a number the award flow really enforces — and it also meant the page could not remember. Add a prize in week three and everybody who entered in week one had been told something else, with nothing anywhere recording it. The published page now keeps a ledger: each time it serves terms that differ from the last, it records that version, and the page footer carries the amendment date and a short reference so two printed copies can be told apart. The contest file lists every version with the date it began and exactly which terms moved.
A version is recorded when the public page SERVES it, so an edit nobody's page load ever reached is not in the ledger — which is the honest answer, because nobody was shown it. A promotion whose rules page has never been loaded shows an empty ledger rather than a claim that its terms are unchanged.
Promotions#What is unfinished, before it goes to air
Activating a promotion checked one thing: whether your plan had a slot. Everything else that makes a contest runnable was somebody's memory on a Monday morning. A promotion page now opens with what is outstanding on it — no station assigned, nothing on the shelf, every unit already claimed, rules never published, an entry form live on a promotion that is paused and refusing everybody, an entry window that closes after the contest ends, a draft whose start date has already passed, or nothing written for air.
It refuses nothing. Every item is a note with a link to the thing that fixes it, and the panel disappears when there is nothing outstanding — an archived promotion never shows one at all.
Promotions#The remote's run sheet, on paper — with what to put in the van
An event page is fine at a desk and useless at a county fair with one bar of signal. Press Run sheet on any event for a printable page: door times, venue, the address, who to find on site and their number, and the four instruction blocks in a fixed order so a hole is where you expect it. It also answers a question nothing in this product could before — which prizes may actually be given away on that date, read for the EVENT's own day rather than today's, so a weekday-only prize never appears on a Saturday sheet. The entry and rules URLs are printed too, when they are live.
Stock is counted as it stands today, so for an event three weeks out the figure is a ceiling rather than a promise, and the sheet says so. An event not linked to a promotion has no shelf behind it and the sheet says that too.
Promotions#
22 updates
Proof of performance, on one printable page
HighlightEvery sponsor recap used to be somebody retyping five screens into a slide the afternoon before the renewal meeting. Open a sponsor and press Recap: every promotion they backed, which stations carried it, how many entries came in, how many winners there were, and the promotional value actually delivered — with the value still sitting on the shelf beside it, so an under-delivered contest shows as one. Filter it to a year or take the whole relationship, then print it or save it as a PDF from the same dialogue the contest file uses.
It reports promotional VALUE, never what a prize cost you — a recap is a document that leaves the building, and what you paid for the shelf is your business. Value delivered counts prizes that were genuinely won: a forfeited prize delivered nothing and is not on it.
Promotions#The 1099 threshold, said while you can still do something about it
HighlightFour hundred dollars in March and three hundred in July is one reportable winner, and neither award said so. The award form now shows where a win leaves that listener for the calendar year — approaching the reporting floor, crossing it with this prize, or already past it — while the winner is still on the phone and a taxpayer form is easy to ask for. Record that the form arrived on the listener's page, and the tax season readout gains a column for it plus a count of everybody over the floor with nothing on file. The CSV carries the date too.
It records that a form was received and when — no taxpayer identification number is stored anywhere in this product, deliberately. Nothing is refused: a missing form never blocks an award, because that judgement belongs to whoever is standing in the studio. The floor shown is the US 1099-MISC figure and is a prompt, not advice.
Winners#Somewhere for a listener to write
Four pages here are read by members of the public — your contest rules, your entry form, a winner's own link and your published winners list — and every one of them named the station and gave the reader no way to reach a person. Set an email, a phone number and a postal address under Contest rules and they appear on all four. On the winners page it comes with the sentence that page was missing: anybody named there can ask to come off, and it does not affect their prize.
Every field is optional and each appears only where you set one — an unset contact prints nothing rather than a route that goes nowhere. The address you put here is published, so make it a promotions address rather than somebody's own.
Platform#The contest that ended and never actually finished
Everything on the dashboard looked forward — what is ending, what is running low, what is nearly overdue. Nothing looked back at the contest that ended in March with a hundred entries nobody drew, two prizes still on the shelf and three names drawn and never rung. There is now a panel that does, oldest first, with each piece of outstanding work listed separately because they are jobs for different people. It also flags the one with a price attached: a finished promotion still marked active is holding one of your plan's promotion slots.
Nothing is archived or closed automatically. A contest left active past its end date is often deliberate — the dates were never corrected, the prizes go out this week — and a console that tidied up by itself would be wrong exactly where it matters. The panel only appears when something is genuinely outstanding.
Promotions#What a prize is worth, and what it cost you
HighlightA prize now carries two figures instead of one. Retail value is what it always was — the number your contest rules publish, the number frozen onto a winner, the number the tax season readout totals. Beside it is what the prize actually cost the station in cash, and where it came from: bought, trade, sponsor-supplied, or off your own shelf. The budget panel reports both, so the promotion that carries fifty thousand dollars of advertised value and cost you six hundred says so on one line instead of looking like a fifty-thousand-dollar spend. The cost freezes onto the winner at award time exactly as the value does, so a spend report you run in December does not move because somebody corrected a price in March.
Leaving the cost box empty means nobody has worked it out, which is not the same as free — the budget counts those prizes apart and says how many it could not see rather than quietly treating them as zero. Nothing you publish ever shows cost: the rules page, the winner link and the contest file all state retail value, because that is the figure a listener and a tax authority are owed.
Promotions#A draw can finally say who actually got a prize
HighlightDraw three names on Tuesday and by Friday nobody remembers which of them you reached. Award from the pool now and the win is joined to the entry it came from, so the entries page, the draw record and the contest file all show each pick as awarded, closed, or still to settle — and the pool's Drawn card tells you how many are still on your desk. When somebody cannot be reached or turns the prize down, record that with a reason and it stops being a loose end. The winner's own page links back to the draw that produced them.
Closing a pick does not put them back in the pool. Drawing the same person twice reads to a listener like a rigged contest, so the pool moves on and the entry keeps the record of what happened. One entry can only ever produce one win — if two people award the same drawn name at once, the second is refused rather than written.
Promotions#A winners page your listeners can read — with their permission
HighlightPublish a page of recent winners at a fixed address you can link from your station site. It shows a first name, a last initial, the town, the prize and the date, and nothing else. Who appears is not your decision: on their winner link, alongside the release, each winner gets an unticked box saying you may name them publicly. Only the people who tick it are on the page, and a winner's own record tells your team which way they answered before anybody puts a name in a promo. While you are in there, your release finally has words above the signature — Settings › Contest rules is where your own terms go, and they render on every winner link.
The last 90 days, newest first, capped at a hundred. Turn it on and it is public to anybody with the URL; turn it off and the address answers as though it never existed. Nobody appears who did not personally agree, so a workspace that has never asked will publish an honest empty page — the settings panel tells you how many are on it before you publish.
Winners#Import a pool from a spreadsheet
The box of entry cards from Saturday's remote, or the file your text-to-win vendor hands over, can now go straight into a promotion's pool. Upload a CSV on the entries page — it only needs a first name, a last name, and an email or a phone, under whatever headings your spreadsheet already uses — and every row goes through exactly the same rules as your public entry form. Anybody already in the pool is counted as a duplicate rather than added twice, and rows it could not use are reported with their line numbers so you can fix the file.
A thousand rows and 2 MB per file, and a file over either is refused rather than quietly cut short — a pool missing people who were told on air that they had entered is worse than a second upload. Imported entries are marked as imports, so a draw's record can always say what its pool was made of. If entry is closed for the promotion, the import stops rather than backdating anybody in.
Promotions#The whole contest, on one printable page
HighlightOpen any promotion and there is now a Contest file: the terms exactly as you published them, the prize shelf with what has actually gone off it, every draw with the seed and pool fingerprint that reproduce it, and every winner with what they won, when, and whether it has been collected. It prints — your browser's print dialogue will save it as a PDF — so when somebody asks six months later how a contest was run, the answer is one document rather than five screens and two spreadsheets. Every figure on it is read the same way the console reads it, so the file and the screens cannot disagree. It works on archived promotions too, which is when people usually ask.
It is a snapshot, not a frozen copy: generate it again after another award and it says something different. Show-prep notes are left off deliberately — those are written for your jocks, not for whoever you hand this to — and the entry list stays a separate CSV, because it can run to tens of thousands of rows.
Promotions#Staff and their households can be kept out of the draw
HighlightEvery set of contest rules says employees and their immediate households may not win. Now the product can actually hold them out. Open a listener, exclude them with a reason — staff, a household member, a sponsor's people, somebody abusing the contest line, or your own policy — and every award to them is refused and their entries are dropped from a draw's pool before it picks, not after. Both counts show on the draw so a pool that shrank can say which rule shrank it. And where a workspace excludes anybody, its published rules pages say so, in the same generated section as the win cooldown.
It is a decision about a named person, so somebody has to make it: nothing infers who works for you. There is no override at award time either — the way past an exclusion is for an admin to lift it, which is recorded. Prizes already won are untouched.
Winners#The claim deadline can chase itself
Set a lead time in Settings › Contest rules and each winner is emailed once, that many days before their prize's claim deadline, with the same message and the same date the Remind button on the handover queue sends. Before you turn it on the panel tells you how many winners the first run would write to, and how many are in the window at all — so nobody switches on unattended mail without knowing its size. The chase button also now sits on the winner's own page, not only on the queue.
Off unless you turn it on, and it needs a claim window set — there is no deadline to count back from otherwise. Each win is chased once, and only before its deadline: an overdue prize is a judgement between forfeiting and telephoning, so it stays a button somebody presses.
Winners#Entries and draws, through the API
HighlightRead a promotion's qualifier pool, put somebody into it, list every draw you have run, and run one — all four on the same key you already use for promotions and winners. The entry endpoint is the one a text-to-win vendor, a remote's tablet or your own website posts to, and it obeys exactly the rules the public form does: the same entry window, the same one-per-person-per-day, the same way of deciding two entries are the same person. A repeat gets a plain answer saying so instead of a second row, so a bridge that replays a message cannot inflate a pool. Running a draw returns the seed it used and the fingerprint of the pool it drew from, and reading a draw back later gives you the winners in the order they came out — worked out from that seed each time rather than stored, so a retry and a read a year later agree.
Nothing here awards a prize — a draw picks a person, and recording what they won is still its own call, where inventory and the frozen value are settled. Draws cannot be deleted.
API#Two records for one person, joined into one
The directory can now find people it is holding twice — anyone who shares an email address or a phone number with somebody else, however it was typed — and join them. Merging moves every winner record onto the one you keep, fills in whatever that record had blank from the other, and carries the other's notes across before removing it. Nothing you already had is overwritten. It matters more than tidiness: two rows split one person's win history, which is what the per-winner limit counts, what your win cooldown reads, and what the year-end export totals against the tax threshold.
Merging is an admin action, and it is done one pair at a time on purpose — the record with the most wins is suggested to keep, but the choice is yours.
Platform#Remind a winner their prize is waiting
The handover queue lists prizes nobody has collected and how long is left on your claim window. Now each row can send that winner an email saying so, with the deadline your workspace actually enforces and the link where they confirm their details and sign. The queue shows when the last reminder went and how many have gone, so nobody chases the same person twice in a morning, and a winner who never got a link gets one issued with the reminder.
One winner at a time, from the row — this is not a mailing list, and a listener with no email on file shows no button rather than a button that cannot work.
Winners#Listeners enter online, and the draw proves itself
HighlightOpen entry on a promotion and it gets its own public form: name, how to reach them, the age box, and the prizes they are entering for, generated from the contest the same way the rules page is. One entry per person, or one a day — whichever you pick, the database itself enforces it, so nobody buys extra chances by holding down refresh. When it is time to pick somebody, draw from the pool in one click. Every draw is recorded with the random seed it used and a fingerprint of the pool it drew from, so you can hand anybody the entry export and that seed and they can work out the same winners themselves. Entrants who are inside your win cooldown are held out of the draw automatically, and the count of how many is kept with it. A drawn name goes straight into the award screen with their details already filled in.
Entrants become listeners in your directory only when you award one of them, and the pool keeps everyone you remove, with the reason, rather than deleting them.
Promotions#Run last year's contest again without retyping it
Duplicate copies a promotion into a new draft with its stations, its sponsor, its terms and its whole prize shelf — every value, quantity, per-winner limit and day mask intact — and moves the dates forward by the length of the original so nothing opens with last year's window still in the box. It works on an archived promotion too, which is usually the one you want. Winners and entries stay with the contest that ran, and nothing the copy inherits is published until you say so.
Liners and imaging are not copied — they are produced work with their own schedules and cart numbers.
Promotions#What a contest is on the hook for, against what it was given
Give a promotion a budget and its page totals the prize shelf against it — committed, which is everything stocked whether or not anybody has won yet, and awarded, which is what has actually left the building at the value frozen the day it was won. The bar runs past its track when the shelf outgrows the number, because that is the case worth seeing.
Nothing is refused. A contest can go over budget, and a console that blocked it would be wrong about a deal it never saw.
Promotions#Prize availability days now read in your language
"Weekdays", "Weekends" and the day names beside a prize were English on every screen, including the public rules page — so a Spanish contest listed its prizes in Spanish and their availability in English. They are translated everywhere the console shows them. The exports and the API keep the English spelling, which is what anything reading them was built against.
Fixes#A rules page you can read out on air
HighlightEvery promotion can now publish an official rules page at its own public link. The dates, the stations, the sponsor, each prize and its approximate retail value, the eligibility window and the claim deadline are all generated from the record you already keep — so the page cannot drift away from the contest it describes. You add the parts the record cannot know: this contest's own terms, and your group's closing terms, which appear under every one. Publishing is a separate step from writing, and taking a page down makes its link answer as though it never existed.
It states what your record says and what this product enforces. What counts as adequate disclosure where you broadcast is a question for your own counsel.
Promotions#"You can't win again for 30 days" — enforced, not just written down
HighlightSet a cooldown for the workspace and a listener who wins anything is held out of every other contest you run until it expires. The award screen says so before anybody fills the form in, naming the last win and the date they come clear, and the API answers with its own code so an automation can tell it apart from an empty shelf. A single promotion can set its own window — ninety days on a grand prize, or none at all on a giveaway. Admins can award through it when a call genuinely needs making; the override goes in the audit log with a name on it.
Forfeited wins do not count towards it, and the window is measured from the win, so changing the number moves everybody's eligibility with it.
Winners#Prizes that have not been picked up, in one list
Give the workspace a claim window and every win carries a deadline. The winners page opens with what is still to hand over, oldest first, and the dashboard shows anything already past its date. The deadline is worked out from the day each prize was won rather than stamped on the record, so shortening the window moves every outstanding one at once instead of leaving two sets of winners under two rules.
It counts wins with nothing recorded as collected — marking the handover is what clears a row.
Winners#The promo calendar, in Outlook and Google
Issue one subscription link and every promotion window, prize window and event shows up in whatever calendar your team already lives in — jocks, street team and sales included, without any of them signing in. It refreshes on its own, carries a year either side of today, and links each entry back to the record behind it. Issuing a new link retires the old one immediately.
Anyone holding the link can read your promotion schedule, so treat it like a key. Only admins can issue or retire one.
Platform#
13 updates
Your copy, read aloud
HighlightEvery liner and imaging script can now be read in a broadcast voice, from the page the copy already lives on. Eight house voices ship with the product, in three deliveries — a neutral house read, something warmer for sponsor copy, and one that pushes for a contest tease. Each take is kept with the exact script it was read from, so when the copy is edited later you can still hear what actually went out.
Reads are metered in characters against your plan each month. A take that fails costs nothing.
Production#A finished promo, bed and all
HighlightOne press turns a script into a produced spot: the voice is read first, then a music bed is composed to the length that read actually came out at, and the two are mixed with the bed ducking under the words the way a board operator would ride it. The spot ends when the music ends, because the music was written to end there — no fading a two-minute library track under a twenty-eight second read.
A promo is billed once, for its read — the bed costs no extra characters. Composing takes a minute or two.
Production#Copy drafted from the promotion itself
HighlightAsk for a :10, :15, :30 or :60 and get three genuinely different drafts, written from the promotion you are looking at — its sponsor, its prize and value, its dates, its rules. Written for the ear, so it says "fifty dollars" rather than "$50". Every number in a draft is checked back against the record, and anything that is not there is flagged on the draft by name.
Drafts are never saved for you. Copy the one you want into a liner or imaging item, edit it, and save it yourself.
Production#Winner calls, ready for air
Upload the phone call and the winner's voice is pulled out from under the hold music and the room noise, levelled, and trimmed of the dead air at each end. It is transcribed at the same time, so finding the ten seconds worth airing is reading rather than scrubbing. Your original recording is kept untouched alongside it.
Transcription is English only. Separating a call takes roughly as long as the call itself.
Winners#Your own imaging talent
Upload five to twenty seconds of your presenter reading normally and the engine reads new copy in that voice. Your voices sit above the house ones in every picker. A voice that has read something can be archived but not deleted, so a promo from March can always say who is on it.
One clean, dry clip of one person — no music and no processing underneath.
Production#Promotions with two status axes
HighlightA promotion's lifecycle — draft, active, paused, archived — is a choice your team makes; where today sits against its dates is worked out from the dates every time anyone looks. The two never fold into one flag, so a promotion paused mid-flight reads "paused" on every list, not "ended", and every stat on the hub is computed over the whole table so the headline cards and the lists beneath them cannot disagree.
Timing cannot be edited directly, on purpose — move the dates or change the status, and the display follows.
Promotions#Prize inventory with day windows
Every prize carries a quantity, a per-winner limit, a value in exact cents and a day-of-week window, with an optional date range of its own inside the promotion's. What is claimed is derived from the winner records themselves — there is no counter to drift out of step — and a weekday-only prize stays out of the weekend's show prep automatically.
A prize with no dates of its own follows the promotion's window; a forfeited win returns its stock the moment the status changes.
Promotions#The winner link
HighlightAward a prize, issue a link, and the listener does their own paperwork: contact details, postal address and an e-signed release, typed by the winner on their own phone. The page shows the prize, the station group's name and the release text — no other winner, no other record — and the name the listener types is kept verbatim as the signature, with the moment it was signed.
The link is the whole credential — anyone holding the URL can open it, so send it to the winner and nobody else. Revoke one and every later visit is a plain 404.
Winners#Year-end tax readiness
A prize's per-unit value is frozen onto the winner record at award time, in integer cents, so repricing a prize in March cannot restate what January's winner won. The tax view totals each listener's calendar year from those frozen figures, flags totals at or over the $600 federal 1099 reporting threshold, and exports the lot as CSV for the bookkeeper.
It is bookkeeping, not tax advice: the figures follow the records you keep, and whether a form is due is between you and your accountant.
Winners#Liners, and imaging with six named stages
Live-read copy is scheduled by date range against its promotion, with an optional station-specific cut, so a jock's list only ever shows what is current. Produced imaging — promos, sweepers, credits, bumpers — moves through six named stages, needs review to completed, with the playout cart number recorded once it has one. Nothing sits in an unnamed limbo between "written" and "on air".
The pipeline tracks the work; the audio itself lives in your playout system, with the cart number recorded here.
Production#Run sheets for remotes
Every appearance gets a run sheet: venue and address, the contact and their phone, door times, what the street team brings, team notes and the on-air mentions — attached to its promotion and its station, so the van leaves with the whole plan rather than with whoever remembers it.
A run sheet records the plan; it does not book anyone or talk to a calendar outside the product.
Promotions#The calendar, and a hub that agrees with itself
HighlightOne month view carries promotion starts and ends, prize windows and events, windowed in the database rather than paginated — the week you are looking at is the whole week, whatever size the tenant. The hub's numbers work the same way: low stock, promotions expiring with prizes still unclaimed, top promotions by awarded value, all computed in SQL over every row.
The winners headline counts a trailing 30 days, not the calendar month.
Platform#The console: roles, API keys, activity
Workspaces with four roles — a read-only Viewer seat means the whole airstaff can check show prep without being able to change a record. Plan caps count what is live, claimed transactionally so two tabs cannot both take the last slot. API keys are hashed at rest and scoped per surface, every call is logged with its status and latency, and consequential actions write an audit trail the activity feed reads back.
A key's scopes are fixed when it is issued — widening one means issuing a new key. Keys are shown once, at creation.
Platform#