Skip to content

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 currentPhase derivation 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 currentPhase directly. No client-side derivation needed.
  • Countdown to live start: use auctionStartAt (the scheduled time), not liveStartedAt. liveStartedAt is only set after the auction goes live.
  • Detect "has this auction started?": liveStartedAt !== null is 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