Payload collections and fields
For review — no decision recorded
Prepared 5 October 2026.
This page proposes one concrete manual catalogue model for stakeholder review. It shows Payload collection fields, nested shapes, relationships, draft-save requirements and proposed publication gates. It is not a deployed schema, migration, API contract or approval to implement. Every example value is fictional and makes no claim about a real casino, company, payment method or offer.
Decision requested
Review the field paths, types, relationships, candidate enums and publication minimums below. For each collection, say which fields to add, remove, rename or change type, and which may be required to save an incomplete authoring draft versus required before publication. Identify feedback by collection and field path, for example: casinoProfiles.paymentPolicies[].processingTime.basis.
Model boundaries
The proposed roots are independent records when identity, reuse or publication requires it. Array rows and block rows belong to their parent lifecycle; a relational child table generated by Payload is not another collection. The selected manual scope is Casino profiles and market-scoped Bonus Offers, with retained support and exact publication records. Cashback, casino VIP programmes and events remain extension examples; this page does not add their collection roots or impose the welcome shape on them.
The candidate spelling promotionalOffers names a proposed collection. The current CMS has a bonusOffers collection; this proposal does not claim it has been renamed, migrated or replaced. Existing users and media collections are referenced where needed; this page does not redefine authentication or uploads.
Field provenance. Existing proposal means the source names this field or broad field family and the row preserves that shape. Candidate means the row selects a new type, spelling, nesting, enum, validation rule, draft-save requirement or publication gate. When a source-backed row adds one of those details, its Source cell says Existing proposal; Candidate: ... and names the new detail. Candidate details remain proposed; the authorities leave many exact descriptors and publication minimums open.
Requiredness columns are separate. “Draft save” describes whether an authoring record/row can be saved before it is complete. “Publication gate” describes the proposed conditions when a casinoProfiles or promotionalOffers revision is published. A field may be optional in a saved draft and required at publication. Reference collections are not independently published; a root publication resolves the exact values it uses.
| Payload type notation | Meaning here |
|---|---|
text, textarea, number, checkbox, date, select, richText | Native Payload scalar/editor fields. Exact decimals use text, never floating-point number. |
relationship → collection | Native Payload relationship to one local collection record unless marked many. casinoId is an application mapping to Core, not a cross-database relationship. |
upload → media | Reference to the existing media collection. |
group | One fixed nested object. |
array | Zero or more same-shape owned rows. Row IDs are Payload's native hidden string IDs. |
blocks | Zero or more typed owned rows; each row carries Payload's native block discriminator. |
json | Only for validated immutable publication snapshots/manifests. Editable catalogue facts use typed native fields. |
Payload supplies each collection's native id using the configured adapter's existing ID type; no UUID migration is proposed. Native createdAt/updatedAt metadata and versions: true authoring history are framework metadata, not fields duplicated below. Native versions do not make authoring content public. Profile/Offer publication is a separate explicit action and immutable record. Array/block row IDs are the stable child identity: no second component ID and no identity-by-position. A locale is selected per publication; localized copy fields are shown as (localized).
Collection inventory
| Slug | Identity and responsibility | Cardinality and key boundary |
|---|---|---|
brands | Commercial brand identity and display name. | One Brand may be related to many Casino products; a name is not a unique identifier. |
casinos | CMS mapping to a Core Casino identity. | One casinoId mapping per CMS Casino; Brand may be absent only while the record is incomplete. |
markets | Explicit audience/jurisdiction applicability context. | Stable unique key; not inferred from language, currency, retrieval route or display label. |
companies | Identified legal entity reused in attributed roles. | Legal name alone does not prove identity; no Company-to-Brand relation is added. |
paymentMethods | Reusable payment method identity and icon. | One method can occur in many profile-owned payment rows; it does not imply availability. |
casinoProfiles | Casino- and Market-scoped facts, owned detail and localized copy. | One authoring profile per (casino, market); profile publication is independent per locale. |
promotionalOffers | Casino- and Market-scoped Bonus Offer and typed terms. | Stable offerId; several same-purpose Offers may share Casino and Market. Each publishes independently per locale. |
evidence | Immutable retained source material and capture/admission context. | Reused by support bindings; a URL alone is not retained evidence. |
cataloguePublications | Immutable approved publish or withdrawal entry. | One exact profile or Offer subject, key and increasing revision per entry. |
publicationSelections | Current entry pointer for a publication key. | One current selection per key, including a withdrawal entry. |
publicationDeliveries | Durable delivery intent and acknowledgement state. | Refers to one exact immutable entry; retry identity stays stable. |
Relationship map
LEGAL_STATEMENT_ROWS, PAYMENT_POLICY_ROWS, TERM_VARIANT_ROWS, WELCOME_STAGE_ROWS, BENEFIT_COMPONENT_BLOCKS and SUPPORT_BINDING_ROWS are owned Payload children, not collection roots. Each support binding belongs to exactly one owning profile or Offer. A publication has exactly one controlled polymorphic authoring subject: the profile alternative or the Offer alternative, never both. A Brand or Company relationship is resolved to immutable values or exact retained versions in a publication; changing a referenced record does not rewrite an earlier publication.
brands
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
name | text | 1 | Required | If used in a profile snapshot, non-empty resolved display name | Existing proposal; Candidate: native text type and draft-save minimum | Commercial Brand name, distinct from a registered Company's legal name. |
aliases | array | 0..n | Optional | None; include only if a consumer needs aliases | Existing proposal; Candidate: text-row nesting and draft/publication gate | Optional alternate names; names do not identify or merge entities. |
aliases[].value | text | 1 per row | Required in row | Same as parent | Candidate | Candidate row spelling and shape; preserve the observed value. |
logo | upload → media | 0..1 | Optional | If included, snapshot pins exact media identity/version | Existing proposal; Candidate: upload type and media target | Reuses the existing media mechanism. No new media collection. |
Brand is a reference, not a public publication root. A Casino draft may omit its Brand; publishing a profile requires an established Brand association on its Casino.
casinos
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
casinoId | text | 1 | Required | Required and immutable for profile and Offer publication | Existing proposal; Candidate: text type and draft-save minimum | Unique validated mapping to an existing Core Casino ID; never a cross-database foreign key or CMS-created Core identity. |
brand | relationship → brands | 0..1 | Optional | Required and editorially established before profile publication | Existing proposal | Incomplete Casino drafts may lack a Brand. One current Brand per established Casino; history retains earlier association. |
staffLabel | text | 0..1 | Optional | Never exposed as public content | Candidate | Private staff-facing label; must not substitute for public Brand/Casino identity. |
Proposed unique constraint: casinoId. Do not use Casino name, domain, translation or Market as its identity key.
markets
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
key | text | 1 | Required | Required and stable in every profile/Offer context | Existing proposal; Candidate: text type and draft-save minimum | Unique immutable internal Market key. |
label | text | 1 | Required | Resolved into the publication context/snapshot | Existing proposal; Candidate: text type and draft-save minimum | Human-readable Market label; it is not the applicability rule. |
scopeKind | select: jurisdiction, audience, combined | 1 | Required | Must match the explicit supported scope | Candidate | Candidate enum; prevents the model treating locale or currency as Market. |
scopeDescription | textarea | 1 | Required | Required to explain the selected scope | Candidate | Explicit curated description of audience and/or jurisdiction applicability. |
jurisdictionLabels | array of text | 0..n | Optional | Required only when scopeKind is jurisdiction or combined | Candidate | Candidate list of source-supported jurisdiction labels; do not infer from retrieval IP or a display flag. |
jurisdictionLabels[].value | text | 1 per row | Required in row | Same as parent | Candidate | No country registry or code set is selected here. |
locale, currency and observed access are separate dimensions. No Market fallback is proposed.
companies
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
legalName | text | 1 | Required | If referenced by a profile statement, exact value is resolved and retained | Existing proposal; Candidate: text type and draft-save minimum | Legal entity name. A common name alone does not establish identity. |
registrationIdentifier | text | 0..1 | Optional | If included, retain its stated jurisdiction and support | Candidate | Candidate spelling for a supported registration identifier. |
registrationJurisdiction | text | 0..1 | Optional | Required when registrationIdentifier is present | Candidate | Candidate field; no jurisdiction is guessed from name or address. |
Companies are reused by typed legal-statement roles. Corporate group/ownership relations and a shared regulator/licence registry are not added.
paymentMethods
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
key | text | 1 | Required | Stable identity when resolved into a publication | Existing proposal; Candidate: text type and draft-save minimum | Unique immutable Payment Method key. |
displayName | text | 1 | Required | Exact display value is resolved if referenced | Existing proposal; Candidate: text type and draft-save minimum | Reusable public-facing method name. |
icon | upload → media | 0..1 | Optional | If included, snapshot pins exact media identity/version | Existing proposal; Candidate: upload field and media target | Reuses existing media; method identity alone does not assert casino support. |
Direction, currency, limits, fees and timing stay on a profile-owned policy row so their conditions remain correlated.
casinoProfiles
casinoProfiles is a nonlocalized Casino/Market authoring root with localized editorial fields. Rows below give the full editable shape; child id values are native Payload row IDs, not additional fields. Proposed index: unique (casino, market) at the native relationship fields.
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
casino | relationship → casinos | 1 | Required | Required; related Casino must have established Brand | Existing proposal | One Casino identity. |
market | relationship → markets | 1 | Required | Required; explicit scope resolved | Existing proposal | One Market presence. |
legalStatements | array | 0..n | Optional | Optional family; every included statement must be complete and supported | Existing proposal; Candidate: optional draft and included-row publication gate | Profile-owned attributed legal assertions; not independent licence verification. |
legalStatements[].role | select: owner, operator, licenceHolder, other | 1 per row | Required in row | Required for every included assertion | Candidate | Candidate role enum. Licence-holder spelling is a domain display term; code value remains a review choice. |
legalStatements[].company | relationship → companies | 0..1 | Optional | Required when the entity is identified; otherwise retain assertedEntityName and an open identity issue | Existing proposal; Candidate: concrete relationship cardinality and conditional gate | No fictitious Company record to complete an uncertain name. |
legalStatements[].assertedEntityName | text | 0..1 | Optional | Required if company is absent and the attributed statement is published | Candidate | Exact source-attributed entity name, not a verified identity. |
legalStatements[].assertion | textarea | 1 per row | Required in row | Required for every included statement | Candidate | Human-readable attributed statement, not a verification result. |
legalStatements[].licenceNumber | text | 0..1 | Optional | If present, must have matching support | Existing proposal; Candidate: text type and exact field path | Number exactly as asserted. |
legalStatements[].regulatorName | text | 0..1 | Optional | If present, must have matching support | Existing proposal; Candidate: text type and exact field path | Attributed authority name; no regulator registry is proposed. |
legalStatements[].jurisdiction | text | 0..1 | Optional | If present, must have matching support | Existing proposal; Candidate: text type and exact field path | Stated jurisdiction; not inferred from Market label. |
paymentPolicies | array | 0..n | Optional | Optional family; each included policy row must be complete for its direction/currency | Existing proposal; Candidate: optional draft and included-row publication gate | Correlated payment capabilities, not a flat method list. |
paymentPolicies[].paymentMethod | relationship → paymentMethods | 1 per row | Required in row | Required for every included policy | Existing proposal; Candidate: exact nested relationship path | Reused method identity. |
paymentPolicies[].direction | select: deposit, withdrawal | 1 per row | Required in row | Required; never merge directions | Candidate | Candidate enum. |
paymentPolicies[].currency | text | 0..1 | Optional | Required for each known monetary amount/fee; never fallback from Market, locale or another row | Existing proposal; Candidate: text type and exact nested path | Explicit source currency code. |
paymentPolicies[].minimum | group with state, amount | 0..1 | Optional | If represented, use the allowed exact-value states below | Candidate | Candidate nested shape. A known zero is amount: "0", not absence. |
paymentPolicies[].minimum.state | select: known, unknown, notApplicable | 1 when group exists | Required in row | known requires amount and currency; other states carry neither | Candidate | none and unlimited are not valid minimum states. |
paymentPolicies[].minimum.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Nonnegative canonical decimal string. |
paymentPolicies[].maximum | group with state, amount | 0..1 | Optional | If represented, use the allowed exact-value states below | Candidate | Candidate nested shape for a maximum. |
paymentPolicies[].maximum.state | select: known, unknown, unlimited, notApplicable | 1 when group exists | Required in row | known requires amount and currency; unlimited means the source explicitly states no upper bound | Candidate | No currency or number fallback. none is not a maximum state. |
paymentPolicies[].maximum.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Nonnegative canonical decimal string. |
paymentPolicies[].fee | group with state, amount | 0..1 | Optional | If represented, use the allowed fee states below | Candidate | Candidate nested shape. |
paymentPolicies[].fee.state | select: known, unknown, none, notApplicable | 1 when group exists | Required in row | known requires amount and currency; none means source explicitly says no fee; no unlimited fee | Candidate | Zero fee is a known amount "0", distinct from none. |
paymentPolicies[].fee.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Nonnegative canonical decimal string. |
paymentPolicies[].processingTime | group with state, minimum, maximum, unit, basis | 0..1 | Optional | If a timing claim is included, retain its amount/range, unit and start basis | Candidate | Candidate structured processing-time claim; not a community payout observation. |
paymentPolicies[].processingTime.state | select: known, unknown, notApplicable | 1 when group exists | Required in row | known requires minimum, maximum when a range is stated, unit and basis | Candidate | No numeric value can be detached from its time basis. |
paymentPolicies[].processingTime.minimum | number safe integer | 0..1 | Optional | Required for known single value/range | Candidate | Nonnegative integer quantity. |
paymentPolicies[].processingTime.maximum | number safe integer | 0..1 | Optional | Required only for a stated range; must be ≥ minimum | Candidate | Nonnegative integer quantity. |
paymentPolicies[].processingTime.unit | select: minutes, hours, days | 0..1 | Optional | Required when timing state is known | Candidate | Candidate unit enum. |
paymentPolicies[].processingTime.basis | select: requestSubmitted, verificationComplete, approvalComplete | 0..1 | Optional | Required when timing state is known | Candidate | Candidate start event enum; a bare duration is incomplete. |
cashierTerms | group | 0..1 | Optional | Optional family; any published row must preserve ordinary cashier scope | Existing proposal; Candidate: concrete optional group and publication gate | Distinct from an Offer award/cashout restriction. |
cashierTerms.limits | array | 0..n | Optional | Included limits need direction, period, value state and currency when known | Candidate | Candidate owned list; each row is scoped to the cashier policy. |
cashierTerms.limits[].direction | select: deposit, withdrawal | 1 per row | Required in row | Required | Candidate | Candidate enum. |
cashierTerms.limits[].period | select: perTransaction, daily, weekly, monthly, other | 1 per row | Required in row | Required; do not merge periods | Candidate | Candidate period enum. |
cashierTerms.limits[].otherPeriod | text | 0..1 | Optional | Required only when period is other | Candidate | Source wording for another explicit period. |
cashierTerms.limits[].basis | select: calendar, rolling, transaction, sourceSpecified | 1 per row | Required in row | Required; perTransaction requires transaction | Candidate | Candidate window basis so “daily” cannot hide calendar-versus-rolling semantics. |
cashierTerms.limits[].timeZone | text | 0..1 | Optional | Required for basis=calendar; must identify the source-stated zone | Candidate | No inferred timezone or schedule calculation. |
cashierTerms.limits[].basisDescription | text | 0..1 | Optional | Required only for basis=sourceSpecified | Candidate | Retains another explicit source-defined window basis. |
cashierTerms.limits[].value | group with state, amount, currency | 1 per row | Required in row | known requires exact amount and currency; upper-limit unlimited only when explicitly stated | Candidate | Candidate exact limit shape; no Offer cashout cap reuse. |
cashierTerms.generalRequirements | textarea | 0..1 | Optional | If published, source binding required | Candidate | Attributed general deposit/withdrawal requirement; not an arbitrary filter. |
cashierTerms.restrictions | array of typed statements | 0..n | Optional | Each included statement has a supported kind and evidence binding | Existing proposal; Candidate: concrete array shape and inclusion gate | Supported restrictions remain profile-owned. |
cashierTerms.restrictions[].kind | select: identityCheck, inactivity, closure, disputes, responsibleGambling, other | 1 per row | Required in row | Required | Candidate | Candidate known restriction kinds; not a universal capability enum. |
cashierTerms.restrictions[].statement | textarea | 1 per row | Required in row | Required when the row is included | Candidate | Keep exact scope and wording; other does not create a filter. |
support | group | 0..1 | Optional | Optional family; included advertised capabilities retain support | Existing proposal; Candidate: concrete group shape and optionality | Describes stated support, not platform test results. |
support.contacts | array | 0..n | Optional | Included contacts need a channel; redact private staff contact data | Candidate | Candidate representation for public-facing contact channels. |
support.contacts[].channel | select: liveChat, email, telephone, other | 1 per row | Required in row | Required | Candidate | Candidate channel enum. |
support.contacts[].availabilityStatement | textarea | 0..1 | Optional | If included, support binding required | Candidate | Advertised availability only; no “online now” freshness claim. |
support.contacts[].languages | array of text | 0..n | Optional | If included, retain the stated language labels | Candidate | Candidate owned language list. |
editorialCopy | group, fields localized | 1 | Optional in draft | Required per selected locale: title and summary | Existing proposal; Candidate: concrete localized group and title/summary minimum | Localized editorial copy and SEO; must not create unsupported structured filters. |
editorialCopy.title | text (localized) | 1 per locale | Optional | Required for that locale's profile publication | Candidate | Candidate field spelling/minimum. |
editorialCopy.summary | textarea (localized) | 1 per locale | Optional | Required for that locale's profile publication | Candidate | Candidate field spelling/minimum. |
editorialCopy.body | richText (localized) | 0..1 per locale | Optional | Optional; included claims need editorial support | Candidate | Reviewed narrative may explain an unfamiliar feature. |
editorialCopy.seoTitle | text (localized) | 0..1 per locale | Optional | Optional | Candidate | Search presentation text. |
editorialCopy.seoDescription | textarea (localized) | 0..1 per locale | Optional | Optional | Candidate | Search presentation text. |
supportBindings | array | 0..n | Optional | Every public factual field/row must resolve to retained evidence and the exact typed field key | Existing proposal; Candidate: concrete row shape and binding granularity | Bindings attach support to a profile root or a stable owned row; details follow below. |
unresolvedIssues | array | 0..n | Optional | An open issue blocks publication only when it affects a required or included public assertion | Existing proposal; Candidate: issue-row shape and conditional publication gate | Retain missing facts, identity gaps and conflicts; do not normalize by source arrival order. |
promotionalOffers
A promotionalOffers root is one Bonus Offer scoped to one Casino and one Market. purpose is not identity; there is no unique (casino, market, purpose) or (offer, currency) rule. Each term variant keeps currency and explicit eligibility together. The welcome nesting below is one candidate mechanic shape, not a universal Offer grammar.
In the table, paths such as components[blockType=cash].award.amount mean fields directly on the cash block row. There is no nested cash or freeSpins group inside components; blockType is Payload's native discriminator. Each components[] row has its own native hidden row id.
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
offerId | text | 1 | Required | Required and immutable after first publication | Existing proposal; Candidate: text type and draft-save minimum | Unique stable Offer identity, separate from Payload id. |
casino | relationship → casinos | 1 | Required | Required; resolves one Casino identity | Existing proposal | One scoped product. |
market | relationship → markets | 1 | Required | Required; resolves explicit scope | Existing proposal | One Market; no language/Market fallback. |
purpose | select: welcome, recurringReward, standaloneReward, other | 1 | Required | Required; does not determine identity or schema | Candidate | Candidate purpose enum. other requires a reviewed description in localized copy. |
mechanic | select: welcomePackage | 1 | Required | Required and supported by the selected typed shape | Candidate | Only the welcome package shape is detailed here. A new mechanic requires its own selected typed shape. |
validity | group with state, startsAt, endsAt | 1 | Optional while unknown | Required state; known validity dates must be ordered | Existing proposal; Candidate: group shape and required explicit state | Publication time is not an Offer start time. |
validity.state | select: known, unknown | 1 | Required when group exists | Required | Candidate | Candidate explicit state; no inferred date. |
validity.startsAt | date ISO-8601 instant | 0..1 | Optional | Required only for a known start | Existing proposal; Candidate: ISO date field type and conditional requiredness | Exact source-supported instant where present. |
validity.endsAt | date ISO-8601 instant | 0..1 | Optional | Required only for a known end | Existing proposal; Candidate: ISO date field type and conditional requiredness | Exact source-supported instant where present. |
termVariants | array | 0..n | Optional; an incomplete draft may have none | At least one publishable applicable variant | Existing proposal; Candidate: empty-draft and one-variant publication gates | Same currency may occur on distinct eligible variants; no currency-only uniqueness. |
termVariants[].currency | text | 1 per row | Optional in incomplete row | Required for each published variant and every known monetary value | Existing proposal; Candidate: text field type and incomplete-row rule | Source-supported currency code; no conversion or missing-currency fallback. |
termVariants[].eligibility | group with audience, conditions | 1 per row | Optional in incomplete row | Required; no missing eligibility fallback | Candidate | Candidate shape for the applicability statement. |
termVariants[].eligibility.audience | select: newCustomers, existingCustomers, allEligibleCustomers, invitedCustomers, other | 1 when group exists | Required in row | Required | Candidate | Candidate audience enum; retrieval route does not prove player eligibility. |
termVariants[].eligibility.conditions | textarea | 0..1 | Optional | Required when audience is other; otherwise add when a source condition narrows eligibility | Candidate | Supported condition in readable form, attached to this currency variant. |
termVariants[].validityOverride | group with state, startsAt, endsAt | 0..1 | Optional | If present, must be explicit and valid for this variant | Candidate | Candidate variant-specific override; never silently inherit a conflicting date. |
termVariants[].stages | array | 0..n | Optional in an incomplete draft | For welcomePackage, at least one complete stage with at least one complete benefit block | Existing proposal; Candidate: welcome-specific publication minimum | Owned welcome terms. Other mechanics do not get welcome stages by default. |
termVariants[].stages[].displayOrder | number safe integer | 1 per row | Required in row | Required; unique within the variant in this candidate | Candidate | Presentation order is not identity; row ID preserves identity after reordering. |
termVariants[].stages[].trigger | select: firstDeposit, registration, recurringPeriod, other | 1 per row | Required in row | Required and source-supported | Candidate | Candidate trigger enum. |
termVariants[].stages[].qualifyingDeposit | group exact amount | 0..1 | Optional | Required only when trigger is a deposit | Candidate | Keep qualifying deposit separate from award and cashier minimums. |
termVariants[].stages[].components | blocks: cash, freeSpins | 0..n | Optional in draft | At least one complete component per published welcome stage | Existing proposal; Candidate: exact cash/freeSpins Payload block types | Typed heterogeneous benefits; child fields stay with their component conditions. |
termVariants[].stages[].components[blockType=cash].award.kind | select: fixedAmount, percentage | 1 in cash block | Required in row | Required | Candidate | Candidate award kind. |
termVariants[].stages[].components[blockType=cash].award.amount | text decimal | 1 in cash block | Required in row | Required; percentage is an exact rate, not a floating-point number | Candidate | Nonnegative canonical decimal string. |
termVariants[].stages[].components[blockType=cash].award.currency | text | 0..1 | Optional | Required when award kind is fixedAmount; omitted for percentage | Candidate | Explicit currency for money only. |
termVariants[].stages[].components[blockType=cash].award.rateBasis | select: depositAmount | 0..1 | Optional | Required when award kind is percentage | Candidate | Candidate percentage basis; never store an unbased rate. |
termVariants[].stages[].components[blockType=cash].award.maximum | group exact amount | 0..1 | Optional | If included, known value requires amount and currency | Candidate | Award ceiling remains separate from any cashout cap. |
termVariants[].stages[].components[blockType=cash].wagering | group with state, multiplier, basis | 1 | Optional in incomplete block | State required; if required, multiplier and basis required | Candidate | Candidate typed wagering requirement. |
termVariants[].stages[].components[blockType=cash].wagering.state | select: required, none, unknown, notApplicable | 1 | Required in row | Required | Candidate | none means an explicit source states no wagering requirement; zero multiplier is not a substitute. |
termVariants[].stages[].components[blockType=cash].wagering.multiplier | text decimal | 0..1 | Optional | Required only when state is required | Candidate | Nonnegative exact multiplier. |
termVariants[].stages[].components[blockType=cash].wagering.basis | select: bonusOnly, bonusPlusDeposit, depositOnly | 0..1 | Optional | Required only when state is required | Candidate | Candidate basis enum; 30 without basis is incomplete. |
termVariants[].stages[].components[blockType=cash].cashoutLimit | group exact upper limit | 0..1 | Optional | If included, state required; known requires amount and currency | Candidate | Offer cashout cap; never use ordinary cashier limit here. |
termVariants[].stages[].components[blockType=freeSpins].count | number safe integer | 1 in freeSpins block | Required in row | Required and greater than zero for a published spin benefit | Candidate | Count is an integer. Zero is a known zero count, not an absent or unknown count; omit the component when no spins are offered. |
termVariants[].stages[].components[blockType=freeSpins].gameNames | array of text | 0..n | Optional | Required when source limits spins to named games | Candidate | No games collection or canonical game identity is added. |
termVariants[].stages[].components[blockType=freeSpins].spinValue | group exact money | 0..1 | Optional | Required if the source specifies spin value; amount and currency stay paired | Candidate | Decimal string plus explicit currency. |
termVariants[].stages[].components[blockType=freeSpins].wagering | group with state, multiplier, basis | 1 | Optional in incomplete block | State required; if required, multiplier and basis required | Candidate | Separate from the cash component's wagering. |
termVariants[].stages[].components[blockType=freeSpins].wagering.state | select: required, none, unknown, notApplicable | 1 | Required in row | Required | Candidate | Same explicit wagering-state meaning as the cash block. |
termVariants[].stages[].components[blockType=freeSpins].wagering.multiplier | text decimal | 0..1 | Optional | Required only when state is required | Candidate | Exact multiplier. |
termVariants[].stages[].components[blockType=freeSpins].wagering.basis | select: bonusOnly, winningsOnly, bonusPlusDeposit | 0..1 | Optional | Required only when state is required | Candidate | Candidate basis enum. |
termVariants[].stages[].components[blockType=freeSpins].winningsCap | group exact upper limit | 0..1 | Optional | If included, state required; known value requires amount and currency | Candidate | Spin winnings cap, separate from the spin's face value. |
editorialCopy | group, fields localized | 1 | Optional in draft | Required per locale: title and summary | Existing proposal; Candidate: concrete localized group and title/summary minimum | Localized Offer copy; does not replace typed terms. |
editorialCopy.title | text (localized) | 1 per locale | Optional | Required for that locale's Offer publication | Candidate | Candidate field spelling/minimum. |
editorialCopy.summary | textarea (localized) | 1 per locale | Optional | Required for that locale's Offer publication | Candidate | Candidate field spelling/minimum. |
editorialCopy.body | richText (localized) | 0..1 per locale | Optional | Optional; included terms must agree with typed terms | Candidate | Reviewed explanation, not an alternate terms store. |
editorialCopy.seoTitle | text (localized) | 0..1 per locale | Optional | Optional | Candidate | Search presentation text. |
editorialCopy.seoDescription | textarea (localized) | 0..1 per locale | Optional | Optional | Candidate | Search presentation text. |
supportBindings | array | 0..n | Optional | Every published factual field/row has retained evidence and a typed field key | Existing proposal; Candidate: concrete row shape and binding granularity | Targets Offer root or stable term/stage/component row identity. |
unresolvedIssues | array | 0..n | Optional | Open issue blocks publication only when it affects required or included public terms | Existing proposal; Candidate: issue-row shape and conditional publication gate | Keep conflict or gap explicit; never resolve by arrival order. |
Native block/array IDs preserve child identity when update/import supplies them. Reordering a stage does not change its support binding. Currency variants select supported terms; they do not convert amounts, and two eligible rows may use the same currency. A shared lifecycle keeps cash and spins together when they form one proposition; separate conditions alone do not create another Offer.
evidence
Evidence is immutable retained support. It may originate from a manual admission; no parser execution or editorial generation record is required. A source URL is optional context, never sufficient evidence on its own. Evidence and bindings are private support, not public profile/Offer content.
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
origin | select: manualAdmission, retrievedCapture, other | 1 | Required to admit an immutable record | If used by a publication, included in the private support manifest | Candidate | Candidate origin values distinguish human admission from retrieval without requiring a parser. |
sourceIdentity | text | 1 | Required | Retained with referenced publication | Existing proposal; Candidate: text field type and requiredness | Name or stable identity of publisher/source; not a staff identity. |
sourceUrl | text | 0..1 | Optional | Optional provenance context; never satisfies retention alone | Existing proposal; Candidate: text field type and optionality | URL can later change or expire. Do not place private URLs in public page examples. |
capturedAt | date ISO-8601 instant | 0..1 | Optional for manual material; required for captured material | Required when origin is retrievedCapture | Existing proposal; Candidate: ISO date type and conditional requiredness | Capture time, distinct from author admission and publication time. |
admittedAt | date ISO-8601 instant | 1 | Required | Retained in support manifest | Candidate | Candidate admission timestamp for manual/retrieved material. |
retainedExcerpt | textarea | 0..1 | Optional if a retained artifact is present | Publication retains exact excerpt when relied upon | Existing proposal; Candidate: textarea type and evidence-admission rule | Captured excerpt or transcription; enough context to inspect the assertion. |
artifact | upload → media | 0..1 | Optional if a retained excerpt is present | Candidate gate: do not rely on it until private access and immutable retention are selected and proven; an existing media relationship alone proves neither | Candidate | Candidate reuse of existing media. One of excerpt or artifact must be present before evidence admission. The sample uses only retainedExcerpt; it claims no artifact ACL. |
contentIdentity | text | 1 | Required | Copied into retained support manifest | Existing proposal; Candidate: text type and admission minimum | Stable identity for retained content/capture; algorithm remains an implementation contract. |
No URL-only support, mutable-latest-document lookup, or public exposure of retained staff material is proposed. Evidence is write-once once admitted; correction adds new evidence and supersedes affected content.
Shared support and issue rows
These rows are owned by casinoProfiles or promotionalOffers; they do not become collections. targetRowId is Payload's stable child ID for an owned row, or empty only when the binding targets a root. fieldKey is selected from a code-defined typed vocabulary, not an arbitrary JSON path. The exact field-key registry is an implementation input; the examples here show the review shape.
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
supportBindings[].targetKind | select: root, ownedRow | 1 per row | Required in row | Required for each binding | Candidate | Candidate target shape. |
supportBindings[].targetRowId | text | 0..1 | Optional | Required when targetKind is ownedRow; must resolve to an existing child ID on this root | Candidate | Stable native array/block ID, not row position or copied component ID. |
supportBindings[].fieldKey | select | 1 per row | Required in row | Required; key must belong to target's typed shape | Candidate | Candidate allowlist includes legalStatement, paymentPolicy, cashierLimit, supportContact, offer.validity, offerTerm.eligibility, welcomeStage.qualifyingDeposit, welcomeStage.trigger, cashComponent, freeSpinsComponent, validity.endsAt, and editorialCopy.summary. |
supportBindings[].evidence | relationship → evidence | 1 per row | Required in row | Required for each public factual binding | Existing proposal; Candidate: exact relationship field path | Retained source material that supports the exact field. |
supportBindings[].excerptLocator | text | 0..1 | Optional | If available, retain exact page/section/time locator | Candidate | Points within the retained artifact; not a mutable remote lookup. |
unresolvedIssues[].kind | select: missing, conflict, identity, scope, unsupported | 1 per row | Required in row | Open issue on required/included public assertion blocks publication | Candidate | Candidate issue kinds; do not convert an issue into a guessed value. |
unresolvedIssues[].targetRowId | text | 0..1 | Optional | Required when issue concerns an owned child; must resolve to its stable ID | Candidate | Candidate row-target shape. |
unresolvedIssues[].fieldKey | select from the same typed key vocabulary | 0..1 | Optional | Required when issue concerns a specific field | Candidate | No arbitrary writable JSON path. |
unresolvedIssues[].summary | textarea | 1 per row | Required in row | Retain with publication review record when relevant | Candidate | Human-readable gap/conflict; no private staff analysis in public snapshot. |
unresolvedIssues[].status | select: open, resolved | 1 per row | Required in row | Must be resolved before publication if it affects an included assertion | Candidate | Candidate lifecycle state for a retained issue. |
unresolvedIssues[].resolution | textarea | 0..1 | Optional | Required when status is resolved | Candidate | Records how the issue was resolved; does not erase prior evidence. |
Shared nested field dictionaries
The following rows complete the exact paths inside the reusable groups above. Their candidate shapes are typed Payload groups/arrays; they are not generic JSON objects. Every row separates authoring-save completeness from the publish condition.
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
cashierTerms.limits[].value.state | select: known, unknown, unlimited, notApplicable | 1 per value | Required in row | Required; known requires amount and currency | Candidate | Candidate exact upper-limit states. |
cashierTerms.limits[].value.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Nonnegative canonical decimal text; 0 is a known zero limit. |
cashierTerms.limits[].value.currency | text | 0..1 | Optional | Required only when state is known | Candidate | Explicit source currency; no fallback. |
termVariants[].stages[].qualifyingDeposit.state | select: known, unknown, notApplicable | 1 when group exists | Required in row | known requires amount and currency | Candidate | Candidate state for a deposit trigger value. |
termVariants[].stages[].qualifyingDeposit.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Exact nonnegative amount. |
termVariants[].stages[].qualifyingDeposit.currency | text | 0..1 | Optional | Required only when state is known | Candidate | Explicit source currency. |
termVariants[].stages[].components[blockType=cash].award.maximum.state | select: known, unknown, unlimited, notApplicable | 1 when group exists | Required in row | known requires amount and currency | Candidate | Award maximum is not a cashout limit. |
termVariants[].stages[].components[blockType=cash].award.maximum.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Exact award ceiling. |
termVariants[].stages[].components[blockType=cash].award.maximum.currency | text | 0..1 | Optional | Required only when state is known | Candidate | Explicit source currency. |
termVariants[].stages[].components[blockType=cash].cashoutLimit.state | select: known, unknown, unlimited, notApplicable | 1 when group exists | Required in row | known requires amount and currency | Candidate | Offer cashout cap only; ordinary cashier limits stay on the profile. |
termVariants[].stages[].components[blockType=cash].cashoutLimit.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Exact upper limit. |
termVariants[].stages[].components[blockType=cash].cashoutLimit.currency | text | 0..1 | Optional | Required only when state is known | Candidate | Explicit source currency. |
termVariants[].stages[].components[blockType=freeSpins].spinValue.state | select: known, unknown, notApplicable | 1 when group exists | Required in row | known requires amount and currency | Candidate | none/unlimited do not describe a spin's face value. |
termVariants[].stages[].components[blockType=freeSpins].spinValue.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Exact nonnegative spin value. |
termVariants[].stages[].components[blockType=freeSpins].spinValue.currency | text | 0..1 | Optional | Required only when state is known | Candidate | Explicit source currency. |
termVariants[].stages[].components[blockType=freeSpins].winningsCap.state | select: known, unknown, unlimited, notApplicable | 1 when group exists | Required in row | known requires amount and currency | Candidate | Cap on spin winnings; distinct from spin face value. |
termVariants[].stages[].components[blockType=freeSpins].winningsCap.amount | text decimal | 0..1 | Optional | Required only when state is known | Candidate | Exact upper limit. |
termVariants[].stages[].components[blockType=freeSpins].winningsCap.currency | text | 0..1 | Optional | Required only when state is known | Candidate | Explicit source currency. |
termVariants[].validityOverride.state | select: known, unknown | 1 when group exists | Required in row | Required; known override dates must be ordered | Candidate | Candidate explicit state for variant-specific dates. |
termVariants[].validityOverride.startsAt | date ISO-8601 instant | 0..1 | Optional | Required only for a known start override | Candidate | Source-supported override, not publication time. |
termVariants[].validityOverride.endsAt | date ISO-8601 instant | 0..1 | Optional | Required only for a known end override | Candidate | Source-supported override. |
support.contacts[].languages[].value | text | 1 per row | Required in row | Retain exact stated language label | Candidate | Array rows have Payload's native hidden string ID. |
termVariants[].stages[].components[blockType=freeSpins].gameNames[].value | text | 1 per row | Required in row | Required when source limits spins to named games | Candidate | Not a canonical game identity; array rows have native hidden string IDs. |
Exact values and candidate validation
These are concrete review choices, not accepted numeric policy. For every decimal field above, propose a nonnegative fixed-point text value: no exponent, sign or separators; canonical zero is 0; no leading or trailing insignificant zeroes; at most 20 integer digits and 8 fractional digits. A stricter mechanic-specific bound may apply. Preserve the source decimal lexeme until validation; do not convert through JavaScript floating point. Each known money value requires its own explicit source currency. The example uses EUR only as a fictional value; no conversion, supported-currency list or fallback is selected.
| Descriptor | Candidate allowed states | Required companion fields and validation |
|---|---|---|
| Minimum money amount | known, unknown, notApplicable | known requires nonnegative decimal text and currency. Zero is a known value. none and unlimited are invalid. |
| Fee | known, unknown, none, notApplicable | known requires decimal and currency; none means the source explicitly says no fee. Zero remains a known zero fee. |
| Maximum/cap/upper limit | known, unknown, unlimited, notApplicable | known requires decimal and currency; unlimited requires an explicit source claim of no upper bound. none is not a cap value. |
| Wagering | required, none, unknown, notApplicable | required requires exact multiplier plus basis. none means explicitly no wagering requirement; zero is not a substitute. |
| Count | No nullable state field; store a number only when known | Count is a safe integer. A published free-spins benefit requires count greater than zero; a known zero is distinct from missing/unknown and is not a free-spins block. |
| Validity | known, unknown | A known range carries source-supported ISO instants and startsAt ≤ endsAt; publication time never fills a missing start. |
none, unlimited, unknown, notApplicable and numeric zero are not interchangeable. A field only permits the states listed for its descriptor. Missing currency never falls back to another variant, Market or locale. Competing supported statements stay as evidence plus an unresolved conflict until reviewed.
cataloguePublications
This immutable collection has exactly two proposed subject types: casinoProfile and bonusOffer. Snapshot content is validated against the subject-specific contentSchema; editable facts above remain native Payload fields. dependencies and supportManifest are immutable exact values retained for review, not writable domain-field bags.
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
publicationKey | text | 1 | No partial record; required on append | Required canonical key, server-derived from exact tuple | Existing proposal; Candidate: exact text encoding | Candidate wire encoding is shown in the example; not concatenated display labels. Profile tuple is subject + casinoId + marketKey + locale; Offer tuple is subject + stable offerId + locale. This field is not unique by itself. |
revision | number safe integer | 1 | Required on append | Monotonic positive revision within key; stale append rejected | Existing proposal; Candidate: safe-integer storage type | Unique constraint is (publicationKey, revision); no revision reused for a key. |
operation | select: publish, withdraw | 1 | Required on append | Required; withdrawal is another immutable entry and advances current selection | Existing proposal; Candidate: exact enum spellings | Explicit operation, not hard-delete. |
subjectType | select: casinoProfile, bonusOffer | 1 | Required on append | Must match the controlled subject relationship | Existing proposal; Candidate: exact enum spellings | Exactly two subject kinds in this slice. |
subject | polymorphic relationship → casinoProfiles OR promotionalOffers | 1 union | Required on append | Exactly one matching subject; context must agree | Existing proposal; Candidate: serialized relationship shape | Native polymorphic value is { "relationTo": "collectionSlug", "value": localId }; select exactly one of the two targets. |
priorPublication | relationship → cataloguePublications | 0..1 | Absent on publish; required on withdraw | Withdrawal pins the exact currently selected entry being withdrawn, with the same publicationKey | Existing proposal; Candidate: explicit local relationship field | A withdrawal is a new entry/revision; it does not point to a replacement draft or delete prior history. |
context | group with Casino, Market and locale | 1 | Required on append | Required; each value must agree with subject | Candidate | Candidate explicit frozen context group. |
context.casinoId | text | 1 | Required on append | Must match the subject's Casino mapping | Candidate | Frozen external Casino identity. |
context.marketKey | text | 1 | Required on append | Must match the subject's Market | Candidate | Frozen applicability context. |
context.locale | text | 1 | Required on append | Required for independent locale publication | Candidate | Must be a configured locale; no implicit locale fallback. |
sourceVersion | text | 1 for publish | Required on publish append | Pins exact native authoring version | Existing proposal; Candidate: text spelling and conditional requiredness | Native Payload version identity; not a second public-status field. |
inputIdentity | text | 1 for publish | Required on publish append | Approval binds to this exact resolved candidate and its dependencies | Candidate | Candidate stable identity for the reviewed input. Withdrawal pins the prior selected entry instead. |
approvedBy | relationship → users | 1 | Required on append | Required human actor for publish or authorized withdrawal | Existing proposal; Candidate: exact relationship path/cardinality | Reuses existing staff account; never exposed publicly. |
approvedAt | date ISO-8601 instant | 1 | Required on append | Required approval/withdrawal time | Existing proposal; Candidate: ISO date type and requiredness | Retained staff action time. |
reasonCode | select: initialPublication, contentCorrection, scheduledUpdate, withdrawal | 1 | Required on append | Required for publish and withdrawal | Candidate | Candidate reason-code values; remove/change through review. Retained with actor, time and exact input. |
reasonNote | textarea | 0..1 | Optional | Optional staff explanation; private | Existing proposal; Candidate: textarea spelling/type | Not part of public payload. |
contentSchema | text | 1 for publish | Required on publish append | Identifies subject-specific snapshot shape/version | Existing proposal; Candidate: exact v1 schema labels below | Withdrawal records explicit withdrawn operation and no actionable content. |
content | json, immutable validated snapshot | 1 for publish | Required on publish append | Validated per subject type and schema version | Existing proposal; Candidate: exact v1 subject schemas below | Snapshot JSON only; no untyped editable catalogue facts. Absent on withdrawal. |
dependencies | json, immutable validated manifest | 1 for publish | Required on publish append | Exact values/revisions used to compose the snapshot | Existing proposal; Candidate: typed dependency union below | No reconstruction from mutable live relations. Private; no arbitrary values bag. |
supportManifest | json, immutable validated manifest | 1 for publish | Required on publish append | Exact retained evidence/content identity used by snapshot | Existing proposal; Candidate: typed support-entry schema below | Private; public reads exclude it. |
Candidate immutable JSON shapes
contentSchema selects one of two fixed candidate structures. title, summary and SEO values are strings for the one locale in context.locale; body, when present, preserves its serialized rich-text object. Editable Payload authoring fields remain locale maps. The snapshot contains resolved display values, not live Payload relationship IDs. Every row in this dictionary is a candidate shape for stakeholder review.
| Snapshot JSON path | JSON field/type | Requiredness | Source | Meaning or validation |
|---|---|---|---|---|
casinoProfile.v1 | object | One per profile publication | Candidate | Versioned schema tag; not an executable API contract. |
casinoProfile.v1.casinoId, .marketKey, .locale | string | Required | Candidate | Frozen publication context matching the authoring subject. |
casinoProfile.v1.brand.name | string | Required | Candidate | Resolved Brand value. |
casinoProfile.v1.title, .summary | string | Required | Candidate | Selected-locale copy; context.locale identifies the locale. |
casinoProfile.v1.body | serialized rich-text object | Optional | Candidate | Selected-locale rich-text value; preserves the native editor representation. |
casinoProfile.v1.seoTitle, .seoDescription | string | Optional | Candidate | Selected-locale SEO text. |
casinoProfile.v1.legalStatements[] | array of fixed objects | Optional | Candidate | Each object has role, companyLegalName or assertedEntityName, assertion, and optional licenceNumber, regulatorName, jurisdiction. |
casinoProfile.v1.paymentPolicies[] | array of fixed objects | Optional | Candidate | Each object has methodName, direction, currency, minimum, maximum, fee, and processingTime; exact states and types follow the source field dictionary. |
casinoProfile.v1.cashierTerms.limits[] | array of fixed objects | Optional | Candidate | Each object has direction, period, conditional otherPeriod, basis, conditional timeZone/basisDescription, and value. |
casinoProfile.v1.support.contacts[] | array of fixed objects | Optional | Candidate | Each object has channel, optional availabilityStatement, and languages[] strings. |
bonusOffer.v1 | object | One per Offer publication | Candidate | Versioned schema tag; one Offer and locale per entry. |
bonusOffer.v1.offerId, .casinoId, .marketKey, .locale | string | Required | Candidate | Frozen subject and scope. |
bonusOffer.v1.purpose, .mechanic | string enum | Required | Candidate | Values must match the typed candidate definitions above. |
bonusOffer.v1.validity | fixed object | Required | Candidate | state plus conditional startsAt and endsAt ISO instants. |
bonusOffer.v1.termVariants[] | array of fixed objects | At least one | Candidate | Each has currency, eligibility, optional validityOverride, and stages[]; same-currency eligible variants remain distinct. |
bonusOffer.v1.termVariants[].stages[] | array of fixed objects | At least one for welcomePackage | Candidate | Each has trigger, conditional qualifyingDeposit, and components[]. |
bonusOffer.v1.termVariants[].stages[].components[] | discriminated union object | At least one per published welcome stage | Candidate | blockType=cash carries award, wagering, optional cashoutLimit; blockType=freeSpins carries count, gameNames[], optional spinValue, wagering, winningsCap. No nested block-name group or untyped attributes bag. |
bonusOffer.v1.title, .summary | string | Required | Candidate | Selected-locale copy; context.locale identifies the locale. |
bonusOffer.v1.body | serialized rich-text object | Optional | Candidate | Selected-locale rich-text value; preserves the native editor representation. |
bonusOffer.v1.seoTitle, .seoDescription | string | Optional | Candidate | Selected-locale SEO text. |
dependencies is an array of fixed, discriminated dependency entries. The kind field selects the permitted fields; the local ID uses the configured Payload collection-ID scalar and versionIdentity pins an exact retained version when the source has versions. No entry has a free-form values object.
| Dependency JSON path | JSON type | Required by kind | Source | Meaning |
|---|---|---|---|---|
dependencies[].kind | string enum: casino, brand, market, company, paymentMethod, media | Always | Candidate | Selects exactly one typed dependency variant. |
dependencies[].localId | configured native Payload ID scalar | Always | Candidate | Local relationship identity only; no forced UUID representation. |
dependencies[].versionIdentity | string | When an exact native version exists | Candidate | Pins the resolved version used by the snapshot. |
dependencies[].casinoId | string | casino | Candidate | Core Casino mapping. |
dependencies[].name | string | brand | Candidate | Exact resolved Brand name. |
dependencies[].key, dependencies[].label, dependencies[].scopeKind, dependencies[].scopeDescription | string | market | Candidate | Exact Market identity and scope used for the publication. |
dependencies[].legalName, dependencies[].registrationIdentifier, dependencies[].registrationJurisdiction | string | company | Candidate | Exact resolved Company values when present. |
dependencies[].key, dependencies[].displayName | string | paymentMethod | Candidate | Exact resolved Payment Method identity/display values. |
dependencies[].mediaIdentity | string | media | Candidate | Exact retained media identity, never a mutable remote URL alone. |
supportManifest is an array of fixed support entries. Each entry binds a public subject path to one admitted evidence identity and copies enough retained material to inspect that support after the evidence record or remote source changes. Each key below is typed; no generic arbitrary JSON path or source-value bag is permitted.
| Support JSON path | JSON type | Requiredness | Source | Meaning |
|---|---|---|---|---|
supportManifest[].targetKind | string enum: root, ownedRow | Required | Candidate | Root or stable row target. |
supportManifest[].targetRowId | string | Required when target is ownedRow | Candidate | Exact Payload array/block child ID. |
supportManifest[].fieldKey | string from the same allowlisted typed vocabulary | Required | Candidate | Exact semantic field, not an arbitrary JSON path. |
supportManifest[].evidenceId | configured native Payload ID scalar | Required | Candidate | Local Evidence identity. |
supportManifest[].contentIdentity, supportManifest[].origin, supportManifest[].sourceIdentity | string | Required | Candidate | Exact admitted material identity and origin. |
supportManifest[].admittedAt | ISO-8601 instant | Required | Candidate | Admission time. |
supportManifest[].capturedAt | ISO-8601 instant | Required only for captured material | Candidate | Capture time, if applicable. |
supportManifest[].retainedExcerpt | string | Required when the entry relies on an excerpt | Candidate | Exact excerpt retained with this publication. |
supportManifest[].artifactIdentity | string | Optional; only after private immutable media handling is selected and proven | Candidate | Exact artifact reference. A media relationship alone establishes neither private access nor immutable retention. |
supportManifest[].excerptLocator | string | Optional | Candidate | Locator within retained material. |
Proposed write rule: append entry, advance its selection and create delivery intent in the same already-active database transaction. Any failure rolls all three back. A delayed publish delivery cannot undo a later withdrawal. Keep staff identity, reason, draft notes and private manifests out of public responses. This is a proposal contract, not proof of a migration, transaction guard or API.
publicationSelections
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
publicationKey | text unique | 1 | Required on pointer write | Exact same canonical key as current entry | Existing proposal; Candidate: exact serialization/type (selection row unique; entry row not unique) | One current pointer per publication key. |
publication | relationship → cataloguePublications | 1 | Required on pointer write | Points to the newest immutable entry, including withdrawal | Existing proposal; Candidate: exact relationship path and requiredness | No mutable authoring content on selection. |
revision | number safe integer | 1 | Required on pointer write | Must equal the pointed entry's revision and advance monotonically | Candidate | Candidate denormalized guard for the current revision. |
This collection is a small mutable pointer. It is not a second content authority, and a pointer change cannot rewrite an earlier snapshot.
publicationDeliveries
| Field path | Payload field / target | Cardinality | Draft save | Publication gate | Source | Meaning or proposed validation |
|---|---|---|---|---|---|---|
deliveryIdentity | text unique | 1 | Required when intent is created | Stable across retries for the same exact entry and target | Existing proposal; Candidate: text type and delivery-key spelling | Durable deduplication identity. |
publication | relationship → cataloguePublications | 1 | Required when intent is created | Exact immutable entry; never a live authoring lookup | Existing proposal; Candidate: exact relationship path and requiredness | Retains publish or withdrawal order. |
target | select: coreCatalogueAdapter | 1 | Required when intent is created | Exact selected consumer target | Candidate | Candidate target value for this bounded slice. |
status | select: pending, delivered, retryable, superseded | 1 | Required when intent is created | Acknowledgement updates delivery state only, never snapshot content | Candidate | Candidate minimal delivery states; delayed older publish must be superseded after withdrawal. |
attemptCount | number safe integer | 1 | Defaults to 0 | Nonnegative; increments for each attempt | Candidate | Candidate delivery counter. |
lastAttemptAt | date ISO-8601 instant | 0..1 | Optional before first attempt | Set only after an attempt | Candidate | Technical delivery metadata. |
acknowledgedAt | date ISO-8601 instant | 0..1 | Optional until acknowledgement | Set with delivered; must refer to exact entry | Candidate | Acknowledgement time. |
The outbox intent is created with the immutable entry and current selection. Retry state does not edit the approved publication.
Synthetic end-to-end example
Every name, ID, amount, date, assertion and URL-like identifier below is fictional. Collection id values illustrate the configured native Payload ID type; owned array/block id values are native stable string row IDs. approvedBy: 501 is a fictional relationship to an existing users record, intentionally outside these 11 collection roots. The authoring copy maps each localized field to a locale; each immutable content object is the exact single-locale projection named by context.locale. The two publications share one dataset but have separate profile and Offer keys, revisions, selections and deliveries.
{
"brands": [
{ "id": 1, "name": "Example Lantern", "aliases": [{ "id": "brand-alias-1", "value": "Lantern Demo" }] }
],
"casinos": [
{ "id": 10, "casinoId": "casino_demo_0042", "brand": 1, "staffLabel": "Lantern sample record" }
],
"markets": [
{ "id": 20, "key": "example-market", "label": "Example Market", "scopeKind": "audience", "scopeDescription": "Fictional adult audience used only to demonstrate field shape." }
],
"companies": [
{ "id": 40, "legalName": "Example Lantern Operations Ltd" }
],
"paymentMethods": [
{ "id": 30, "key": "example-transfer", "displayName": "Example Transfer" }
],
"evidence": [
{
"id": 60,
"origin": "manualAdmission",
"sourceIdentity": "Fictional review-page illustration",
"admittedAt": "2026-10-05T10:00:00.000Z",
"retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.",
"contentIdentity": "illustration:payload-fields:1"
}
],
"casinoProfiles": [
{
"id": 70,
"casino": 10,
"market": 20,
"legalStatements": [
{ "id": "legal-row-1", "role": "operator", "company": 40, "assertedEntityName": "Example Lantern Operations Ltd", "assertion": "Fictional operator relationship for schema illustration." }
],
"paymentPolicies": [
{
"id": "payment-row-1",
"paymentMethod": 30,
"direction": "deposit",
"currency": "EUR",
"minimum": { "state": "known", "amount": "10" },
"maximum": { "state": "unknown" },
"fee": { "state": "none" },
"processingTime": { "state": "unknown" }
}
],
"cashierTerms": {
"limits": [
{ "id": "cashier-limit-1", "direction": "withdrawal", "period": "daily", "basis": "rolling", "value": { "state": "known", "amount": "500", "currency": "EUR" } }
]
},
"support": {
"contacts": [
{ "id": "support-contact-1", "channel": "liveChat", "availabilityStatement": "Fictional example hours: weekdays, 09:00–17:00 Example Time.", "languages": [{ "id": "support-language-1", "value": "en" }] }
]
},
"editorialCopy": {
"title": { "en": "Example Lantern in Example Market" },
"summary": { "en": "Fictional copy showing one localized profile." }
},
"supportBindings": [
{ "id": "profile-binding-1", "targetKind": "ownedRow", "targetRowId": "legal-row-1", "fieldKey": "legalStatement", "evidence": 60, "excerptLocator": "illustration:operator-role" },
{ "id": "profile-binding-2", "targetKind": "ownedRow", "targetRowId": "payment-row-1", "fieldKey": "paymentPolicy", "evidence": 60, "excerptLocator": "illustration:example-transfer-deposit" },
{ "id": "profile-binding-3", "targetKind": "ownedRow", "targetRowId": "cashier-limit-1", "fieldKey": "cashierLimit", "evidence": 60, "excerptLocator": "illustration:daily-withdrawal-limit" },
{ "id": "profile-binding-4", "targetKind": "ownedRow", "targetRowId": "support-contact-1", "fieldKey": "supportContact", "evidence": 60, "excerptLocator": "illustration:live-chat" }
],
"unresolvedIssues": []
}
],
"promotionalOffers": [
{
"id": 80,
"offerId": "offer_demo_welcome_1",
"casino": 10,
"market": 20,
"purpose": "welcome",
"mechanic": "welcomePackage",
"validity": { "state": "known", "startsAt": "2026-10-01T00:00:00.000Z", "endsAt": "2026-12-31T23:59:59.000Z" },
"termVariants": [
{
"id": "term-eur-1",
"currency": "EUR",
"eligibility": { "audience": "newCustomers", "conditions": "Fictional first-deposit condition." },
"stages": [
{
"id": "stage-first-deposit-1",
"displayOrder": 1,
"trigger": "firstDeposit",
"qualifyingDeposit": { "state": "known", "amount": "10", "currency": "EUR" },
"components": [
{
"id": "cash-block-1",
"blockType": "cash",
"award": { "kind": "percentage", "amount": "100", "rateBasis": "depositAmount", "maximum": { "state": "known", "amount": "500", "currency": "EUR" } },
"wagering": { "state": "required", "multiplier": "30", "basis": "bonusPlusDeposit" },
"cashoutLimit": { "state": "known", "amount": "50", "currency": "EUR" }
},
{
"id": "free-spins-block-1",
"blockType": "freeSpins",
"count": 20,
"gameNames": [{ "id": "game-name-1", "value": "Example Game" }],
"spinValue": { "state": "known", "amount": "0.2", "currency": "EUR" },
"wagering": { "state": "required", "multiplier": "40", "basis": "winningsOnly" },
"winningsCap": { "state": "known", "amount": "100", "currency": "EUR" }
}
]
}
]
}
],
"editorialCopy": {
"title": { "en": "Example Lantern welcome package" },
"summary": { "en": "Fictional cash and spins terms for the schema example." }
},
"supportBindings": [
{ "id": "offer-binding-1", "targetKind": "root", "fieldKey": "offer.validity", "evidence": 60, "excerptLocator": "illustration:validity" },
{ "id": "offer-binding-2", "targetKind": "ownedRow", "targetRowId": "term-eur-1", "fieldKey": "offerTerm.eligibility", "evidence": 60, "excerptLocator": "illustration:new-customers" },
{ "id": "offer-binding-3", "targetKind": "ownedRow", "targetRowId": "stage-first-deposit-1", "fieldKey": "welcomeStage.qualifyingDeposit", "evidence": 60, "excerptLocator": "illustration:first-deposit" },
{ "id": "offer-binding-6", "targetKind": "ownedRow", "targetRowId": "stage-first-deposit-1", "fieldKey": "welcomeStage.trigger", "evidence": 60, "excerptLocator": "illustration:stage-trigger" },
{ "id": "offer-binding-4", "targetKind": "ownedRow", "targetRowId": "cash-block-1", "fieldKey": "cashComponent", "evidence": 60, "excerptLocator": "illustration:cash-benefit" },
{ "id": "offer-binding-5", "targetKind": "ownedRow", "targetRowId": "free-spins-block-1", "fieldKey": "freeSpinsComponent", "evidence": 60, "excerptLocator": "illustration:spin-benefit" }
],
"unresolvedIssues": []
}
],
"cataloguePublications": [
{
"id": 100,
"publicationKey": "v1:[\"casinoProfile\",\"casino_demo_0042\",\"example-market\",\"en\"]",
"revision": 1,
"operation": "publish",
"subjectType": "casinoProfile",
"subject": { "relationTo": "casinoProfiles", "value": 70 },
"context": { "casinoId": "casino_demo_0042", "marketKey": "example-market", "locale": "en" },
"sourceVersion": "example-profile-version-1",
"inputIdentity": "example-profile-candidate-1",
"approvedBy": 501,
"approvedAt": "2026-10-05T11:00:00.000Z",
"reasonCode": "initialPublication",
"contentSchema": "casinoProfile.v1",
"content": {
"casinoId": "casino_demo_0042",
"marketKey": "example-market",
"locale": "en",
"brand": { "name": "Example Lantern" },
"title": "Example Lantern in Example Market",
"summary": "Fictional copy showing one localized profile.",
"legalStatements": [{ "role": "operator", "companyLegalName": "Example Lantern Operations Ltd", "assertion": "Fictional operator relationship for schema illustration." }],
"paymentPolicies": [{ "methodName": "Example Transfer", "direction": "deposit", "currency": "EUR", "minimum": { "state": "known", "amount": "10" }, "maximum": { "state": "unknown" }, "fee": { "state": "none" }, "processingTime": { "state": "unknown" } }],
"cashierTerms": { "limits": [{ "direction": "withdrawal", "period": "daily", "basis": "rolling", "value": { "state": "known", "amount": "500", "currency": "EUR" } }] },
"support": { "contacts": [{ "channel": "liveChat", "availabilityStatement": "Fictional example hours: weekdays, 09:00–17:00 Example Time.", "languages": ["en"] }] }
},
"dependencies": [
{ "kind": "casino", "localId": 10, "casinoId": "casino_demo_0042" },
{ "kind": "brand", "localId": 1, "name": "Example Lantern" },
{ "kind": "market", "localId": 20, "key": "example-market", "label": "Example Market", "scopeKind": "audience", "scopeDescription": "Fictional adult audience used only to demonstrate field shape." },
{ "kind": "company", "localId": 40, "legalName": "Example Lantern Operations Ltd" },
{ "kind": "paymentMethod", "localId": 30, "key": "example-transfer", "displayName": "Example Transfer" }
],
"supportManifest": [
{ "targetKind": "ownedRow", "targetRowId": "legal-row-1", "fieldKey": "legalStatement", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:operator-role" },
{ "targetKind": "ownedRow", "targetRowId": "payment-row-1", "fieldKey": "paymentPolicy", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:example-transfer-deposit" },
{ "targetKind": "ownedRow", "targetRowId": "cashier-limit-1", "fieldKey": "cashierLimit", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:daily-withdrawal-limit" },
{ "targetKind": "ownedRow", "targetRowId": "support-contact-1", "fieldKey": "supportContact", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:live-chat" }
]
},
{
"id": 101,
"publicationKey": "v1:[\"bonusOffer\",\"offer_demo_welcome_1\",\"en\"]",
"revision": 1,
"operation": "publish",
"subjectType": "bonusOffer",
"subject": { "relationTo": "promotionalOffers", "value": 80 },
"context": { "casinoId": "casino_demo_0042", "marketKey": "example-market", "locale": "en" },
"sourceVersion": "example-offer-version-1",
"inputIdentity": "example-offer-candidate-1",
"approvedBy": 501,
"approvedAt": "2026-10-05T11:05:00.000Z",
"reasonCode": "initialPublication",
"contentSchema": "bonusOffer.v1",
"content": {
"offerId": "offer_demo_welcome_1",
"casinoId": "casino_demo_0042",
"marketKey": "example-market",
"locale": "en",
"purpose": "welcome",
"mechanic": "welcomePackage",
"validity": { "state": "known", "startsAt": "2026-10-01T00:00:00.000Z", "endsAt": "2026-12-31T23:59:59.000Z" },
"termVariants": [{ "currency": "EUR", "eligibility": { "audience": "newCustomers", "conditions": "Fictional first-deposit condition." }, "stages": [{ "trigger": "firstDeposit", "qualifyingDeposit": { "state": "known", "amount": "10", "currency": "EUR" }, "components": [{ "blockType": "cash", "award": { "kind": "percentage", "amount": "100", "rateBasis": "depositAmount", "maximum": { "state": "known", "amount": "500", "currency": "EUR" } }, "wagering": { "state": "required", "multiplier": "30", "basis": "bonusPlusDeposit" }, "cashoutLimit": { "state": "known", "amount": "50", "currency": "EUR" } }, { "blockType": "freeSpins", "count": 20, "gameNames": ["Example Game"], "spinValue": { "state": "known", "amount": "0.2", "currency": "EUR" }, "wagering": { "state": "required", "multiplier": "40", "basis": "winningsOnly" }, "winningsCap": { "state": "known", "amount": "100", "currency": "EUR" } }] }] }],
"title": "Example Lantern welcome package",
"summary": "Fictional cash and spins terms for the schema example."
},
"dependencies": [
{ "kind": "casino", "localId": 10, "casinoId": "casino_demo_0042" },
{ "kind": "brand", "localId": 1, "name": "Example Lantern" },
{ "kind": "market", "localId": 20, "key": "example-market", "label": "Example Market", "scopeKind": "audience", "scopeDescription": "Fictional adult audience used only to demonstrate field shape." }
],
"supportManifest": [
{ "targetKind": "root", "fieldKey": "offer.validity", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:validity" },
{ "targetKind": "ownedRow", "targetRowId": "term-eur-1", "fieldKey": "offerTerm.eligibility", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:new-customers" },
{ "targetKind": "ownedRow", "targetRowId": "stage-first-deposit-1", "fieldKey": "welcomeStage.qualifyingDeposit", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:first-deposit" },
{ "targetKind": "ownedRow", "targetRowId": "stage-first-deposit-1", "fieldKey": "welcomeStage.trigger", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:stage-trigger" },
{ "targetKind": "ownedRow", "targetRowId": "cash-block-1", "fieldKey": "cashComponent", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:cash-benefit" },
{ "targetKind": "ownedRow", "targetRowId": "free-spins-block-1", "fieldKey": "freeSpinsComponent", "evidenceId": 60, "contentIdentity": "illustration:payload-fields:1", "origin": "manualAdmission", "sourceIdentity": "Fictional review-page illustration", "admittedAt": "2026-10-05T10:00:00.000Z", "retainedExcerpt": "Fictional example only: Example Lantern is the Brand. Example Lantern Operations Ltd is identified as operator. Example Transfer accepts deposits in EUR; the stated deposit minimum is EUR 10, no deposit fee is charged, and no deposit maximum or processing time is stated. The cashier terms state a rolling daily withdrawal limit of EUR 500. The profile states live chat is available weekdays from 09:00 to 17:00 Example Time and is offered in English. The welcome package is for new customers after a first deposit of EUR 10, is available from 1 October 2026 through 31 December 2026, and gives a 100% deposit match up to EUR 500 with 30x bonus-plus-deposit wagering and a EUR 50 cashout cap. It also gives 20 Example Game spins worth EUR 0.2 each, with 40x winnings-only wagering and a EUR 100 winnings cap. All names and terms in this excerpt are fictional.", "excerptLocator": "illustration:spin-benefit" }
]
}
],
"publicationSelections": [
{ "id": 110, "publicationKey": "v1:[\"casinoProfile\",\"casino_demo_0042\",\"example-market\",\"en\"]", "publication": 100, "revision": 1 },
{ "id": 111, "publicationKey": "v1:[\"bonusOffer\",\"offer_demo_welcome_1\",\"en\"]", "publication": 101, "revision": 1 }
],
"publicationDeliveries": [
{ "id": 120, "deliveryIdentity": "example-delivery-profile-1", "publication": 100, "target": "coreCatalogueAdapter", "status": "pending", "attemptCount": 0, "lastAttemptAt": null, "acknowledgedAt": null },
{ "id": 121, "deliveryIdentity": "example-delivery-offer-1", "publication": 101, "target": "coreCatalogueAdapter", "status": "pending", "attemptCount": 0, "lastAttemptAt": null, "acknowledgedAt": null }
]
}
The sample profile and Offer are independent publication units. The ordinary cashier withdrawal limit (500 EUR/day rolling in this fictional data) is distinct from the Offer cashout cap (50 EUR); the Offer award ceiling (500 EUR) is a third value. Cash and free-spin wagering retain their own bases. The JSON illustrates native relationship/row identity and proposed snapshot intent; it is not an executable Payload config, JSON Schema or API DTO.
Review checklist
Please identify feedback with the exact collection and field path. In particular, decide the candidate field types and enum values; whether the proposed profile and welcome Offer minimums fit a manual first model; which fields should remain saveable while incomplete; and whether a future cashback, VIP or event shape needs another selected typed increment. Also flag any relationship, currency, source-support or publication state that the sample fails to preserve.
Recorded outcome
No decision recorded. Reviewing this model or its editorial wording does not approve product policy, implementation, migration, API contract, schedule or deployment. Record an actual agreement in the authoritative owner and update this page to the reviewed revision and conditions.