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:
- 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.- 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:
- Program creation and editing: hosting and complete validation
- Auction lifecycle config (REST contract)
- Auction frontend integration (strict lifecycle)
- Starting an auction
1. The six-layer model¶
Every configurable key resolves independently across layers in strict precedence order (higher wins):
- 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)¶
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:
- Re-resolves
default < platform < company < preset < program < auction. - Freezes the result into a versioned snapshot on the auction row:
configSnapshot(settings,allowedSecurities,triggerPolicy,provenance,presetId, schema version,armedAt) +configVersion. - Reports
ARM_LIFECYCLEin 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(andcurrentPhase) fromGET /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/resolvedreturns the full fold +provenance. - For an auction (runtime rules):
GET /v2/companies|admin/auctions/:auctionIdreturnssettings,approvalRequired, plusprovenancewhere the console needs to label origins. - For program defaults:
GET .../programs/:programId/settingsreturns the program's override layer +provenance; combine with the resolved-policy endpoint when rendering an effective-value editor.
Rule of thumb for writes:
- Load
resolvedto show effective values. - Load the layer you are editing to show what is already overridden (
null= inheriting). - Send a partial patch with only the keys the user changed; send
nullto clear an override and fall back to the lower layer. - 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)¶
GET .../company-auction-policy/resolved→ prefill.- Show provenance badges (e.g. "from company policy", "from preset").
PATCH/step-2 submit with only the changed keys.- Note: changes apply to auctions armed after this point.
Scheduling an auction¶
GET .../auctions/:auctionId→ read frozensettings,approvalRequired,prebidPhase,currentPhase.- Offer per-auction overrides only for the §2 auction-instance keys.
PATCH .../schedulewithauctionStartAt,auctionDurationSeconds, and any overrides.- Response returns the mutation envelope with the re-armed
configVersion— treat the auction as now frozen under the new snapshot.
Editing policy mid-lifecycle¶
- Save the platform/company/preset/program patch.
- Tell the user it applies from the next arming (next schedule / next cycle).
- 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/settingsreturns effective values — it returns the program override layer only. Useresolvedfor effective values. - Sending trigger flags or
allowedSecuritiesin 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
nullto clear. - Editing program settings and expecting an already-scheduled auction to pick them up — it does not; re-arm it.