Skip to content

Auction Settings & Policy — Frontend Implementation Guide

This page is the authoritative frontend implementation guide for auction settings, policies, presets, and the per-auction config snapshot. It corrects the common misconception that "settings are configured at the program level and stay in sync with the auction server."

That statement is wrong. Two separate misconceptions:

  1. Settings are not configured "at the program level" only. They resolve across six layers — default < platform < company < preset < program < auction — each with its own REST surface. Program defaults are just one layer; per-auction overrides sit on top of them.
  2. Settings do not "stay in sync" with the auction server. The server resolves the effective config and freezes it into a versioned per-auction snapshot when the auction is armed (on schedule, approval, cycle activation). The live auction and all its automated lifecycle transitions run off that frozen snapshot, not off the current program/policy rows. Edits made later do not retroactively change an armed auction — they apply from the next arming (or a re-arm).

The correct mental model is resolve-then-freeze: edits flow program → policy → … → auction only at arming time, and afterwards the auction is immutable until the next arm.

Companion deep dives:


1. The six-layer model

Every configurable key resolves independently across layers in strict precedence order (higher wins):

default (system floor)  <  platform  <  company  <  preset  <  program  <  auction
  • default — hard-coded server floor (DEFAULT_AUCTION_SETTINGS).
  • platform — superadmin-wide policy (/v2/admin/platform-auction-policy).
  • company — per-company policy (/v2/companies/company-auction-policy, admin: /v2/admin/companies/:companyId/company-auction-policy).
  • preset — reusable named config layer, assigned to programs (/v2/companies/auction-presets + admin variants).
  • program — per-program default settings (/v2/companies|admin/programs/:programId/settings), set at program creation (step 2) and editable later.
  • auction — per-auction overrides applied at scheduling (PATCH /v2/companies|admin/auctions/:auctionId/schedule).

Each layer is nullable: a null (or absent) value means "inherit from the next lower layer". Every resolved key reports the layer that supplied it in provenance — use that to tell the UI where a value came from.

Not every key is supported at every layer:

Concern Keys Supported layers
Auction settings auctionBidMode, auctionClosingMode, auctionDurationSeconds, auctionExtensionSeconds, auctionFirstCallSeconds, auctionSecondCallSeconds, auctionThirdCallSeconds, subscriberJoinGraceSeconds, subscriberJoinLeadSeconds, allowStaffOfflineBids, prebidMutabilityPolicy, auctionJoiningRule, hasPrebid all six (auction layer has no hasPrebid)
Trigger policy autoStart, approvalRequired, autoOpenPrebid, autoRevealPrebids, autoDeclareWinner platform, company, preset, program (no auction layer)
Securities allowedSecurities program only

So you cannot override trigger flags or the security whitelist on a single auction via the schedule endpoint. If the UI must change them, change the program (or a higher) layer and re-arm.


2. The config layer contract

The same nullable patch contract is accepted by the platform policy PUT, company policy PUT, preset POST/PUT, and program settings PATCH. Fields are optional; null clears this layer's override. Program creation step 2 and general program PATCH have different conditional requirements and nullability; use the creation and editing guide for those forms.

Field Type Notes
hasPrebid boolean | null enables the prebid flow (not accepted on the auction layer / schedule)
auctionBidMode DISCOUNT_INCREASING | TOTAL_VALUE_DECREASING | null
auctionClosingMode DURATION_MODE | CALL_MODE | null
auctionDurationSeconds int | null >= 1 when set
auctionExtensionSeconds int | null >= 0 when set
auctionFirstCallSeconds int | null first-call timing (call mode)
auctionSecondCallSeconds int | null second-call timing (call mode)
auctionThirdCallSeconds int | null third-call timing (call mode)
subscriberJoinGraceSeconds int | null live join grace window
subscriberJoinLeadSeconds int | null seconds before auction start when joining opens
allowStaffOfflineBids boolean | null staff floor/offline bids
prebidMutabilityPolicy IMMUTABLE_CANCEL_ONLY | MUTABLE_UNTIL_CLOSE | null
auctionJoiningRule BEFORE_START | GRACE_PERIOD | ANYTIME | null
autoStart boolean | null trigger flag; auto-starts at auctionStartAt
approvalRequired boolean | null trigger flag; forces SCHEDULED → READY approval gate
autoOpenPrebid boolean | null trigger flag; auto-opens the prebid window on arm
autoRevealPrebids boolean | null trigger flag; auto-reveals sealed prebids at ENDED
autoDeclareWinner boolean | null trigger flag; auto-declares winner at ENDED
allowedSecurities string[] | null program only; empty array resolves to default

