Auction Live Phase Integration¶
Focused guide for the live-phase additions to the subscriber auction detail REST response and the storage-backed started transition in WebSocket replay.
This is a supplement, not a replacement. See subscriber-auction-detail.md for the full REST contract, auction-frontend-integration.md §2.4 for the
currentPhasederivation table, and auction.md for the full WebSocket event contract.
1. REST detail — two new fields¶
Every GET /v2/subscribers/me/auctions/:auctionId response now always includes currentPhase and liveStartedAt at the top level. They are never omitted, even before the auction goes live.
| Field | Type | Description |
|---|---|---|
currentPhase | string | Derived lifecycle summary. Render directly as a phase badge or step indicator. |
liveStartedAt | string | null | ISO-8601 live-start marker. null until the auction actually goes live; set once and never cleared. |
Example — prebid open (not yet live)¶
{
"auctionId": "auc_abc123",
"auctionStatus": "SCHEDULED",
"prebidPhase": "OPEN",
"currentPhase": "PREBID_OPEN",
"liveStartedAt": null,
"prebidEndAt": "2026-08-10T18:30:00.000Z",
"auctionStartAt": "2026-08-11T10:00:00.000Z"
}
Example — live auction¶
{
"auctionId": "auc_abc123",
"auctionStatus": "LIVE",
"prebidPhase": "CLOSED",
"currentPhase": "LIVE_BIDDING",
"liveStartedAt": "2026-08-11T10:00:00.000Z"
}
currentPhase values¶
PENDING → auction not yet scheduled
PREBID_OPEN → prebid window is open
PREBID_CLOSED → prebid window closed, waiting for approval or start
PENDING_APPROVAL → approval required before start
READY_TO_START → approved or no approval needed, waiting for staff start
LIVE_BIDDING → auction is live
PAUSED → auction paused by staff
ENDED → auction ended, awaiting winner selection
COMPLETE → winners declared
CANCELLED → auction cancelled
Derivation is deterministic from auctionStatus + prebidPhase + approvalRequired — see auction-frontend-integration.md §2.4 for the full table.
How to use them¶
- Phase badge / step indicator: read
currentPhasedirectly. No client-side derivation needed. - Countdown to live start: use
auctionStartAt(the scheduled time), notliveStartedAt.liveStartedAtis only set after the auction goes live. - Detect "has this auction started?":
liveStartedAt !== nullis the canonical check.auctionStatus === 'LIVE'also works but doesn't distinguish a live auction from a paused one.
2. WebSocket — canonical persisted lifecycle state¶
The started transition is persisted to the auction activity feed when the auction goes live (manual start or scheduled auto-start). The updated contract also makes its live broadcast identical to its replay representation: both carry an event id, serverSequence, transition, and a complete payload.state object.
{
"id": "evt_def456",
"type": "auction.state.changed",
"timestamp": "2026-08-11T10:00:00.000Z",
"data": {
"auctionId": "auc_abc123",
"cycleId": "cyc_xyz",
"stateVersion": 2,
"serverSequence": 14,
"payload": {
"transition": "started",
"state": {
"status": "LIVE",
"stateVersion": 2,
"currentPhase": "LIVE_BIDDING",
"prebidPhase": "CLOSED",
"auctionStartAt": "2026-08-11T10:00:00.000Z",
"prebidStartAt": null,
"prebidEndAt": null,
"auctionEndAt": "2026-08-11T10:30:00.000Z",
"startedAt": "2026-08-11T10:00:00.000Z",
"pausedAt": null,
"closingPhase": null,
"closingPhaseEndsAt": null,
"prebidAmountsRevealed": false,
"prebidAmountsRevealedAt": null,
"approvalRequired": false,
"cycleStatus": "ACTIVE",
"joinWindow": {
"status": "CLOSED",
"version": 1,
"joiningRule": "BEFORE_START",
"opensAt": "2026-08-11T09:50:00.000Z",
"openedAt": "2026-08-11T09:50:00.000Z",
"closesAt": "2026-08-11T10:00:00.000Z",
"closedAt": "2026-08-11T10:00:00.000Z"
}
}
}
}
}
Replace the local lifecycle slice from payload.state. Older clients that read payload.startedAt must migrate to payload.state.startedAt.
Late-join replay¶
A fresh subscribe (no lastSequence) into an auction that is past live start includes a replay parcel whose events contain the persisted started transition. This is the same event that would have been synthesised before — it now comes from storage instead, which means it carries a real serverSequence and a proper id.
The same event is prepended to gap-fill replay.events on reconnect when the auction is past live start and the gap does not already carry it. Clients should treat re-applying the started transition as idempotent.
ID-mapping (reconnect gap-fill)¶
When reconnecting with lastSequence, the server fills gaps from the activity feed. Each event in the gap has:
| Field | Description |
|---|---|
id | Activity event id (deterministic, reuse-safe). |
serverSequence | Monotonic sequence within the auction's event stream. |
type | auction.state.changed for lifecycle transitions. |
payload | Transition-specific fields (see above). |
The client should apply visible events in serverSequence order and advance lastSequence to the replay response's high-water value. Role/scope filtering can make the visible sequence sparse, so a numeric gap is not itself evidence of message loss.
3. Summary of changes¶
| Area | Before | After |
|---|---|---|
| REST detail | currentPhase sometimes null | currentPhase always present, enum string |
| REST detail | liveStartedAt absent | liveStartedAt always present, ISO-8601 or null |
| WS replay (late-join) | Synthetic/minimal started | Persisted started with complete state |
WS realtime started | Transition-specific payload | Same complete payload as replay |
| Client action required | Read root timing fields | Replace state from payload.state |