Same-layer contradictions are rejected (e.g. autoOpenPrebid: true while hasPrebid: false on the same patch).


3. Where each layer is configured

All endpoints use the shared { status, code, data, message, error } envelope and Authorization: Bearer <token>. Company scope comes from auth/path — never send companyId in the body.

3.1 Platform policy (superadmin)

Method Path
GET /v2/admin/platform-auction-policy
PUT /v2/admin/platform-auction-policy

3.2 Company policy

Method Path
GET /v2/companies/company-auction-policy
PUT /v2/companies/company-auction-policy
GET /v2/admin/companies/:companyId/company-auction-policy
PUT /v2/admin/companies/:companyId/company-auction-policy

3.3 Resolved policy (prefill the console)

Returns the fully folded config for a company — settings, allowedSecurities, triggerPolicy, and provenance — so the UI can render effective values and label where each came from:

Method Path
GET /v2/companies/company-auction-policy/resolved
GET /v2/admin/companies/:companyId/company-auction-policy/resolved
{
  "companyId": "company-id",
  "settings": {
    "auctionBidMode": "TOTAL_VALUE_DECREASING",
    "auctionClosingMode": "DURATION_MODE",
    "auctionDurationSeconds": 1800
  },
  "allowedSecurities": ["CHIT"],
  "triggerPolicy": {
    "autoStart": true,
    "approvalRequired": false,
    "autoOpenPrebid": true,
    "autoRevealPrebids": false,
    "autoDeclareWinner": false
  },
  "provenance": {
    "auctionDurationSeconds": "platform",
    "autoStart": "company",
    "approvalRequired": "default",
    "allowedSecurities": "company"
  }
}

3.4 Auction presets

Method Path
GET /v2/companies/auction-presets / POST
GET /v2/companies/auction-presets/:presetId / PUT / DELETE
GET /v2/admin/auction-presets / POST
GET /v2/admin/auction-presets/:presetId / PUT / DELETE
GET /v2/admin/companies/:companyId/auction-presets / POST
GET /v2/admin/companies/:companyId/auction-presets/:presetId / PUT / DELETE

Platform presets have companyId: null; company presets are scoped. Assigning a preset to a program is a program-settings concern (see §3.5).

3.5 Program default settings

Method Path
GET /v2/companies/programs/:programId/settings
PATCH /v2/companies/programs/:programId/settings
GET /v2/admin/programs/:programId/settings
PATCH /v2/admin/programs/:programId/settings

Response data:

{
  "programId": "program-id",
  "programName": "Auctions",
  "presetId": "preset-id",
  "prebidDocumentRequired": true,
  "prebidDocument": null,
  "settings": { "...": "program's own override layer" },
  "allowedSecurities": ["CHIT"],
  "triggerPolicy": {
    "autoStart": true,
    "approvalRequired": false,
    "autoOpenPrebid": true,
    "autoRevealPrebids": false,
    "autoDeclareWinner": false
  },
  "provenance": { "approvalRequired": "company", "autoStart": "platform", "...": "..." }
}

settings here is the program layer only (not the folded result). To prefill a program form, use the resolved-policy endpoint (§3.3) plus this endpoint's program override, and let provenance decide which control is editable in place.

Program creation sets the same fields on step 2 of /v2/companies|admin/programs/new|existing/:programId/steps/2 (the five trigger flags live under the same patch shape, plus allowedSecurities).

3.6 Per-auction overrides (schedule)

PATCH /v2/companies/auctions/:auctionId/schedule
PATCH /v2/admin/auctions/:auctionId/schedule

Body requires auctionStartAt + auctionDurationSeconds and may include any subset of the auction-instance settings from §2 (auctionBidMode, auctionClosingMode, call/duration timings, allowStaffOfflineBids, prebidMutabilityPolicy, auctionJoiningRule). Trigger flags and allowedSecurities are rejected here.

Scheduling re-arms the auction: the server re-resolves all layers (now with this auction's overrides on top), freezes the result into a new configSnapshot and bumps configVersion. This is the main way a per-auction divergence is introduced.


4. The arming / snapshot model (why nothing "stays in sync")

When an auction is armed, the server:

  1. Re-resolves default < platform < company < preset < program < auction.
  2. Freezes the result into a versioned snapshot on the auction row: configSnapshot (settings, allowedSecurities, triggerPolicy, provenance, presetId, schema version, armedAt) + configVersion.
  3. Reports ARM_LIFECYCLE in the action log and stores the next enabled transition timestamp.

Arming happens automatically on: schedule, approve (re-arm from SCHEDULED → READY), and cycle activation. Every lifecycle transition — auto-open prebid, auto-start, auto-reveal, auto-declare winner — reads its trigger flags from the frozen snapshot, so a policy edited mid-flight cannot yank the switch on a running auction.

When does an edit take effect?

Edit Applies to
Platform / company / preset / program layer The next arming: next schedule or next cycle activation. Already-armed auctions keep their frozen snapshot.
Schedule body (auction layer) Immediately on that auction (schedule re-arms).
approvalRequired Only to auctions armed after the change; it is frozen into the snapshot and read by the approve/start gate.

Practical consequence for the UI:

  • A settings change should surface a notice like "applies from the next auction" rather than implying a live toggle.
  • To force-apply an edit to an existing auction, the console can re-schedule (re-arm) the auction — that is the supported "push current policy into this auction" action.
  • Never build the UI's notion of a running auction's rules from the current program/policy rows. Read the auction's own settings / approvalRequired / prebidPhase (and currentPhase) from GET /v2/companies|admin/auctions/:auctionId — those reflect the frozen snapshot.

5. Client-side effective-config computation

The server already computes and exposes the folded result, so the frontend does not have to re-implement resolution for reads:

  • For a company (prefill forms, console policy page): GET .../company-auction-policy/resolved returns the full fold + provenance.
  • For an auction (runtime rules): GET /v2/companies|admin/auctions/:auctionId returns settings, approvalRequired, plus provenance where the console needs to label origins.
  • For program defaults: GET .../programs/:programId/settings returns the program's override layer + provenance; combine with the resolved-policy endpoint when rendering an effective-value editor.

Rule of thumb for writes:

  1. Load resolved to show effective values.
  2. Load the layer you are editing to show what is already overridden (null = inheriting).
  3. Send a partial patch with only the keys the user changed; send null to clear an override and fall back to the lower layer.
  4. Remember trigger flags cannot be set per-auction — editing them means editing the program (or a higher) layer and re-arming the affected auctions.

6. Frontend flow checklists

Program setup (step 2)

  1. GET .../company-auction-policy/resolved → prefill.
  2. Show provenance badges (e.g. "from company policy", "from preset").
  3. PATCH/step-2 submit with only the changed keys.
  4. Note: changes apply to auctions armed after this point.

Scheduling an auction

  1. GET .../auctions/:auctionId → read frozen settings, approvalRequired, prebidPhase, currentPhase.
  2. Offer per-auction overrides only for the §2 auction-instance keys.
  3. PATCH .../schedule with auctionStartAt, auctionDurationSeconds, and any overrides.
  4. Response returns the mutation envelope with the re-armed configVersion — treat the auction as now frozen under the new snapshot.

Editing policy mid-lifecycle

  1. Save the platform/company/preset/program patch.
  2. Tell the user it applies from the next arming (next schedule / next cycle).
  3. If they want it on a specific already-scheduled auction now, trigger a re-arm by re-scheduling that auction.

7. Common mistakes

  • Assuming GET .../programs/:programId/settings returns effective values — it returns the program override layer only. Use resolved for effective values.
  • Sending trigger flags or allowedSecurities in the schedule body — rejected; they are program-or-higher.
  • Reading a running auction's rules from policy rows instead of the auction payload — the auction payload is the frozen truth.
  • Clearing an override by omitting the key — omit means "no change"; send null to clear.
  • Editing program settings and expecting an already-scheduled auction to pick them up — it does not; re-arm it.