diff --git a/clients/pricing-client/src/openapi-runtime.json b/clients/pricing-client/src/openapi-runtime.json index fd88bb0a7..12f4b3521 100644 --- a/clients/pricing-client/src/openapi-runtime.json +++ b/clients/pricing-client/src/openapi-runtime.json @@ -481,54 +481,6 @@ "responses": {} } }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants:list": { - "post": { - "operationId": "$listConditionalVariants", - "parameters": [ - { - "in": "path", - "name": "slug", - "required": true - }, - { - "in": "path", - "name": "entity_id", - "required": true - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": {} - } - }, - "responses": {} - } - }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants:tree": { - "post": { - "operationId": "$getConditionalVariantTree", - "parameters": [ - { - "in": "path", - "name": "slug", - "required": true - }, - { - "in": "path", - "name": "entity_id", - "required": true - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": {} - } - }, - "responses": {} - } - }, "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}": { "get": { "operationId": "$getActiveConditionalVariantVersion", @@ -628,42 +580,6 @@ } }, "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions": { - "get": { - "operationId": "$listConditionalVariantVersions", - "parameters": [ - { - "in": "path", - "name": "slug", - "required": true - }, - { - "in": "path", - "name": "entity_id", - "required": true - }, - { - "in": "path", - "name": "variant_id", - "required": true - }, - { - "in": "query", - "name": "limit", - "required": false - }, - { - "in": "query", - "name": "order", - "required": false - }, - { - "in": "query", - "name": "cursor", - "required": false - } - ], - "responses": {} - }, "post": { "operationId": "$appendConditionalVariantVersion", "parameters": [ @@ -814,44 +730,6 @@ ], "responses": {} } - }, - "/v1/conditional-pricing/{slug}/variants:batchUpsert": { - "post": { - "operationId": "$batchUpsertConditionalVariants", - "parameters": [ - { - "in": "path", - "name": "slug", - "required": true - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": {} - } - }, - "responses": {} - } - }, - "/v1/conditional-pricing/{slug}/variants:batchDelete": { - "post": { - "operationId": "$batchDeleteConditionalVariants", - "parameters": [ - { - "in": "path", - "name": "slug", - "required": true - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": {} - } - }, - "responses": {} - } } }, "components": {} diff --git a/clients/pricing-client/src/openapi.d.ts b/clients/pricing-client/src/openapi.d.ts index 8260a3187..8fddb7acc 100644 --- a/clients/pricing-client/src/openapi.d.ts +++ b/clients/pricing-client/src/openapi.d.ts @@ -172,7 +172,8 @@ declare namespace Components { * When this version takes effect. Defaults to now. * * An RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time - * (`2026-01-01T00:00:00Z`), to at most millisecond precision. + * (`2026-01-01T00:00:00Z`), to at most millisecond precision. Deliberately not declared as + * `format: date-time`, which would reject the plain-date form that this accepts. * * A date in the past is accepted and answered with warnings, never refused. A date the * variant already has a version at is refused as `VERSION_CONFLICT`. @@ -186,11 +187,23 @@ declare namespace Components { * 2027-01-01T00:00:00Z */ valid_from?: string; - /** - * The attribute overrides this version carries. An append seeds the attributes the variant - * may not override from the version in effect at this version's own `valid_from` and then - * applies these values over them, so the stored values are not a pure function of this - * body. An append dated before the variant's earliest version inherits nothing. + values: /** + * The attribute values this version overrides on the base entity, keyed by attribute name. + * + * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields + * (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable + * attributes present here are ignored rather than rejected, so a client working from a slightly + * stale schema snapshot still succeeds instead of failing on fields it could not have known to + * drop. An attribute's `render_condition` says when to show it and has no bearing on whether a + * variant may override it. + * + * Ignored means *not updated*, never *removed*: a value already stored for an attribute that is + * not currently overridable is preserved, so removing and restoring the flag deactivates and + * then reactivates the same override. + * + * A composite price's `price_components` is an ordinary overridable relation attribute: a + * composite variant pins its component variants here the same way any other relation value is + * set, with no special handling. * * example: * { @@ -198,9 +211,7 @@ declare namespace Components { * "unit_amount_decimal": "24.99" * } */ - values: { - [name: string]: any; - }; + VariantValues; /** * Optional, and never applied: a variant's conditions are fixed when it is created. Accepted * only so that a client building its body from the version it loaded is not forced to strip @@ -514,12 +525,6 @@ declare namespace Components { * The flag for prices that contain price components. */ is_composite_price: true; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * The price creation date */ @@ -601,12 +606,6 @@ declare namespace Components { Currency; cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; active?: boolean; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Whether the coupon requires a promo code to be applied */ @@ -953,12 +952,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -1299,12 +1292,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -1525,12 +1512,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -1626,6459 +1607,173 @@ declare namespace Components { */ base_url?: string; } + export type BillingPeriod = "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly"; /** - * A delete addressing its variant by the situation it applies to — the form an importer uses - * when it knows the source rows rather than the ids they produced. - * - * `conditions` is optional because the entity's fallback variant pins nothing: an item - * addressing it sends `default: true` and no `conditions`, exactly as a create marks one. - * - * **An item that addresses no variant is a per-item `VARIANT_UNPINNED`, not an envelope - * `400` and not a `skipped`.** Three shapes reach it: no `conditions` and no `default`, - * `conditions: {}`, and `default: false` alone — an empty postal-code column in a source row, - * serialized one way or another. - * - * Two more shapes validate here and are refused per item rather than described by the schema: - * an item marking `default` while also pinning `conditions` — a fallback variant applies only - * when nothing else does, so it cannot also pin — and an item carrying `valid_from` with no - * variant addressed at all. Both carry a message and no code, as the create path refuses the - * first today. - * + * A valid cart payload from a client. */ - export interface BatchDeleteByConditions { + export interface CartDto { + metadata?: /* A set of key-value pairs used to store meta data information about an entity. */ MetaData; + customer?: Customer; + billing_address?: Address; + delivery_address?: Address; /** - * The conditional entity the variant belongs to. Required, as it is beside a `variant_id`. - * + * type of source, e.g. journey or manual * example: - * price-sp26d1yo + * journey */ - entity_id: string; - conditions?: /** - * The situation this variant applies to: a flat map keyed by condition name, as the entity's - * schema declares them. A condition left out is a wildcard — the variant applies whatever the - * context says for it, which is what makes adding a condition to a schema non-breaking for the - * variants that already exist. - * - * Exact values only. A predicate is a read-side thing — a resolve context or a listing's - * condition filter — and is never stored: what a variant applies to is one situation, not a - * range of them. - * - * Values are typed by their condition and stored canonicalized for that type: a `date` becomes - * millisecond-precision UTC, a `daterange` an object carrying `from` and `until` where an empty - * string is an open end, a `location` of format `zipcode` the postal code itself and one of - * format `zipcode_town` an object carrying both. A `select` value must be a string, and must - * be one the condition's `options` declare, which is always a closed vocabulary. - * - * `default`, and any name beginning with `_`, are reserved for the server and cannot be pinned - * here. Whether a variant is the entity's fallback is set through the request's `default` flag. - * + source_type?: string; + /** + * identifier for source e.g. journey ID * example: - * { - * "postal_code": "46045" - * } + * ce99875f-fba9-4fe2-a8f9-afaf52059051 */ - PinnedConditions; - /** - * Address the entity's fallback variant, the one it serves when nothing else applies. A - * property of the variant, as it is on a write, never an entry in `conditions`. + source_id?: string; + source?: /* The order generation source */ OrderSource; + additional_addresses?: Address[]; + payment_method?: /** + * A PaymentMethod represent your customer's payment instruments. * */ - default?: boolean; + PaymentMethod; + line_items: /* A valid set of product prices, quantities, (discounts) and taxes from a client. */ PriceItemsDto; /** - * The one version to remove, by the instant it takes effect. Omitted, the whole variant - * goes. + * An array of file IDs, already upload into the File API, that are related with this cart + */ + files?: string[]; + status?: /** * - * An RFC 3339 date or date-time, to at most millisecond precision, canonicalized before it - * is matched. + * | status | description | + * |-------------|-------| + * | `draft` | ​​Starting state for all orders, at this point we can still edit the order | + * | `quote` | The order is in a quoting phase, bound to an expiration date | + * | `placed` | The order has been paid and can now be fulfilled (shipped, delivered, complete) or canceled | + * | `cancelled` | The order has been cancelled | + * | `completed` | The order is now closed and finalized | * - * example: - * 2027-01-01T00:00:00Z */ - valid_from?: string; + OrderStatus; + tags?: string[]; + journey_data?: { + [name: string]: any; + }; + consents?: { + [name: string]: any; + }; } /** - * A delete addressing its variant by id — the form a cleanup pass uses after the schema has - * drifted, since a tuple naming a condition the schema no longer declares addresses nothing. - * + * A detail associated with a specific cashback. */ - export interface BatchDeleteByVariantId { + export interface CashbackAmount { /** - * The conditional entity the variant belongs to. **Required beside `variant_id`, and not - * redundant**: a variant id alone addresses nothing in this API. - * - * example: - * price-sp26d1yo + * The name of the cashback. */ - entity_id: string; + cashback_name?: string; + cashback_period: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; /** - * The variant to remove, or whose version to remove. - * example: - * var-46045 + * The sum of all cashbacks for a specific cashback period */ - variant_id: string; + amount_total: number; + } + export interface CashbackAmounts { /** - * The one version to remove, by the instant it takes effect. Omitted, the whole variant - * goes — its tuple, its index registration and every version it accumulated. - * - * An RFC 3339 date or date-time, to at most millisecond precision, canonicalized before it - * is matched. - * - * example: - * 2027-01-01T00:00:00Z + * The cashback amount. */ - valid_from?: string; - } - /** - * How many items reached each outcome. Keyed by exactly the values of `BatchDeleteOutcome`, all - * of them present, and summing to the length of `results`. No `total`. - * - */ - export interface BatchDeleteCounts { + cashback_amount?: number; /** - * example: - * 1 + * The cashback amount as a string with all the decimal places. */ - deleted: number; + cashback_amount_decimal?: string; + cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; /** - * example: - * 1 + * Total amount after cashback is applied. */ - skipped: number; + after_cashback_amount_total?: number; /** - * example: - * 1 + * Total amount after cashback is applied as a string with all the decimal places. */ - error: number; + after_cashback_amount_total_decimal?: string; } /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - export type BatchDeleteItem = /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - /** - * A delete addressing its variant by id — the form a cleanup pass uses after the schema has - * drifted, since a tuple naming a condition the schema no longer declares addresses nothing. - * - */ - BatchDeleteByVariantId | /** - * A delete addressing its variant by the situation it applies to — the form an importer uses - * when it knows the source rows rather than the ids they produced. - * - * `conditions` is optional because the entity's fallback variant pins nothing: an item - * addressing it sends `default: true` and no `conditions`, exactly as a create marks one. - * - * **An item that addresses no variant is a per-item `VARIANT_UNPINNED`, not an envelope - * `400` and not a `skipped`.** Three shapes reach it: no `conditions` and no `default`, - * `conditions: {}`, and `default: false` alone — an empty postal-code column in a source row, - * serialized one way or another. - * - * Two more shapes validate here and are refused per item rather than described by the schema: - * an item marking `default` while also pinning `conditions` — a fallback variant applies only - * when nothing else does, so it cannot also pin — and an item carrying `valid_from` with no - * variant addressed at all. Both carry a message and no code, as the create path refuses the - * first today. - * + * The cashback period, for now it's limited to either 0 months or 12 months */ - BatchDeleteByConditions; + export type CashbackPeriod = "0" | "12"; /** - * What one delete item did. - * - * - `deleted`: the variant, or the one version the item named, is gone. - * - `skipped`: the item addressed nothing — **the variant or the version**, never the entity. An - * entity that cannot answer the item is an `error` carrying `ENTITY_NOT_FOUND`, - * `ENTITY_TYPE_MISMATCH` or `ENTITY_NOT_CONDITIONAL`. - * - `error`: this item alone failed, and the entry's `error` says why. + * List of entity fields to include or exclude from the results. * + * example: + * [ + * "!_files", + * "!**.versions" + * ] */ - export type BatchDeleteOutcome = "deleted" | "skipped" | "error"; + export type CatalogFieldsParam = string[]; /** - * What a batch delete did: one entry per item, in request order, and a count per outcome. - * + * A catalog search payload + * example: + * { + * "q": "_id:1233432 OR _id:123432454 OR _id:23445433", + * "sort": "description ASC", + * "from": 0, + * "size": 200 + * } */ - export interface BatchDeleteResult { - /** - * The `correlation_id` the request carried, echoed only when it was sent. - * example: - * postal-code-cleanup-2026-09 - */ - correlation_id?: string; - counts: /** - * How many items reached each outcome. Keyed by exactly the values of `BatchDeleteOutcome`, all - * of them present, and summing to the length of `results`. No `total`. - * - */ - BatchDeleteCounts; + export interface CatalogSearch { /** - * One entry per item, **in request order** — position is what maps an outcome back to its - * source row. - * - */ - results: /** - * What one delete item did, and anything worth knowing about it. - * - * The same six properties as a batch upsert entry, and it carries nothing else. - * - */ - BatchDeleteResultEntry[]; - } - /** - * What one delete item did, and anything worth knowing about it. - * - * The same six properties as a batch upsert entry, and it carries nothing else. - * - */ - export interface BatchDeleteResultEntry { - outcome: /** - * What one delete item did. - * - * - `deleted`: the variant, or the one version the item named, is gone. - * - `skipped`: the item addressed nothing — **the variant or the version**, never the entity. An - * entity that cannot answer the item is an `error` carrying `ENTITY_NOT_FOUND`, - * `ENTITY_TYPE_MISMATCH` or `ENTITY_NOT_CONDITIONAL`. - * - `error`: this item alone failed, and the entry's `error` says why. - * + * The query to perform using lucene query syntax. */ - BatchDeleteOutcome; + q: string; /** - * The entity this item removed from, echoed from the item — present whatever happened. - * example: - * price-sp26d1yo + * The sort expression to sort the results. */ - entity_id: string; + sort?: string; /** - * The variant this item removed, or whose version it removed. Present wherever it is known: - * always for an item that named one, and for an item addressing a condition tuple only once - * that tuple resolved. **A `skipped` entry for a tuple no variant pins therefore names no - * variant.** - * - * example: - * var-46045 + * The index from which to query, used for pagination purposes. Defaults to 0 */ - variant_id?: string; + from?: number; /** - * The version this item removed, canonicalized to millisecond-precision UTC. Absent where - * the item removed the whole variant, which is what distinguishes the two deletes this one - * endpoint performs. - * - * example: - * 2027-01-01T00:00:00.000Z + * The max size of the response, defaults to 2000. */ - valid_from?: string; + size?: number; /** - * Things worth knowing that did not stop this item's delete — chiefly which reads the - * removal moved: `ACTIVE_VERSION_CHANGED` where what resolves now changed, and - * `SUPERSEDED_VERSION_WRITTEN` where a past-dated read did. Always present and possibly - * empty, on every outcome, as batch upsert's is. - * + * When true, enables entity hydration to resolve nested $relation references in-place. */ - warnings: /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. + hydrate?: boolean; + fields?: /** + * List of entity fields to include or exclude from the results. * + * example: + * [ + * "!_files", + * "!**.versions" + * ] */ - WriteWarning[]; + CatalogFieldsParam; + availability?: /* Availability filters dimensions */ AvailabilityFilters; + } + /** + * The query result payload + * example: + * { + * "hits": 2, + * "results": [ + * { + * "schema": "product", + * "description": "product a" + * }, + * { + * "schema": "price", + * "unit_amount_decimal": "124.342343434" + * } + * ] + * } + */ + export interface CatalogSearchResult { /** - * Why this item failed, present only with `outcome: error`. The same typed shape a - * single-item delete is refused with. - * - * `LAST_VERSION_UNDELETABLE` is the refusal specific to this endpoint's dated form; - * `VARIANT_UNPINNED` is an item that addresses no variant — no `variant_id`, no - * `default`, and no or empty `conditions`; `ENTITY_NOT_FOUND`, `ENTITY_TYPE_MISMATCH` and - * `ENTITY_NOT_CONDITIONAL` are per item, since each item names its own entity; - * `WRITE_CONFLICT` is transient contention. - * A missing variant or version is not here at all — that is `skipped`. - * - */ - error?: /** - * Why this item failed, present only with `outcome: error`. The same typed shape a - * single-item delete is refused with. - * - * `LAST_VERSION_UNDELETABLE` is the refusal specific to this endpoint's dated form; - * `VARIANT_UNPINNED` is an item that addresses no variant — no `variant_id`, no - * `default`, and no or empty `conditions`; `ENTITY_NOT_FOUND`, `ENTITY_TYPE_MISMATCH` and - * `ENTITY_NOT_CONDITIONAL` are per item, since each item names its own entity; - * `WRITE_CONFLICT` is transient contention. - * A missing variant or version is not here at all — that is `skipped`. - * + * The number of results returned. */ - { - code: "SCHEMA_NOT_FOUND"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_NOT_FOUND"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_TYPE_MISMATCH"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - /** - * The entity type that id belongs to. Where it is a conditional entity type, it - * is the slug to send instead. - * - * example: - * product - */ - actual_schema: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_NOT_CONDITIONAL"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_NOT_FOUND"; - details: { - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "VERSION_NOT_FOUND"; - details: { - /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the request addressed, by the instant it takes effect from. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "NO_MATCHES"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the resolve was scoped to. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "NO_ACTIVE_VERSION"; - details: { - /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The instant a version in effect was asked for at. - * example: - * 2026-06-01T00:00:00.000Z - */ - as_of: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "AMBIGUOUS_RESOLUTION"; - details: { - /** - * Every variant that applied, each with the conditions it pins — which is what - * makes the overlap actionable: two variants both apply because their pins do - * not distinguish the context they were both asked about. - * - * Bounded by the same cap `TOO_MANY_MATCHES` reports, which is checked first, - * so this list is never longer than one response may carry. - * - */ - candidates: [ - { - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }, - { - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }, - ...{ - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }[] - ]; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "TUPLE_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The variant already holding the tuple, where the write read it back. - * - * example: - * var-50667 - */ - conflicting_variant_id?: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "VERSION_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The instant already claimed by a version of that variant. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "CONDITION_UNDEFINED"; - details: { - /** - * The condition named by the request and absent from the schema. - * example: - * postal_code - */ - condition_name: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "OPERATOR_UNSUPPORTED"; - details: { - /** - * example: - * postal_code - */ - condition_name: string; - /** - * The type the schema declares that condition with, which is what decides the - * operators it accepts. - * - * example: - * location - */ - condition_type: string; - /** - * The operator the context or filter asked for. - * example: - * between - */ - operator: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "CONTEXT_FORMAT_INVALID"; - details: { - /** - * example: - * postal_code - */ - condition_name: string; - /** - * What a value for that condition has to be, in prose. - * example: - * a postal code - */ - expected: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "CONDITION_VALUE_INVALID"; - details: { - /** - * example: - * segment - */ - condition_name: string; - /** - * The value the write pinned, as it arrived. Declared without a type: the - * vocabulary holds strings, so anything else is out of it by definition and is - * reported as sent. - * - * example: - * industrial - */ - value: any; - /** - * The vocabulary *as enforced* — after the entries this deploy cannot read have - * been dropped, so a tenant whose `options` holds a title-only entry is told - * what the API actually checked against rather than what they believe they - * wrote. Empty when the condition declares no vocabulary at all, which is - * itself the reason the pin was refused; the message says which of the two - * (unconfigured, or unreadable) applies. - * - * example: - * [ - * "private", - * "commercial" - * ] - */ - options: string[]; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "TOO_MANY_MATCHES"; - details: { - /** - * The most variants one resolve may compose. - * example: - * 100 - */ - limit: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "WRITE_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the write addressed, where one was addressed. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from?: string; - /** - * The revision the write required the stored version to still be at. - * example: - * 3 - */ - expected_revision?: number; - /** - * The revision the version is actually at, where the failed write read it back. - * Absent when it could not be. - * - * example: - * 4 - */ - current_revision?: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "OFFSET_WINDOW_EXCEEDED"; - details: { - /** - * The offset the request asked for. - * example: - * 24990 - */ - from: number; - /** - * The page size the request asked for, after clamping. Present because the two - * together are what exceeded the window — an offset inside it can still be - * refused for the page it would have to read. - * - * example: - * 25 - */ - size: number; - /** - * The last row this deploy's index will serve from an offset. Read it to size a - * page control, never to decide when to switch to the cursor — a caller can page - * on with `next` from any page. - * - * example: - * 25000 - */ - window: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "CURSOR_INVALID"; - details: { - /** - * Which check the cursor failed, in prose. - * example: - * The cursor was issued for a different sort order - */ - reason: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_LIMIT_REACHED"; - details: { - /** - * Variants this entity already holds. - * example: - * 5000 - */ - variant_count: number; - /** - * Variants this entity may hold. Configurable per deploy, the same value for - * every organization on it. - * - * example: - * 5000 - */ - cap: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "PIN_FORMAT_INVALID"; - details: { - /** - * example: - * valid_period - */ - condition_name: string; - /** - * The type the schema declares that condition with, which is what decides the - * values it accepts. - * - * example: - * daterange - */ - condition_type: string; - /** - * What a pin for that condition has to be, in prose — the same field - * `CONTEXT_FORMAT_INVALID` carries, worded for the write side. It says what - * `condition_type` cannot: a `location` of format `zipcode` wants a postal code - * and one of format `zipcode_town` wants an object carrying both, and the type - * is `location` either way. - * - * example: - * an object carrying a from and an until date, either may be open - */ - expected: string; - /** - * The value the write pinned, as it arrived. Declared without a type, since - * what makes it invalid is that it is not of the condition's type. - * - * example: - * 2027-01-01/2027-12-31 - */ - value: any; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_UNPINNED"; - details: { - /** - * The conditional entity the item addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - code: "LAST_VERSION_UNDELETABLE"; - details: { - /** - * The variant whose last version the delete addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the delete addressed, by the instant it takes effect from. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[]; - } | { - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - error?: /** - * The `error` field of an error response: the message, or — where the request itself failed - * validation before any handler ran — the validation errors themselves, which those 400s put - * here in place of a string. - * - * A conditional-pricing operation answers a body its schema rejects with the list, and - * everything else it refuses with the message. - * - */ - ReportedError; - }; - } - /** - * A batch of variant and version deletes under one schema, each item naming the entity it - * removes from. - * - */ - export interface BatchDeleteVariantsRequest { - /** - * An opaque string the caller uses to tie this response to the file and cycle that produced - * it. Echoed back verbatim, only when it was sent, and never interpreted. - * - * example: - * postal-code-cleanup-2026-09 - */ - correlation_id?: string; - /** - * The deletes to apply, in the order they should apply where two of them address the same - * variant — which is decided after every condition tuple has been resolved to a variant id, - * so the order holds across the two addressing forms. At most 100 per call. - * - */ - items: [ - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem?, - /** - * One delete: the variant, addressed by id or by the condition tuple it pins, and optionally - * the one version of it to remove. - * - * Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches - * neither branch and is an envelope `400`, since the request validator rejects the body before - * any item runs. - * - */ - BatchDeleteItem? - ]; - } - /** - * How many items reached each outcome. Keyed by exactly the values of `BatchUpsertOutcome`, all - * of them present, so a logger reads a count without `?? 0`. - * - * **They sum to the length of `results`.** There is no `total`. - * - */ - export interface BatchUpsertCounts { - /** - * example: - * 1 - */ - variant_created: number; - /** - * example: - * 1 - */ - version_created: number; - /** - * example: - * 1 - */ - updated: number; - /** - * example: - * 1 - */ - skipped: number; - /** - * example: - * 1 - */ - error: number; - } - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - export interface BatchUpsertItem { - /** - * The conditional entity this item writes to. On the item rather than in the path, so one - * call can refresh a whole tariff hierarchy — a composite price and its components - * together. - * - * example: - * price-sp26d1yo - */ - entity_id: string; - conditions?: /** - * The situation this variant applies to: a flat map keyed by condition name, as the entity's - * schema declares them. A condition left out is a wildcard — the variant applies whatever the - * context says for it, which is what makes adding a condition to a schema non-breaking for the - * variants that already exist. - * - * Exact values only. A predicate is a read-side thing — a resolve context or a listing's - * condition filter — and is never stored: what a variant applies to is one situation, not a - * range of them. - * - * Values are typed by their condition and stored canonicalized for that type: a `date` becomes - * millisecond-precision UTC, a `daterange` an object carrying `from` and `until` where an empty - * string is an open end, a `location` of format `zipcode` the postal code itself and one of - * format `zipcode_town` an object carrying both. A `select` value must be a string, and must - * be one the condition's `options` declare, which is always a closed vocabulary. - * - * `default`, and any name beginning with `_`, are reserved for the server and cannot be pinned - * here. Whether a variant is the entity's fallback is set through the request's `default` flag. - * - * example: - * { - * "postal_code": "46045" - * } - */ - PinnedConditions; - /** - * Mark this variant as the entity's fallback, exactly as a create does: a property of the - * variant, never an entry in `conditions`. An item that pins nothing and is not the default - * is `VARIANT_UNPINNED` — the empty postal-code column in a source file. - * - */ - default?: boolean; - /** - * When the version this item writes takes effect. Omitted, it is a current-state, - * last-write-wins write with no `skipped` detection. - * - * An RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time - * (`2026-01-01T00:00:00Z`), to at most millisecond precision. - * - * A past instant is written like any other and answered with the timeline warnings on this - * item, so an importer stamping one `valid_from` across a batch sees them on every item. - * - * example: - * 2027-01-01T00:00:00Z - */ - valid_from?: string; - values: /** - * The attribute values this version overrides on the base entity, keyed by attribute name. - * - * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. - * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. - * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. - * - * example: - * { - * "unit_amount": 2499, - * "unit_amount_decimal": "24.99" - * } - */ - VariantValues; - } - /** - * What one upsert item did, derived from what was stored rather than from a mode the caller - * declared. - * - * - `variant_created`: the condition tuple was unknown, so a variant and its first version were - * created. The entry's `variant_id` is the id an order or contract pins. - * - `version_created`: the tuple was known and had no version at the item's `valid_from`, so - * one was appended. The ordinary monthly-refresh case, and a separate value from - * `variant_created` so an importer's counts can tell "new postal codes appeared" from - * "existing variants got their scheduled adjustment". - * - `updated`: a version existed at that exact instant and was written in place. - * - `skipped`: reserved for a write whose values are identical to what is stored, so re-running - * an unchanged import reads as a no-op. An item without `valid_from` has no `skipped` - * detection at all. - * - `error`: this item alone failed, and the entry's `error` says why. - * - */ - export type BatchUpsertOutcome = "variant_created" | "version_created" | "updated" | "skipped" | "error"; - /** - * What a batch upsert did: one entry per item, in request order, and a count per outcome. - * - */ - export interface BatchUpsertResult { - /** - * The `correlation_id` the request carried, echoed only when it was sent. - * example: - * tariff-refresh-2027-01 - */ - correlation_id?: string; - counts: /** - * How many items reached each outcome. Keyed by exactly the values of `BatchUpsertOutcome`, all - * of them present, so a logger reads a count without `?? 0`. - * - * **They sum to the length of `results`.** There is no `total`. - * - */ - BatchUpsertCounts; - /** - * One entry per item, **in request order** — position is what maps an outcome back to its - * source row, and no entry carries an index of its own. - * - */ - results: /** - * What one upsert item did, and anything worth knowing about it. - * - * **It carries nothing else.** Position in `results` is the contract, so no entry carries an - * index; nothing the caller sent is echoed back beyond `entity_id`; and there is no `_revision` - * — an editing screen re-reads the version it is about to write through its own `GET`. - * - */ - BatchUpsertResultEntry[]; - } - /** - * What one upsert item did, and anything worth knowing about it. - * - * **It carries nothing else.** Position in `results` is the contract, so no entry carries an - * index; nothing the caller sent is echoed back beyond `entity_id`; and there is no `_revision` - * — an editing screen re-reads the version it is about to write through its own `GET`. - * - */ - export interface BatchUpsertResultEntry { - outcome: /** - * What one upsert item did, derived from what was stored rather than from a mode the caller - * declared. - * - * - `variant_created`: the condition tuple was unknown, so a variant and its first version were - * created. The entry's `variant_id` is the id an order or contract pins. - * - `version_created`: the tuple was known and had no version at the item's `valid_from`, so - * one was appended. The ordinary monthly-refresh case, and a separate value from - * `variant_created` so an importer's counts can tell "new postal codes appeared" from - * "existing variants got their scheduled adjustment". - * - `updated`: a version existed at that exact instant and was written in place. - * - `skipped`: reserved for a write whose values are identical to what is stored, so re-running - * an unchanged import reads as a no-op. An item without `valid_from` has no `skipped` - * detection at all. - * - `error`: this item alone failed, and the entry's `error` says why. - * - */ - BatchUpsertOutcome; - /** - * The entity this item wrote to, echoed from the item — present whatever happened. - * example: - * price-sp26d1yo - */ - entity_id: string; - /** - * The variant this item created or wrote to. Present on every outcome but `error`: for a - * `variant_created` item it is the id an importer needs to pin, and for the rest it is the - * variant the item's condition tuple resolved to. - * - * example: - * var-46045 - */ - variant_id?: string; - /** - * The version this item wrote, canonicalized to millisecond-precision UTC. Present on every - * outcome but `error`, including for an item that sent none — the server stamps the instant - * a current-state write takes effect, and this is where the caller reads it back. - * - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from?: string; - /** - * Things worth knowing that did not stop this item's write. **Always present, and possibly - * empty** — on a `skipped` and an `error` entry too — so a client reads its length rather - * than branching on its absence, as every other write in this document already asks. - * `skipped` describes what storage did; a warning describes what the request asked for, and - * the two are not the same fact. - * - * Every warning fires per item, with no batch-level suppression: - * `VARIANT_COUNT_APPROACHING_CAP` included, even where an entity past its threshold - * produces it on all 100 entries. A logger dedupes by code. - * - */ - warnings: /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. - * - */ - WriteWarning[]; - /** - * Why this item failed, present only with `outcome: error`. The same typed shape a - * single-item write is refused with, so a per-item failure and a single-item failure are - * read by one client type. - * - * An item carries the codes variant create raises — `VARIANT_UNPINNED`, - * `CONDITION_UNDEFINED`, `CONDITION_VALUE_INVALID`, `PIN_FORMAT_INVALID`, - * `VARIANT_LIMIT_REACHED`, `WRITE_CONFLICT` for transient contention, and the three the - * addressed entity answers with: `ENTITY_NOT_FOUND`, `ENTITY_TYPE_MISMATCH` and - * `ENTITY_NOT_CONDITIONAL` — less two. Those three are per item because each item names its - * own entity, while `SCHEMA_NOT_FOUND` is the envelope's, since the slug is in the path. `TUPLE_CONFLICT` never appears on an item, and neither does `VERSION_CONFLICT`: a - * guard failure on a brand-new tuple is re-read and re-derived, and an existing - * `valid_from` is a replacement. - * - */ - error?: /** - * Why this item failed, present only with `outcome: error`. The same typed shape a - * single-item write is refused with, so a per-item failure and a single-item failure are - * read by one client type. - * - * An item carries the codes variant create raises — `VARIANT_UNPINNED`, - * `CONDITION_UNDEFINED`, `CONDITION_VALUE_INVALID`, `PIN_FORMAT_INVALID`, - * `VARIANT_LIMIT_REACHED`, `WRITE_CONFLICT` for transient contention, and the three the - * addressed entity answers with: `ENTITY_NOT_FOUND`, `ENTITY_TYPE_MISMATCH` and - * `ENTITY_NOT_CONDITIONAL` — less two. Those three are per item because each item names its - * own entity, while `SCHEMA_NOT_FOUND` is the envelope's, since the slug is in the path. `TUPLE_CONFLICT` never appears on an item, and neither does `VERSION_CONFLICT`: a - * guard failure on a brand-new tuple is re-read and re-derived, and an existing - * `valid_from` is a replacement. - * - */ - { - code: "SCHEMA_NOT_FOUND"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_NOT_FOUND"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_TYPE_MISMATCH"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - /** - * The entity type that id belongs to. Where it is a conditional entity type, it - * is the slug to send instead. - * - * example: - * product - */ - actual_schema: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_NOT_CONDITIONAL"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_NOT_FOUND"; - details: { - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VERSION_NOT_FOUND"; - details: { - /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the request addressed, by the instant it takes effect from. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "NO_MATCHES"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the resolve was scoped to. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "NO_ACTIVE_VERSION"; - details: { - /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The instant a version in effect was asked for at. - * example: - * 2026-06-01T00:00:00.000Z - */ - as_of: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "AMBIGUOUS_RESOLUTION"; - details: { - /** - * Every variant that applied, each with the conditions it pins — which is what - * makes the overlap actionable: two variants both apply because their pins do - * not distinguish the context they were both asked about. - * - * Bounded by the same cap `TOO_MANY_MATCHES` reports, which is checked first, - * so this list is never longer than one response may carry. - * - */ - candidates: [ - { - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }, - { - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }, - ...{ - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }[] - ]; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "TUPLE_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The variant already holding the tuple, where the write read it back. - * - * example: - * var-50667 - */ - conflicting_variant_id?: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VERSION_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The instant already claimed by a version of that variant. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CONDITION_UNDEFINED"; - details: { - /** - * The condition named by the request and absent from the schema. - * example: - * postal_code - */ - condition_name: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "OPERATOR_UNSUPPORTED"; - details: { - /** - * example: - * postal_code - */ - condition_name: string; - /** - * The type the schema declares that condition with, which is what decides the - * operators it accepts. - * - * example: - * location - */ - condition_type: string; - /** - * The operator the context or filter asked for. - * example: - * between - */ - operator: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CONTEXT_FORMAT_INVALID"; - details: { - /** - * example: - * postal_code - */ - condition_name: string; - /** - * What a value for that condition has to be, in prose. - * example: - * a postal code - */ - expected: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CONDITION_VALUE_INVALID"; - details: { - /** - * example: - * segment - */ - condition_name: string; - /** - * The value the write pinned, as it arrived. Declared without a type: the - * vocabulary holds strings, so anything else is out of it by definition and is - * reported as sent. - * - * example: - * industrial - */ - value: any; - /** - * The vocabulary *as enforced* — after the entries this deploy cannot read have - * been dropped, so a tenant whose `options` holds a title-only entry is told - * what the API actually checked against rather than what they believe they - * wrote. Empty when the condition declares no vocabulary at all, which is - * itself the reason the pin was refused; the message says which of the two - * (unconfigured, or unreadable) applies. - * - * example: - * [ - * "private", - * "commercial" - * ] - */ - options: string[]; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "TOO_MANY_MATCHES"; - details: { - /** - * The most variants one resolve may compose. - * example: - * 100 - */ - limit: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "WRITE_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the write addressed, where one was addressed. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from?: string; - /** - * The revision the write required the stored version to still be at. - * example: - * 3 - */ - expected_revision?: number; - /** - * The revision the version is actually at, where the failed write read it back. - * Absent when it could not be. - * - * example: - * 4 - */ - current_revision?: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "OFFSET_WINDOW_EXCEEDED"; - details: { - /** - * The offset the request asked for. - * example: - * 24990 - */ - from: number; - /** - * The page size the request asked for, after clamping. Present because the two - * together are what exceeded the window — an offset inside it can still be - * refused for the page it would have to read. - * - * example: - * 25 - */ - size: number; - /** - * The last row this deploy's index will serve from an offset. Read it to size a - * page control, never to decide when to switch to the cursor — a caller can page - * on with `next` from any page. - * - * example: - * 25000 - */ - window: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CURSOR_INVALID"; - details: { - /** - * Which check the cursor failed, in prose. - * example: - * The cursor was issued for a different sort order - */ - reason: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_LIMIT_REACHED"; - details: { - /** - * Variants this entity already holds. - * example: - * 5000 - */ - variant_count: number; - /** - * Variants this entity may hold. Configurable per deploy, the same value for - * every organization on it. - * - * example: - * 5000 - */ - cap: number; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "PIN_FORMAT_INVALID"; - details: { - /** - * example: - * valid_period - */ - condition_name: string; - /** - * The type the schema declares that condition with, which is what decides the - * values it accepts. - * - * example: - * daterange - */ - condition_type: string; - /** - * What a pin for that condition has to be, in prose — the same field - * `CONTEXT_FORMAT_INVALID` carries, worded for the write side. It says what - * `condition_type` cannot: a `location` of format `zipcode` wants a postal code - * and one of format `zipcode_town` wants an object carrying both, and the type - * is `location` either way. - * - * example: - * an object carrying a from and an until date, either may be open - */ - expected: string; - /** - * The value the write pinned, as it arrived. Declared without a type, since - * what makes it invalid is that it is not of the condition's type. - * - * example: - * 2027-01-01/2027-12-31 - */ - value: any; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_UNPINNED"; - details: { - /** - * The conditional entity the item addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "LAST_VERSION_UNDELETABLE"; - details: { - /** - * The variant whose last version the delete addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the delete addressed, by the instant it takes effect from. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - error?: /** - * The `error` field of an error response: the message, or — where the request itself failed - * validation before any handler ran — the validation errors themselves, which those 400s put - * here in place of a string. - * - * A conditional-pricing operation answers a body its schema rejects with the list, and - * everything else it refuses with the message. - * - */ - ReportedError; - }; - } - /** - * A batch of variant writes under one schema, each item naming the entity it writes to. - * - */ - export interface BatchUpsertVariantsRequest { - /** - * An opaque string the caller uses to tie this response to the file and cycle that produced - * it. Echoed back verbatim, only when it was sent, and never interpreted. - * - * example: - * tariff-refresh-2027-01 - */ - correlation_id?: string; - /** - * The writes to apply, in the order they should apply where two of them address the same - * variant. At most 100 per call — a limit on one request, distinct from the per-entity - * variant cap, which limits stored state. - * - */ - items: [ - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem?, - /** - * One variant write: the entity it belongs to, the situation it applies to, and the values it - * carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on - * a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the - * variant already holding it. - * - * There is no `variant_id`. An upsert creates variants that have no id yet. - * - */ - BatchUpsertItem? - ]; - } - export type BillingPeriod = "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly"; - /** - * A valid cart payload from a client. - */ - export interface CartDto { - metadata?: /* A set of key-value pairs used to store meta data information about an entity. */ MetaData; - customer?: Customer; - billing_address?: Address; - delivery_address?: Address; - /** - * type of source, e.g. journey or manual - * example: - * journey - */ - source_type?: string; - /** - * identifier for source e.g. journey ID - * example: - * ce99875f-fba9-4fe2-a8f9-afaf52059051 - */ - source_id?: string; - source?: /* The order generation source */ OrderSource; - additional_addresses?: Address[]; - payment_method?: /** - * A PaymentMethod represent your customer's payment instruments. - * - */ - PaymentMethod; - line_items: /* A valid set of product prices, quantities, (discounts) and taxes from a client. */ PriceItemsDto; - /** - * An array of file IDs, already upload into the File API, that are related with this cart - */ - files?: string[]; - status?: /** - * - * | status | description | - * |-------------|-------| - * | `draft` | ​​Starting state for all orders, at this point we can still edit the order | - * | `quote` | The order is in a quoting phase, bound to an expiration date | - * | `placed` | The order has been paid and can now be fulfilled (shipped, delivered, complete) or canceled | - * | `cancelled` | The order has been cancelled | - * | `completed` | The order is now closed and finalized | - * - */ - OrderStatus; - tags?: string[]; - journey_data?: { - [name: string]: any; - }; - consents?: { - [name: string]: any; - }; - } - /** - * A detail associated with a specific cashback. - */ - export interface CashbackAmount { - /** - * The name of the cashback. - */ - cashback_name?: string; - cashback_period: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; - /** - * The sum of all cashbacks for a specific cashback period - */ - amount_total: number; - } - export interface CashbackAmounts { - /** - * The cashback amount. - */ - cashback_amount?: number; - /** - * The cashback amount as a string with all the decimal places. - */ - cashback_amount_decimal?: string; - cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; - /** - * Total amount after cashback is applied. - */ - after_cashback_amount_total?: number; - /** - * Total amount after cashback is applied as a string with all the decimal places. - */ - after_cashback_amount_total_decimal?: string; - } - /** - * The cashback period, for now it's limited to either 0 months or 12 months - */ - export type CashbackPeriod = "0" | "12"; - /** - * List of entity fields to include or exclude from the results. - * - * example: - * [ - * "!_files", - * "!**.versions" - * ] - */ - export type CatalogFieldsParam = string[]; - /** - * A catalog search payload - * example: - * { - * "q": "_id:1233432 OR _id:123432454 OR _id:23445433", - * "sort": "description ASC", - * "from": 0, - * "size": 200 - * } - */ - export interface CatalogSearch { - /** - * The query to perform using lucene query syntax. - */ - q: string; - /** - * The sort expression to sort the results. - */ - sort?: string; - /** - * The index from which to query, used for pagination purposes. Defaults to 0 - */ - from?: number; - /** - * The max size of the response, defaults to 2000. - */ - size?: number; - /** - * When true, enables entity hydration to resolve nested $relation references in-place. - */ - hydrate?: boolean; - fields?: /** - * List of entity fields to include or exclude from the results. - * - * example: - * [ - * "!_files", - * "!**.versions" - * ] - */ - CatalogFieldsParam; - availability?: /* Availability filters dimensions */ AvailabilityFilters; - } - /** - * The query result payload - * example: - * { - * "hits": 2, - * "results": [ - * { - * "schema": "product", - * "description": "product a" - * }, - * { - * "schema": "price", - * "unit_amount_decimal": "124.342343434" - * } - * ] - * } - */ - export interface CatalogSearchResult { - /** - * The number of results returned. - */ - hits?: number; - results?: (/** - * The product entity - * example: - * { - * "type": "product", - * "_schema": "product", - * "_title": "Solar Panel with Battery Storage", - * "name": "Solar Panel with Battery Storage", - * "code": "SOLAR-BATT", - * "active": true, - * "description": "Solar Panel with battery solution, optimized for max efficiency. ", - * "feature": [ - * { - * "_tags": [], - * "feature": "Eco-Panels" - * }, - * { - * "_tags": [], - * "feature": "Remote Management Platform" - * }, - * { - * "_tags": [], - * "feature": "Battery Remote Control" - * }, - * { - * "_tags": [], - * "feature": "Mobile App" - * } - * ], - * "cross_sellable_products": { - * "$relation": [ - * { - * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", - * "_schema": "product", - * "_tags": [] - * }, - * { - * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", - * "_tags": [] - * } - * ] - * }, - * "product_images": { - * "$relation": [ - * { - * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" - * }, - * { - * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" - * } - * ] - * }, - * "product_downloads": { - * "$relation": [ - * { - * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" - * } - * ] - * }, - * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", - * "_org": "728", - * "_created_at": "2022-06-03T15: 52: 27.512Z", - * "_updated_at": "2022-06-03T16: 05: 15.029Z", - * "price_options": { - * "$relation": [ - * { - * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "_tags": [] - * }, - * { - * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", - * "_tags": [] - * } - * ] - * } - * } - */ - Product | /** - * The price entity schema for simple pricing - * example: - * { - * "unit_amount": 100000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "1000", - * "sales_tax": "standard", - * "is_tax_inclusive": true, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "_schema": "price", - * "_title": "Solar Panel Module", - * "description": "Solar Panel Module", - * "active": true, - * "_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "_org": "728", - * "_created_at": "2022-06-03T16:04:10.369Z", - * "_updated_at": "2022-06-03T16:04:10.369Z", - * "pricing_model": "per_unit", - * "is_composite_price": false - * } - */ - Price | /** - * The coupon entity - * example: - * { - * "_id": "123e4567-e89b-12d3-a456-426614174000", - * "_schema": "coupon", - * "_org": "org_12345", - * "_created_at": "2024-01-15T10:00:00.000Z", - * "_updated_at": "2024-01-20T12:00:00.000Z", - * "_title": "Sample Coupon", - * "name": "Sample Coupon", - * "type": "fixed", - * "fixed_value": 555, - * "fixed_value_currency": "USD", - * "fixed_value_decimal": "5.55", - * "active": true, - * "category": "cashback", - * "prices": { - * "$relation": [ - * { - * "entity_id": "abc12345-def6-7890-gh12-ijklmnopqrst", - * "_tags": [ - * "discount", - * "special" - * ], - * "_schema": "price" - * } - * ] - * } - * } - */ - Coupon)[]; - } - /** - * The cart checkout request payload - */ - export interface CheckoutCart { - cart?: string | /* A valid cart payload from a client. */ CartDto; - redeemed_promos?: RedeemedPromo[]; - mode?: /* The checkout mode for the cart checkout. */ CheckoutMode; - } - /** - * The cart checkout result - */ - export interface CheckoutCartResult { - order?: /** - * The order entity - * example: - * { - * "order_number": "OR 2022/742701", - * "status": "quote", - * "source": { - * "title": "manual", - * "href": null - * }, - * "source_type": "manual", - * "_schema": "order", - * "_title": "OR 2022/742701", - * "expires_at": "2022-06-30T16:17:00.000Z", - * "line_items": [ - * { - * "price_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "product_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "taxes": [ - * { - * "tax": { - * "_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc", - * "rate": 19, - * "_schema": "tax", - * "_org": "728", - * "_created_at": "2021-09-24T15:06:13.859Z", - * "_updated_at": "2022-04-04T17:36:15.273Z", - * "_title": "Tax Standard", - * "type": "VAT", - * "active": true, - * "region": "DE", - * "description": "Standard" - * }, - * "amount": 255462 - * } - * ], - * "_price": { - * "_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "unit_amount": 100000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "1000", - * "sales_tax": "standard", - * "is_tax_inclusive": true, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "_schema": "price", - * "_title": "Solar Panel Module", - * "description": "Solar Panel Module", - * "active": true, - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "tax": { - * "$relation": [ - * { - * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" - * } - * ] - * }, - * "_org": "728", - * "_created_at": "2022-06-03T16:04:10.369Z", - * "_updated_at": "2022-06-03T16:04:10.369Z" - * }, - * "_product": { - * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", - * "type": "product", - * "_schema": "product", - * "_title": "Solar Panel with Battery Storage", - * "name": "Solar Panel with Battery Storage", - * "code": "SOLAR-BATT", - * "active": true, - * "description": "Solar Panel with battery solution, optimized for max efficiency. ", - * "feature": [ - * { - * "_tags": [], - * "feature": "Eco-Panels" - * }, - * { - * "_tags": [], - * "feature": "Remote Management Platform" - * }, - * { - * "_tags": [], - * "feature": "Battery Remote Control" - * }, - * { - * "_tags": [], - * "feature": "Mobile App" - * } - * ], - * "cross_sellable_products": { - * "$relation": [ - * { - * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", - * "_schema": "product", - * "_tags": [] - * }, - * { - * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", - * "_tags": [] - * } - * ] - * }, - * "product_images": { - * "$relation": [ - * { - * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" - * }, - * { - * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" - * } - * ] - * }, - * "product_downloads": { - * "$relation": [ - * { - * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" - * } - * ] - * }, - * "_org": "728", - * "_created_at": "2022-06-03T15:52:27.512Z", - * "_updated_at": "2022-06-03T16:05:15.029Z", - * "price_options": { - * "$relation": [ - * { - * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "_tags": [] - * }, - * { - * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", - * "_tags": [] - * } - * ] - * } - * }, - * "quantity": 16, - * "currency": "EUR", - * "description": "Solar Panel Module", - * "unit_amount": 100000, - * "unit_amount_net": 84034, - * "amount_subtotal": 1344538, - * "amount_total": 1600000 - * }, - * { - * "price_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", - * "product_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "taxes": [ - * { - * "tax": { - * "_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc", - * "rate": 19, - * "_schema": "tax", - * "_org": "728", - * "_created_at": "2021-09-24T15:06:13.859Z", - * "_updated_at": "2022-04-04T17:36:15.273Z", - * "_title": "Tax Standard", - * "type": "VAT", - * "active": true, - * "region": "DE", - * "description": "Standard" - * }, - * "amount": 31933 - * } - * ], - * "_price": { - * "_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", - * "unit_amount": 50000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "500", - * "sales_tax": "standard", - * "is_tax_inclusive": true, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "_schema": "price", - * "_title": "Battery Module 500amps", - * "description": "Battery Module 500amps", - * "active": true, - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "tax": { - * "$relation": [ - * { - * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" - * } - * ] - * }, - * "_org": "728", - * "_created_at": "2022-06-03T16:05:04.391Z", - * "_updated_at": "2022-06-03T16:05:04.391Z" - * }, - * "_product": { - * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", - * "type": "product", - * "_schema": "product", - * "_title": "Solar Panel with Battery Storage", - * "name": "Solar Panel with Battery Storage", - * "code": "SOLAR-BATT", - * "active": true, - * "description": "Solar Panel with battery solution, optimized for max efficiency. ", - * "feature": [ - * { - * "_tags": [], - * "feature": "Eco-Panels" - * }, - * { - * "_tags": [], - * "feature": "Remote Management Platform" - * }, - * { - * "_tags": [], - * "feature": "Battery Remote Control" - * }, - * { - * "_tags": [], - * "feature": "Mobile App" - * } - * ], - * "cross_sellable_products": { - * "$relation": [ - * { - * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", - * "_schema": "product", - * "_tags": [] - * }, - * { - * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", - * "_tags": [] - * } - * ] - * }, - * "product_images": { - * "$relation": [ - * { - * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" - * }, - * { - * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" - * } - * ] - * }, - * "product_downloads": { - * "$relation": [ - * { - * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" - * } - * ] - * }, - * "_org": "728", - * "_created_at": "2022-06-03T15:52:27.512Z", - * "_updated_at": "2022-06-03T16:05:15.029Z", - * "price_options": { - * "$relation": [ - * { - * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "_tags": [] - * }, - * { - * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", - * "_tags": [] - * } - * ] - * } - * }, - * "quantity": 4, - * "currency": "EUR", - * "description": "Battery Module 500amps", - * "unit_amount": 50000, - * "unit_amount_net": 42017, - * "amount_subtotal": 168067, - * "amount_total": 200000 - * }, - * { - * "price_id": "d88a8763-3e3d-4fc7-a7a5-2bc9117148bf", - * "product_id": "065d6618-cc59-45f4-8e3a-700edf6813c3", - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "_price": { - * "_id": "d88a8763-3e3d-4fc7-a7a5-2bc9117148bf", - * "unit_amount": 12055, - * "type": "recurring", - * "billing_period": "monthly", - * "billing_duration_amount": 8, - * "billing_duration_unit": "years", - * "notice_time_amount": 3, - * "notice_time_unit": "months", - * "termination_time_amount": 2, - * "termination_time_unit": "months", - * "renewal_duration_amount": 1, - * "renewal_duration_unit": "years", - * "active": true, - * "sales_tax": "reduced", - * "is_tax_inclusive": true, - * "description": "Monthly", - * "billing_scheme": "per_unit", - * "_schema": "price", - * "_org": "728", - * "_created_at": "2021-11-10T14:40:27.695Z", - * "_updated_at": "2021-12-14T18:16:33.248Z", - * "_title": "Monthly", - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "120.55456634", - * "pricing_model": "per_unit", - * "is_composite_price": false - * }, - * "_product": { - * "_id": "065d6618-cc59-45f4-8e3a-700edf6813c3", - * "name": "Smartmeter: Schneider Electric PM5000 LCD Energiemessgerät / 3-phasig", - * "code": "1312378123", - * "_tags": [ - * "wallbox", - * "review demo", - * "1" - * ], - * "categories": [ - * "Power" - * ], - * "type": "product", - * "active": true, - * "feature": [ - * { - * "_tags": [], - * "feature": "Bis zu 11 kW Ladeleistung (5x schneller laden)" - * }, - * { - * "_tags": [], - * "feature": "Integrierter MID Zähler für eine kilowattstundengenaue Abrechnung*" - * }, - * { - * "_tags": [], - * "feature": "Konfigurierbare Ladeleistung" - * }, - * { - * "_tags": [], - * "feature": "Zugangskontrolle über RFID-Karten" - * }, - * { - * "_tags": [], - * "feature": "Kommunikation über LAN" - * }, - * { - * "_tags": [], - * "feature": "New feature" - * } - * ], - * "_schema": "product", - * "_org": "728", - * "_created_at": "2021-11-30T11:05:19.484Z", - * "_updated_at": "2022-01-13T09:18:29.944Z", - * "_title": "Smartmeter: Schneider Electric PM5000 LCD Energiemessgerät / 3-phasig", - * "price_options": { - * "$relation": [ - * { - * "entity_id": "5264b089-fc6a-4a91-9a2a-80c673958faa" - * }, - * { - * "entity_id": "d88a8763-3e3d-4fc7-a7a5-2bc9117148bf" - * } - * ] - * }, - * "product_images": { - * "$relation": [ - * { - * "entity_id": "16729e60-c527-44ef-93c9-c68b6acf1224" - * } - * ] - * } - * }, - * "quantity": 1, - * "currency": "EUR", - * "description": "Monthly", - * "unit_amount": 12055, - * "unit_amount_net": 11267, - * "amount_subtotal": 11267, - * "amount_total": 12055, - * "taxes": [ - * { - * "rate": "reduced", - * "amount": 789 - * } - * ] - * }, - * { - * "price_id": "e1ddf75a-d0d1-40b4-a07e-56e292867c88", - * "product_id": "5b9f05b7-f0f8-49c2-8a8d-0f8f923d6382", - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "_price": { - * "_id": "e1ddf75a-d0d1-40b4-a07e-56e292867c88", - * "unit_amount": 9900, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "99", - * "sales_tax": "standard", - * "is_tax_inclusive": true, - * "price_display_in_journeys": "show_price", - * "type": "recurring", - * "billing_period": "yearly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "_schema": "price", - * "_title": "Yearly payment", - * "description": "Yearly payment", - * "active": true, - * "pricing_model": "per_unit", - * "is_composite_price": false, - * "_org": "728", - * "_created_at": "2022-02-07T22:58:39.884Z", - * "_updated_at": "2022-02-07T22:58:39.884Z" - * }, - * "_product": { - * "_id": "5b9f05b7-f0f8-49c2-8a8d-0f8f923d6382", - * "_schema": "product", - * "_title": "Yearly Payment Product", - * "name": "Yearly Payment Product", - * "type": "product", - * "active": true, - * "price_options": { - * "$relation": [ - * { - * "entity_id": "e1ddf75a-d0d1-40b4-a07e-56e292867c88", - * "_tags": [] - * } - * ] - * }, - * "_org": "728", - * "_created_at": "2022-02-07T22:58:44.162Z", - * "_updated_at": "2022-02-08T09:34:08.026Z", - * "description": "Hier steht die Produktbeschreibung die sich auf dem Dokument, was generiert wird, gezogen wird." - * }, - * "quantity": 1, - * "currency": "EUR", - * "description": "Yearly payment", - * "unit_amount": 9900, - * "unit_amount_net": 8319, - * "amount_subtotal": 8319, - * "amount_total": 9900, - * "taxes": [ - * { - * "rate": "standard", - * "amount": 1581 - * } - * ] - * } - * ], - * "amount_subtotal": 1532191, - * "amount_total": 1821955, - * "total_details": { - * "amount_tax": 289764, - * "breakdown": { - * "taxes": [ - * { - * "tax": { - * "_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc", - * "rate": 19, - * "_schema": "tax", - * "_org": "728", - * "_created_at": "2021-09-24T15:06:13.859Z", - * "_updated_at": "2022-04-04T17:36:15.273Z", - * "_title": "Tax Standard", - * "type": "VAT", - * "active": true, - * "region": "DE", - * "description": "Standard" - * }, - * "amount": 287395 - * } - * ], - * "recurrences": [ - * { - * "type": "one_time", - * "amount_subtotal": 1512605, - * "amount_subtotal_decimal": "15126.05", - * "amount_total": 1800000, - * "amount_total_decimal": "18000.00", - * "amount_tax": 287395, - * "amount_tax_decimal": "2873.95" - * }, - * { - * "type": "recurring", - * "billing_period": "monthly", - * "amount_subtotal": 11267, - * "amount_subtotal_decimal": "112.67", - * "amount_total": 12055, - * "amount_total_decimal": "120.55", - * "amount_tax": 789, - * "amount_tax_decimal": "7.89" - * }, - * { - * "type": "recurring", - * "billing_period": "yearly", - * "amount_subtotal": 8319, - * "amount_subtotal_decimal": "83.19", - * "amount_total": 9900, - * "amount_total_decimal": "99.00", - * "amount_tax": 1581, - * "amount_tax_decimal": "15.81" - * } - * ] - * } - * }, - * "currency": "EUR", - * "payment_method": [ - * { - * "type": "IBAN", - * "details": {} - * } - * ], - * "billing_contact": { - * "$relation": [ - * { - * "entity_id": "1834a54e-b68f-4f7f-a98a-fe16f11bc2a5", - * "_tags": [] - * } - * ] - * }, - * "billing_first_name": "Joao", - * "billing_last_name": "Pinho", - * "billing_email": "j.pinho@epilot.cloud", - * "billing_company_name": "epilot cloud", - * "billing_address": [ - * { - * "_tags": [], - * "street": "Im Media Park", - * "street_number": "8a", - * "postal_code": "52000", - * "city": "Cologne", - * "country": "DE", - * "additional_info": "" - * } - * ], - * "delivery_address": [], - * "dates": [ - * { - * "_tags": [ - * "Instalation Date" - * ], - * "dates": "", - * "value": "2022-06-30T16:29:00.000Z" - * } - * ], - * "_id": "4c7c9562-f8f0-4af0-a3a6-6aebc5571a6e", - * "_org": "728", - * "_created_at": "2022-06-03T16:29:46.303Z", - * "_updated_at": "2022-06-03T16:29:46.303Z" - * } - */ - Order; - } - /** - * The checkout mode for the cart checkout. - */ - export type CheckoutMode = "create_order" | "create_invoice" | "create_quote"; - /** - * The composite price entity - * example: - * { - * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_title": "My Composite Price", - * "description": "My Composite Price", - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "is_composite_price": true, - * "price_components": { - * "$relation": [ - * { - * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 1, - * "item": { - * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * }, - * { - * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 2, - * "item": { - * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * } - * ] - * } - * } - */ - export type CompositePrice = /** - * The composite price entity - * example: - * { - * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_title": "My Composite Price", - * "description": "My Composite Price", - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "is_composite_price": true, - * "price_components": { - * "$relation": [ - * { - * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 1, - * "item": { - * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * }, - * { - * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 2, - * "item": { - * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * } - * ] - * } - * } - */ - /** - * The composite price entity - * example: - * { - * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_title": "My Composite Price", - * "description": "My Composite Price", - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "is_composite_price": true, - * "price_components": { - * "$relation": [ - * { - * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 1, - * "item": { - * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * }, - * { - * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 2, - * "item": { - * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * } - * ] - * } - * } - */ - NonHydratedCompositePrice | /** - * The composite price entity - * example: - * { - * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_title": "My Composite Price", - * "description": "My Composite Price", - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "is_composite_price": true, - * "price_components": { - * "$relation": [ - * { - * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 1, - * "item": { - * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * }, - * { - * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 2, - * "item": { - * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * } - * ] - * } - * } - */ - HydratedCompositePrice; - /** - * Represents a composite price input to the pricing library. - * example: - * { - * "amount_subtotal": 10000, - * "amount_total": 10600, - * "currency": "EUR", - * "description": "Annual internet service", - * "price_id": "7e24ff5d-d580-4136-a32f-19191eed039a", - * "product_id": "6241487f-b7fd-428b-ab92-24ee0b37fd84", - * "taxes": [ - * { - * "amount": 600, - * "tax": { - * "active": true, - * "description": "Without Behaviour", - * "rate": 6, - * "region": "DE", - * "type": "VAT", - * "_created_at": "2022-02-07T14:49:08.831Z", - * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", - * "_org": "739224", - * "_schema": "tax", - * "_title": "Tax Without Behaviour", - * "_updated_at": "2022-02-07T14:49:08.831Z" - * } - * } - * ], - * "unit_amount": 10000, - * "unit_amount_net": 10000, - * "pricing_model": "per_unit", - * "_price": { - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "_schema": "price", - * "_title": "Solar Panel Module", - * "description": "Solar Panel Module", - * "active": true, - * "tax": { - * "$relation": [ - * { - * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" - * } - * ] - * }, - * "_id": "7e24ff5d-d580-4136-a32f-19191eed039a", - * "_org": "728", - * "_created_at": "2022-06-03T16:04:10.369Z", - * "_updated_at": "2022-06-03T16:04:10.369Z", - * "pricing_model": "per_unit" - * }, - * "_product": { - * "name": "Cool box", - * "type": "product", - * "_id": "73f857a4-0fbc-4aa6-983f-87c0d6d410a6", - * "_title": "Cool box" - * } - * } - */ - export interface CompositePriceItem { - /** - * Total of all items before (discounts or) taxes are applied. - */ - amount_subtotal?: number; - /** - * Total of all items before (discounts or) taxes are applied, as a string with all the decimal places. - */ - amount_subtotal_decimal?: string; - /** - * Total of all items after (discounts and) taxes are applied. - */ - amount_total?: number; - /** - * Total of all items after (discounts and) taxes are applied, as a string with all the decimal places. - */ - amount_total_decimal?: string; - /** - * The cashback amount. - */ - cashback_amount?: number; - /** - * The cashback amount as a string with all the decimal places. - */ - cashback_amount_decimal?: string; - cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; - /** - * Total amount after cashback is applied. - */ - after_cashback_amount_total?: number; - /** - * Total amount after cashback is applied as a string with all the decimal places. - */ - after_cashback_amount_total_decimal?: string; - /** - * The discount amount. - */ - discount_amount?: number; - /** - * The discount amount as a string with all the decimal places. - */ - discount_amount_decimal?: string; - /** - * The discount percentage, if the applied coupon had a percentage type. - */ - discount_percentage?: number; - /** - * Total amount before discount is applied. - */ - before_discount_amount_total?: number; - /** - * Total amount before discount is applied as a string with all the decimal places. - */ - before_discount_amount_total_decimal?: string; - /** - * Total amount before discount is applied, excluding taxes. - */ - before_discount_amount_subtotal?: number; - /** - * Total amount before discount is applied, excluding taxes, as a string with all the decimal places. - */ - before_discount_amount_subtotal_decimal?: string; - metadata?: /* A set of key-value pairs used to store meta data information about an entity. */ MetaData; - /** - * The quantity of products being purchased. - */ - quantity?: number; - /** - * The id of the product. - */ - product_id?: string; - /** - * The id of the price. - */ - price_id?: string; - /** - * An arbitrary string attached to the price item. Often useful for displaying to users. Defaults to product name. - */ - description?: string; - /** - * The description for the product. - */ - product_description?: string; - /** - * The name for the product. - */ - product_name?: string; - price_mappings?: /** - * example: - * [ - * { - * "price_id": "589B011B-F8D9-4F8E-AD71-BACE4B543C0F", - * "frequency_unit": "weekly", - * "value": 1000.245, - * "name": "avg consumption", - * "metadata": { - * "journey_title": "energy journey", - * "step_name": "avg consumption picker" - * } - * } - * ] - */ - PriceInputMappings; - /** - * Specifies whether the price is considered `inclusive` of taxes or not. - */ - is_tax_inclusive?: boolean; - /** - * The snapshot of the product. + hits?: number; + results?: (/** + * The product entity * example: * { * "type": "product", @@ -8090,565 +1785,1206 @@ declare namespace Components { * "description": "Solar Panel with battery solution, optimized for max efficiency. ", * "feature": [ * { - * "_tags": [], - * "feature": "Eco-Panels" + * "_tags": [], + * "feature": "Eco-Panels" + * }, + * { + * "_tags": [], + * "feature": "Remote Management Platform" + * }, + * { + * "_tags": [], + * "feature": "Battery Remote Control" + * }, + * { + * "_tags": [], + * "feature": "Mobile App" + * } + * ], + * "cross_sellable_products": { + * "$relation": [ + * { + * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", + * "_schema": "product", + * "_tags": [] + * }, + * { + * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", + * "_tags": [] + * } + * ] + * }, + * "product_images": { + * "$relation": [ + * { + * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" + * }, + * { + * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" + * } + * ] + * }, + * "product_downloads": { + * "$relation": [ + * { + * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" + * } + * ] + * }, + * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", + * "_org": "728", + * "_created_at": "2022-06-03T15: 52: 27.512Z", + * "_updated_at": "2022-06-03T16: 05: 15.029Z", + * "price_options": { + * "$relation": [ + * { + * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "_tags": [] + * }, + * { + * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", + * "_tags": [] + * } + * ] + * } + * } + */ + Product | /** + * The price entity schema for simple pricing + * example: + * { + * "unit_amount": 100000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "1000", + * "sales_tax": "standard", + * "is_tax_inclusive": true, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Solar Panel Module", + * "description": "Solar Panel Module", + * "active": true, + * "_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "_org": "728", + * "_created_at": "2022-06-03T16:04:10.369Z", + * "_updated_at": "2022-06-03T16:04:10.369Z", + * "pricing_model": "per_unit", + * "is_composite_price": false + * } + */ + Price | /** + * The coupon entity + * example: + * { + * "_id": "123e4567-e89b-12d3-a456-426614174000", + * "_schema": "coupon", + * "_org": "org_12345", + * "_created_at": "2024-01-15T10:00:00.000Z", + * "_updated_at": "2024-01-20T12:00:00.000Z", + * "_title": "Sample Coupon", + * "name": "Sample Coupon", + * "type": "fixed", + * "fixed_value": 555, + * "fixed_value_currency": "USD", + * "fixed_value_decimal": "5.55", + * "active": true, + * "category": "cashback", + * "prices": { + * "$relation": [ + * { + * "entity_id": "abc12345-def6-7890-gh12-ijklmnopqrst", + * "_tags": [ + * "discount", + * "special" + * ], + * "_schema": "price" + * } + * ] + * } + * } + */ + Coupon)[]; + } + /** + * The cart checkout request payload + */ + export interface CheckoutCart { + cart?: string | /* A valid cart payload from a client. */ CartDto; + redeemed_promos?: RedeemedPromo[]; + mode?: /* The checkout mode for the cart checkout. */ CheckoutMode; + } + /** + * The cart checkout result + */ + export interface CheckoutCartResult { + order?: /** + * The order entity + * example: + * { + * "order_number": "OR 2022/742701", + * "status": "quote", + * "source": { + * "title": "manual", + * "href": null + * }, + * "source_type": "manual", + * "_schema": "order", + * "_title": "OR 2022/742701", + * "expires_at": "2022-06-30T16:17:00.000Z", + * "line_items": [ + * { + * "price_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "product_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "taxes": [ + * { + * "tax": { + * "_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc", + * "rate": 19, + * "_schema": "tax", + * "_org": "728", + * "_created_at": "2021-09-24T15:06:13.859Z", + * "_updated_at": "2022-04-04T17:36:15.273Z", + * "_title": "Tax Standard", + * "type": "VAT", + * "active": true, + * "region": "DE", + * "description": "Standard" + * }, + * "amount": 255462 + * } + * ], + * "_price": { + * "_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "unit_amount": 100000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "1000", + * "sales_tax": "standard", + * "is_tax_inclusive": true, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Solar Panel Module", + * "description": "Solar Panel Module", + * "active": true, + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "tax": { + * "$relation": [ + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * } + * ] + * }, + * "_org": "728", + * "_created_at": "2022-06-03T16:04:10.369Z", + * "_updated_at": "2022-06-03T16:04:10.369Z" + * }, + * "_product": { + * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", + * "type": "product", + * "_schema": "product", + * "_title": "Solar Panel with Battery Storage", + * "name": "Solar Panel with Battery Storage", + * "code": "SOLAR-BATT", + * "active": true, + * "description": "Solar Panel with battery solution, optimized for max efficiency. ", + * "feature": [ + * { + * "_tags": [], + * "feature": "Eco-Panels" + * }, + * { + * "_tags": [], + * "feature": "Remote Management Platform" + * }, + * { + * "_tags": [], + * "feature": "Battery Remote Control" + * }, + * { + * "_tags": [], + * "feature": "Mobile App" + * } + * ], + * "cross_sellable_products": { + * "$relation": [ + * { + * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", + * "_schema": "product", + * "_tags": [] + * }, + * { + * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", + * "_tags": [] + * } + * ] + * }, + * "product_images": { + * "$relation": [ + * { + * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" + * }, + * { + * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" + * } + * ] + * }, + * "product_downloads": { + * "$relation": [ + * { + * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" + * } + * ] + * }, + * "_org": "728", + * "_created_at": "2022-06-03T15:52:27.512Z", + * "_updated_at": "2022-06-03T16:05:15.029Z", + * "price_options": { + * "$relation": [ + * { + * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "_tags": [] + * }, + * { + * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", + * "_tags": [] + * } + * ] + * } + * }, + * "quantity": 16, + * "currency": "EUR", + * "description": "Solar Panel Module", + * "unit_amount": 100000, + * "unit_amount_net": 84034, + * "amount_subtotal": 1344538, + * "amount_total": 1600000 * }, * { - * "_tags": [], - * "feature": "Remote Management Platform" + * "price_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", + * "product_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "taxes": [ + * { + * "tax": { + * "_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc", + * "rate": 19, + * "_schema": "tax", + * "_org": "728", + * "_created_at": "2021-09-24T15:06:13.859Z", + * "_updated_at": "2022-04-04T17:36:15.273Z", + * "_title": "Tax Standard", + * "type": "VAT", + * "active": true, + * "region": "DE", + * "description": "Standard" + * }, + * "amount": 31933 + * } + * ], + * "_price": { + * "_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", + * "unit_amount": 50000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "500", + * "sales_tax": "standard", + * "is_tax_inclusive": true, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Battery Module 500amps", + * "description": "Battery Module 500amps", + * "active": true, + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "tax": { + * "$relation": [ + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * } + * ] + * }, + * "_org": "728", + * "_created_at": "2022-06-03T16:05:04.391Z", + * "_updated_at": "2022-06-03T16:05:04.391Z" + * }, + * "_product": { + * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", + * "type": "product", + * "_schema": "product", + * "_title": "Solar Panel with Battery Storage", + * "name": "Solar Panel with Battery Storage", + * "code": "SOLAR-BATT", + * "active": true, + * "description": "Solar Panel with battery solution, optimized for max efficiency. ", + * "feature": [ + * { + * "_tags": [], + * "feature": "Eco-Panels" + * }, + * { + * "_tags": [], + * "feature": "Remote Management Platform" + * }, + * { + * "_tags": [], + * "feature": "Battery Remote Control" + * }, + * { + * "_tags": [], + * "feature": "Mobile App" + * } + * ], + * "cross_sellable_products": { + * "$relation": [ + * { + * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", + * "_schema": "product", + * "_tags": [] + * }, + * { + * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", + * "_tags": [] + * } + * ] + * }, + * "product_images": { + * "$relation": [ + * { + * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" + * }, + * { + * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" + * } + * ] + * }, + * "product_downloads": { + * "$relation": [ + * { + * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" + * } + * ] + * }, + * "_org": "728", + * "_created_at": "2022-06-03T15:52:27.512Z", + * "_updated_at": "2022-06-03T16:05:15.029Z", + * "price_options": { + * "$relation": [ + * { + * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "_tags": [] + * }, + * { + * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", + * "_tags": [] + * } + * ] + * } + * }, + * "quantity": 4, + * "currency": "EUR", + * "description": "Battery Module 500amps", + * "unit_amount": 50000, + * "unit_amount_net": 42017, + * "amount_subtotal": 168067, + * "amount_total": 200000 * }, * { - * "_tags": [], - * "feature": "Battery Remote Control" + * "price_id": "d88a8763-3e3d-4fc7-a7a5-2bc9117148bf", + * "product_id": "065d6618-cc59-45f4-8e3a-700edf6813c3", + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "_price": { + * "_id": "d88a8763-3e3d-4fc7-a7a5-2bc9117148bf", + * "unit_amount": 12055, + * "type": "recurring", + * "billing_period": "monthly", + * "billing_duration_amount": 8, + * "billing_duration_unit": "years", + * "notice_time_amount": 3, + * "notice_time_unit": "months", + * "termination_time_amount": 2, + * "termination_time_unit": "months", + * "renewal_duration_amount": 1, + * "renewal_duration_unit": "years", + * "active": true, + * "sales_tax": "reduced", + * "is_tax_inclusive": true, + * "description": "Monthly", + * "billing_scheme": "per_unit", + * "_schema": "price", + * "_org": "728", + * "_created_at": "2021-11-10T14:40:27.695Z", + * "_updated_at": "2021-12-14T18:16:33.248Z", + * "_title": "Monthly", + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "120.55456634", + * "pricing_model": "per_unit", + * "is_composite_price": false + * }, + * "_product": { + * "_id": "065d6618-cc59-45f4-8e3a-700edf6813c3", + * "name": "Smartmeter: Schneider Electric PM5000 LCD Energiemessgerät / 3-phasig", + * "code": "1312378123", + * "_tags": [ + * "wallbox", + * "review demo", + * "1" + * ], + * "categories": [ + * "Power" + * ], + * "type": "product", + * "active": true, + * "feature": [ + * { + * "_tags": [], + * "feature": "Bis zu 11 kW Ladeleistung (5x schneller laden)" + * }, + * { + * "_tags": [], + * "feature": "Integrierter MID Zähler für eine kilowattstundengenaue Abrechnung*" + * }, + * { + * "_tags": [], + * "feature": "Konfigurierbare Ladeleistung" + * }, + * { + * "_tags": [], + * "feature": "Zugangskontrolle über RFID-Karten" + * }, + * { + * "_tags": [], + * "feature": "Kommunikation über LAN" + * }, + * { + * "_tags": [], + * "feature": "New feature" + * } + * ], + * "_schema": "product", + * "_org": "728", + * "_created_at": "2021-11-30T11:05:19.484Z", + * "_updated_at": "2022-01-13T09:18:29.944Z", + * "_title": "Smartmeter: Schneider Electric PM5000 LCD Energiemessgerät / 3-phasig", + * "price_options": { + * "$relation": [ + * { + * "entity_id": "5264b089-fc6a-4a91-9a2a-80c673958faa" + * }, + * { + * "entity_id": "d88a8763-3e3d-4fc7-a7a5-2bc9117148bf" + * } + * ] + * }, + * "product_images": { + * "$relation": [ + * { + * "entity_id": "16729e60-c527-44ef-93c9-c68b6acf1224" + * } + * ] + * } + * }, + * "quantity": 1, + * "currency": "EUR", + * "description": "Monthly", + * "unit_amount": 12055, + * "unit_amount_net": 11267, + * "amount_subtotal": 11267, + * "amount_total": 12055, + * "taxes": [ + * { + * "rate": "reduced", + * "amount": 789 + * } + * ] * }, * { - * "_tags": [], - * "feature": "Mobile App" - * } - * ], - * "cross_sellable_products": { - * "$relation": [ - * { - * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", - * "_schema": "product", - * "_tags": [] + * "price_id": "e1ddf75a-d0d1-40b4-a07e-56e292867c88", + * "product_id": "5b9f05b7-f0f8-49c2-8a8d-0f8f923d6382", + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "_price": { + * "_id": "e1ddf75a-d0d1-40b4-a07e-56e292867c88", + * "unit_amount": 9900, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "99", + * "sales_tax": "standard", + * "is_tax_inclusive": true, + * "price_display_in_journeys": "show_price", + * "type": "recurring", + * "billing_period": "yearly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Yearly payment", + * "description": "Yearly payment", + * "active": true, + * "pricing_model": "per_unit", + * "is_composite_price": false, + * "_org": "728", + * "_created_at": "2022-02-07T22:58:39.884Z", + * "_updated_at": "2022-02-07T22:58:39.884Z" * }, - * { - * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", - * "_tags": [] - * } - * ] - * }, - * "product_images": { - * "$relation": [ - * { - * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" + * "_product": { + * "_id": "5b9f05b7-f0f8-49c2-8a8d-0f8f923d6382", + * "_schema": "product", + * "_title": "Yearly Payment Product", + * "name": "Yearly Payment Product", + * "type": "product", + * "active": true, + * "price_options": { + * "$relation": [ + * { + * "entity_id": "e1ddf75a-d0d1-40b4-a07e-56e292867c88", + * "_tags": [] + * } + * ] + * }, + * "_org": "728", + * "_created_at": "2022-02-07T22:58:44.162Z", + * "_updated_at": "2022-02-08T09:34:08.026Z", + * "description": "Hier steht die Produktbeschreibung die sich auf dem Dokument, was generiert wird, gezogen wird." * }, - * { - * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" - * } - * ] - * }, - * "product_downloads": { - * "$relation": [ - * { - * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" - * } - * ] + * "quantity": 1, + * "currency": "EUR", + * "description": "Yearly payment", + * "unit_amount": 9900, + * "unit_amount_net": 8319, + * "amount_subtotal": 8319, + * "amount_total": 9900, + * "taxes": [ + * { + * "rate": "standard", + * "amount": 1581 + * } + * ] + * } + * ], + * "amount_subtotal": 1532191, + * "amount_total": 1821955, + * "total_details": { + * "amount_tax": 289764, + * "breakdown": { + * "taxes": [ + * { + * "tax": { + * "_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc", + * "rate": 19, + * "_schema": "tax", + * "_org": "728", + * "_created_at": "2021-09-24T15:06:13.859Z", + * "_updated_at": "2022-04-04T17:36:15.273Z", + * "_title": "Tax Standard", + * "type": "VAT", + * "active": true, + * "region": "DE", + * "description": "Standard" + * }, + * "amount": 287395 + * } + * ], + * "recurrences": [ + * { + * "type": "one_time", + * "amount_subtotal": 1512605, + * "amount_subtotal_decimal": "15126.05", + * "amount_total": 1800000, + * "amount_total_decimal": "18000.00", + * "amount_tax": 287395, + * "amount_tax_decimal": "2873.95" + * }, + * { + * "type": "recurring", + * "billing_period": "monthly", + * "amount_subtotal": 11267, + * "amount_subtotal_decimal": "112.67", + * "amount_total": 12055, + * "amount_total_decimal": "120.55", + * "amount_tax": 789, + * "amount_tax_decimal": "7.89" + * }, + * { + * "type": "recurring", + * "billing_period": "yearly", + * "amount_subtotal": 8319, + * "amount_subtotal_decimal": "83.19", + * "amount_total": 9900, + * "amount_total_decimal": "99.00", + * "amount_tax": 1581, + * "amount_tax_decimal": "15.81" + * } + * ] + * } * }, - * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", - * "_org": "728", - * "_created_at": "2022-06-03T15: 52: 27.512Z", - * "_updated_at": "2022-06-03T16: 05: 15.029Z", - * "price_options": { + * "currency": "EUR", + * "payment_method": [ + * { + * "type": "IBAN", + * "details": {} + * } + * ], + * "billing_contact": { * "$relation": [ * { - * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", - * "_tags": [] - * }, - * { - * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", - * "_tags": [] - * } - * ] - * } - * } - */ - _product?: { - [name: string]: any; - /** - * The description for the product - */ - description?: string; - /** - * The product code - */ - code?: string; - /** - * The type of Product: - * - * | type | description | - * |----| ----| - * | `product` | Represents a physical good | - * | `service` | Represents a service or virtual product | - * - */ - type?: "product" | "service"; - /** - * The product main name - */ - name?: string; - /** - * The product categories - */ - categories?: string[]; - feature?: { - /** - * An arbitrary set of tags attached to a feature - */ - _tags?: string[]; - feature?: string; - }[]; - /** - * Stores references to products that can be cross sold with the current product. - */ - cross_sellable_products?: { - $relation?: EntityRelation[]; - }; - /** - * Stores references to a set of file images of the product - */ - product_images?: /* Stores references to a set of file images of the product */ { - $relation?: EntityRelation[]; - } | File[]; - /** - * Stores references to a set of files downloadable from the product. - * e.g: tech specifications, quality control sheets, privacy policy agreements - * - */ - product_downloads?: /** - * Stores references to a set of files downloadable from the product. - * e.g: tech specifications, quality control sheets, privacy policy agreements - * - */ - { - $relation?: EntityRelation[]; - } | File[]; - /** - * A set of [prices](/api/pricing#tag/simple_price_schema) or [composite prices](/api/pricing#tag/dynamic_price_schema) for the current product. - */ - price_options?: { - $relation?: EntityRelation[]; - }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; - /** - * Stores references to the availability files that define where this product is available. - * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. - * - */ - _availability_files?: File[]; - /** - * The product id - */ - _id?: string; - /** - * The autogenerated product title - */ - _title?: string; - /** - * The organization id the product belongs to - */ - _org_id?: string; - /** - * The product creation date - */ - _created_at?: string; - /** - * The product last update date - */ - _updated_at?: string; - }; - /** - * price item id - */ - _id?: string; - /** - * The unit amount value - */ - unit_amount?: number; - /** - * The unit amount in eur to be charged, represented as a decimal string with at most 12 decimal places. - */ - unit_amount_decimal?: string; - /** - * The unit amount before any discount is applied - */ - before_discount_unit_amount?: number; - /** - * The unit amount before any discount is applied, represented as a decimal string with at most 12 decimal places. - */ - before_discount_unit_amount_decimal?: string; - /** - * The unit gross amount before any discount is applied - */ - before_discount_unit_amount_gross?: number; - /** - * The unit gross amount before any discount is applied, represented as a decimal string with at most 12 decimal places. - */ - before_discount_unit_amount_gross_decimal?: string; - /** - * The unit net amount before any discount is applied - */ - before_discount_unit_amount_net?: number; - /** - * The unit net amount before any discount is applied, represented as a decimal string with at most 12 decimal places. - */ - before_discount_unit_amount_net_decimal?: string; - /** - * The discount amount applied for each unit - */ - unit_discount_amount?: number; - /** - * The discount amount applied for each unit represented as a decimal string - */ - unit_discount_amount_decimal?: string; - /** - * The unit gross amount value. - */ - unit_amount_gross?: number; - /** - * The unit gross amount value. - */ - unit_amount_gross_decimal?: string; - /** - * Net unit amount without taxes or discounts. - */ - unit_amount_net?: number; - /** - * Net unit amount without taxes or discounts. - */ - unit_amount_net_decimal?: string; - /** - * The net discount amount applied for each unit - */ - unit_discount_amount_net?: number; - /** - * The net discount amount applied for each unit represented as a decimal string - */ - unit_discount_amount_net_decimal?: string; - /** - * The discount amount applied to the tax - */ - tax_discount_amount?: number; - /** - * The discount amount applied to the tax represented as a decimal string - */ - tax_discount_amount_decimal?: string; - /** - * The net discount amount applied - */ - discount_amount_net?: number; - /** - * The net discount amount applied represented as a decimal string - */ - discount_amount_net_decimal?: string; - /** - * Total tax amount for this line item. - */ - amount_tax?: number; - /** - * The tax amount before any discount is applied - */ - before_discount_tax_amount?: number; - /** - * The tax amount before any discount is applied represented as a decimal string - */ - before_discount_tax_amount_decimal?: string; - currency?: /** - * Three-letter ISO currency code, in lowercase. Must be a supported currency. - * ISO 4217 CURRENCY CODES as specified in the documentation: https://www.iso.org/iso-4217-currency-codes.html - * - * example: - * EUR - */ - Currency; - /** - * The taxes applied to the price item. - */ - taxes?: (/* A tax amount associated with a specific tax rate. */ TaxAmount)[]; - /** - * The sum of amounts of the price items by recurrence. - */ - recurrences?: (/* An amount associated with a specific recurrence. */ RecurrenceAmount)[]; - /** - * The coupons applicable to the composite price item + related (cashback) amounts + * "entity_id": "1834a54e-b68f-4f7f-a98a-fe16f11bc2a5", + * "_tags": [] + * } + * ] + * }, + * "billing_first_name": "Joao", + * "billing_last_name": "Pinho", + * "billing_email": "j.pinho@epilot.cloud", + * "billing_company_name": "epilot cloud", + * "billing_address": [ + * { + * "_tags": [], + * "street": "Im Media Park", + * "street_number": "8a", + * "postal_code": "52000", + * "city": "Cologne", + * "country": "DE", + * "additional_info": "" + * } + * ], + * "delivery_address": [], + * "dates": [ + * { + * "_tags": [ + * "Instalation Date" + * ], + * "dates": "", + * "value": "2022-06-30T16:29:00.000Z" + * } + * ], + * "_id": "4c7c9562-f8f0-4af0-a3a6-6aebc5571a6e", + * "_org": "728", + * "_created_at": "2022-06-03T16:29:46.303Z", + * "_updated_at": "2022-06-03T16:29:46.303Z" + * } */ - _coupons?: ({ - [name: string]: any; - _id: EntityId /* uuid */; - /** - * The auto-generated title for the title - */ - _title: string; - /** - * Organization Id the entity belongs to - */ - _org: string; - /** - * The schema of the entity, for coupons it is always `coupon` - */ - _schema: "coupon"; - _tags?: string[]; - /** - * The creation date for the opportunity - */ - _created_at: string; // date-time - /** - * The date the coupon was last updated - */ - _updated_at: string; // date-time - name: string | null; - description?: string | null; - type: "fixed" | "percentage"; - category: "discount" | "cashback"; - /** - * Use if type is set to percentage. The percentage to be discounted, represented as a whole integer. - */ - percentage_value?: string | null; - /** - * Use if type is set to fixed. The fixed amount in cents to be discounted, represented as a whole integer. - */ - fixed_value?: number; - /** - * Use if type is set to fixed. The unit amount in eur to be discounted, represented as a decimal string with at most 12 decimal places. - */ - fixed_value_decimal?: string; - /** - * Use if type is set to fixed. Three-letter ISO currency code, in lowercase. - */ - fixed_value_currency?: /* Use if type is set to fixed. Three-letter ISO currency code, in lowercase. */ /** - * Three-letter ISO currency code, in lowercase. Must be a supported currency. - * ISO 4217 CURRENCY CODES as specified in the documentation: https://www.iso.org/iso-4217-currency-codes.html - * - * example: - * EUR - */ - Currency; - cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; - active?: boolean; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; - /** - * Whether the coupon requires a promo code to be applied - */ - requires_promo_code?: boolean; - /** - * The cashback amount. - */ - cashback_amount?: number; - /** - * The cashback amount as a string with all the decimal places. - */ - cashback_amount_decimal?: string; - /** - * Total amount after cashback is applied. - */ - after_cashback_amount_total?: number; - /** - * Total amount after cashback is applied as a string with all the decimal places. - */ - after_cashback_amount_total_decimal?: string; - } & /* The shared properties for the coupon entity and coupon item entity */ (/* The shared properties for the coupon entity and coupon item entity */ CouponItem))[]; + Order; + } + /** + * The checkout mode for the cart checkout. + */ + export type CheckoutMode = "create_order" | "create_invoice" | "create_quote"; + /** + * The composite price entity + * example: + * { + * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_title": "My Composite Price", + * "description": "My Composite Price", + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "is_composite_price": true, + * "price_components": { + * "$relation": [ + * { + * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 1, + * "item": { + * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * }, + * { + * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 2, + * "item": { + * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * } + * ] + * } + * } + */ + export type CompositePrice = /** + * The composite price entity + * example: + * { + * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_title": "My Composite Price", + * "description": "My Composite Price", + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "is_composite_price": true, + * "price_components": { + * "$relation": [ + * { + * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 1, + * "item": { + * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * }, + * { + * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 2, + * "item": { + * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * } + * ] + * } + * } + */ + /** + * The composite price entity + * example: + * { + * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_title": "My Composite Price", + * "description": "My Composite Price", + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "is_composite_price": true, + * "price_components": { + * "$relation": [ + * { + * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 1, + * "item": { + * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * }, + * { + * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 2, + * "item": { + * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * } + * ] + * } + * } + */ + NonHydratedCompositePrice | /** + * The composite price entity + * example: + * { + * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_title": "My Composite Price", + * "description": "My Composite Price", + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "is_composite_price": true, + * "price_components": { + * "$relation": [ + * { + * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 1, + * "item": { + * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * }, + * { + * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 2, + * "item": { + * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * } + * ] + * } + * } + */ + HydratedCompositePrice; + /** + * Represents a composite price input to the pricing library. + * example: + * { + * "amount_subtotal": 10000, + * "amount_total": 10600, + * "currency": "EUR", + * "description": "Annual internet service", + * "price_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "product_id": "6241487f-b7fd-428b-ab92-24ee0b37fd84", + * "taxes": [ + * { + * "amount": 600, + * "tax": { + * "active": true, + * "description": "Without Behaviour", + * "rate": 6, + * "region": "DE", + * "type": "VAT", + * "_created_at": "2022-02-07T14:49:08.831Z", + * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", + * "_org": "739224", + * "_schema": "tax", + * "_title": "Tax Without Behaviour", + * "_updated_at": "2022-02-07T14:49:08.831Z" + * } + * } + * ], + * "unit_amount": 10000, + * "unit_amount_net": 10000, + * "pricing_model": "per_unit", + * "_price": { + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Solar Panel Module", + * "description": "Solar Panel Module", + * "active": true, + * "tax": { + * "$relation": [ + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * } + * ] + * }, + * "_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "_org": "728", + * "_created_at": "2022-06-03T16:04:10.369Z", + * "_updated_at": "2022-06-03T16:04:10.369Z", + * "pricing_model": "per_unit" + * }, + * "_product": { + * "name": "Cool box", + * "type": "product", + * "_id": "73f857a4-0fbc-4aa6-983f-87c0d6d410a6", + * "_title": "Cool box" + * } + * } + */ + export interface CompositePriceItem { /** - * When set to true on a `_price` displayed as OnRequest (`show_as_on_request: 'on_request'`) this flag means the price has been approved and can now be displayed to the customer. This flag is only valid for prices shown as 'on_request'. + * Total of all items before (discounts or) taxes are applied. */ - on_request_approved?: boolean; + amount_subtotal?: number; /** - * The flag for prices that contain price components. + * Total of all items before (discounts or) taxes are applied, as a string with all the decimal places. */ - is_composite_price: true; + amount_subtotal_decimal?: string; /** - * Contains price item configurations, per price component, when the main price item is a [composite price](/api/pricing#tag/dynamic_price_schema). + * Total of all items after (discounts and) taxes are applied. */ - item_components?: /** - * Represents a price item - * example: - * { - * "amount_subtotal": 10000, - * "amount_total": 10600, - * "currency": "EUR", - * "description": "Annual internet service", - * "price_id": "7e24ff5d-d580-4136-a32f-19191eed039a", - * "product_id": "6241487f-b7fd-428b-ab92-24ee0b37fd84", - * "taxes": [ - * { - * "amount": 600, - * "tax": { - * "active": true, - * "description": "Without Behaviour", - * "rate": 6, - * "region": "DE", - * "type": "VAT", - * "_created_at": "2022-02-07T14:49:08.831Z", - * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", - * "_org": "739224", - * "_schema": "tax", - * "_title": "Tax Without Behaviour", - * "_updated_at": "2022-02-07T14:49:08.831Z" - * } - * }, - * { - * "amount": 600, - * "tax": { - * "active": true, - * "description": "Without Behaviour", - * "rate": 6, - * "region": "DE", - * "type": "VAT", - * "_created_at": "2022-02-07T14:49:08.831Z", - * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", - * "_org": "739224", - * "_schema": "tax", - * "_title": "Tax Without Behaviour", - * "_updated_at": "2022-02-07T14:49:08.831Z" - * } - * } - * ], - * "unit_amount": 10000, - * "unit_amount_net": 10000, - * "pricing_model": "per_unit", - * "_price": { - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "_schema": "price", - * "_title": "Solar Panel Module", - * "description": "Solar Panel Module", - * "active": true, - * "tax": { - * "$relation": [ - * { - * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" - * }, - * { - * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" - * } - * ] - * }, - * "_id": "7e24ff5d-d580-4136-a32f-19191eed039a", - * "_org": "728", - * "_created_at": "2022-06-03T16:04:10.369Z", - * "_updated_at": "2022-06-03T16:04:10.369Z", - * "pricing_model": "per_unit" - * }, - * "_product": { - * "name": "Cool box", - * "type": "product", - * "_id": "73f857a4-0fbc-4aa6-983f-87c0d6d410a6", - * "_title": "Cool box" - * } - * } + amount_total?: number; + /** + * Total of all items after (discounts and) taxes are applied, as a string with all the decimal places. */ - PriceItem[]; - total_details?: /* The total details with tax (and discount) aggregated totals. */ TotalDetails; + amount_total_decimal?: string; /** - * The price snapshot data. + * The cashback amount. */ - _price?: /* The price snapshot data. */ /** - * The composite price entity - * example: - * { - * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_title": "My Composite Price", - * "description": "My Composite Price", - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "is_composite_price": true, - * "price_components": { - * "$relation": [ - * { - * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 1, - * "item": { - * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * }, - * { - * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 2, - * "item": { - * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * } - * ] - * } - * } + cashback_amount?: number; + /** + * The cashback amount as a string with all the decimal places. + */ + cashback_amount_decimal?: string; + cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; + /** + * Total amount after cashback is applied. + */ + after_cashback_amount_total?: number; + /** + * Total amount after cashback is applied as a string with all the decimal places. + */ + after_cashback_amount_total_decimal?: string; + /** + * The discount amount. + */ + discount_amount?: number; + /** + * The discount amount as a string with all the decimal places. */ - CompositePrice; - } - /** - * Represents a composite price input to the pricing library. - */ - export interface CompositePriceItemDto { + discount_amount_decimal?: string; + /** + * The discount percentage, if the applied coupon had a percentage type. + */ + discount_percentage?: number; + /** + * Total amount before discount is applied. + */ + before_discount_amount_total?: number; + /** + * Total amount before discount is applied as a string with all the decimal places. + */ + before_discount_amount_total_decimal?: string; + /** + * Total amount before discount is applied, excluding taxes. + */ + before_discount_amount_subtotal?: number; + /** + * Total amount before discount is applied, excluding taxes, as a string with all the decimal places. + */ + before_discount_amount_subtotal_decimal?: string; metadata?: /* A set of key-value pairs used to store meta data information about an entity. */ MetaData; /** * The quantity of products being purchased. @@ -8837,12 +3173,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -8870,324 +3200,103 @@ declare namespace Components { */ _updated_at?: string; }; - external_fees_mappings?: /** - * example: - * [ - * { - * "price_id": "589B011B-F8D9-4F8E-AD71-BACE4B543C0F", - * "frequency_unit": "weekly", - * "amount_total": 1000, - * "amount_total_decimal": "10.00" - * } - * ] - */ - ExternalFeeMappings; - external_fees_metadata?: ExternalFeeMetadata; - external_location_metadata?: /* The provider entity */ ExternalLocationMetadata; - external_price_metadata?: ExternalPriceMetadata; - _immutable_pricing_details?: /* The result from the calculation of a set of price items. */ PricingDetails; - /** - * The ids of the coupons applicable to the price item - */ - coupon_ids?: string[]; - /** - * The taxes applied to the price item. - */ - taxes?: (/* A valid tax rate from a client. */ TaxAmountDto)[]; - /** - * The taxes applied to the price item. - */ - recurrences?: (/* An amount associated with a specific recurrence. */ RecurrenceAmountDto)[]; - /** - * The coupons applicable to the price item - */ - _coupons?: (/* The shared properties for the coupon entity and coupon item entity */ CouponItem)[]; - /** - * The flag for prices that contain price components. - */ - is_composite_price: true; - /** - * Contains price item configurations, per price component, when the main price item is a [composite price](/api/pricing#tag/dynamic_price_schema). - */ - item_components?: /* Represents a price input to the pricing library. */ PriceItemDto[]; - /** - * The ids of the price components that should be selected for the price calculation. - */ - selected_price_component_ids?: string[]; - /** - * The map of coupon ids applicable to the price components - */ - price_component_coupon_ids?: { - [name: string]: string[]; - }; - _price?: /** - * The composite price entity - * example: - * { - * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_title": "My Composite Price", - * "description": "My Composite Price", - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "is_composite_price": true, - * "price_components": { - * "$relation": [ - * { - * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 1, - * "item": { - * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * }, - * { - * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "_schema": "price", - * "_product_id": "target-price-product-id", - * "quantity": 2, - * "item": { - * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", - * "unit_amount": 10000, - * "unit_amount_currency": "EUR", - * "unit_amount_decimal": "100.00", - * "sales_tax": "standard", - * "is_tax_inclusive": false, - * "price_display_in_journeys": "show_price", - * "type": "one_time", - * "_schema": "price", - * "_title": "Test 1", - * "description": "Test 1", - * "tax": { - * "$relation": [ - * { - * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" - * } - * ] - * }, - * "_org": "739224", - * "_created_at": "2022-02-18T10:10:26.439Z", - * "_updated_at": "2022-02-18T11:53:04.191Z", - * "active": true, - * "billing_period": "weekly", - * "billing_duration_unit": "months", - * "notice_time_unit": "months", - * "termination_time_unit": "months", - * "renewal_duration_unit": "months", - * "is_composite_price": false - * } - * } - * ] - * } - * } - */ - CompositePrice; - } - /** - * The compute price payload - */ - export type ComputePriceParams = /* The compute price payload */ /* The compute price payload for power */ ComputePriceParamsPower | /* The compute price payload for gas */ ComputePriceParamsGas; - export interface ComputePriceParamsBase { - /** - * The postal code to search for providers - */ - postal_code: string; - /** - * The consumption type - */ - consumption_type?: "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; - /** - * (DEPRECATED - use consumption_HT) The yearly consumption to compute the price in kWh - */ - consumption?: number; - /** - * The yearly HT consumption to compute the price in kWh - */ - consumption_HT?: number; - /** - * The yearly NT consumption to compute the price in kWh - */ - consumption_NT?: number; - /** - * The association id - */ - association_id?: string; - /** - * The billing period (defaults to monthly) - */ - billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; - /** - * The optional reference date for the price computation (ISO 8601 format) - */ - reference_date?: string; // date - } - /** - * The compute price payload for gas - */ - export interface ComputePriceParamsGas { - /** - * The postal code to search for providers - */ - postal_code: string; - /** - * The consumption type - */ - consumption_type?: "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; - /** - * (DEPRECATED - use consumption_HT) The yearly consumption to compute the price in kWh - */ - consumption?: number; - /** - * The yearly HT consumption to compute the price in kWh - */ - consumption_HT?: number; - /** - * The yearly NT consumption to compute the price in kWh - */ - consumption_NT?: number; - /** - * The association id - */ - association_id?: string; - /** - * The billing period (defaults to monthly) - */ - billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; - /** - * The optional reference date for the price computation (ISO 8601 format) - */ - reference_date?: string; // date /** - * The type of energy to compute the price + * price item id */ - type: "gas"; - concession_type?: /* The concession type for gas */ GasConcessionType; - } - /** - * The compute price payload for power - */ - export interface ComputePriceParamsPower { + _id?: string; /** - * The postal code to search for providers + * The unit amount value */ - postal_code: string; + unit_amount?: number; /** - * The consumption type + * The unit amount in eur to be charged, represented as a decimal string with at most 12 decimal places. */ - consumption_type?: "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; + unit_amount_decimal?: string; /** - * (DEPRECATED - use consumption_HT) The yearly consumption to compute the price in kWh + * The unit amount before any discount is applied */ - consumption?: number; + before_discount_unit_amount?: number; /** - * The yearly HT consumption to compute the price in kWh + * The unit amount before any discount is applied, represented as a decimal string with at most 12 decimal places. */ - consumption_HT?: number; + before_discount_unit_amount_decimal?: string; /** - * The yearly NT consumption to compute the price in kWh + * The unit gross amount before any discount is applied */ - consumption_NT?: number; + before_discount_unit_amount_gross?: number; /** - * The association id + * The unit gross amount before any discount is applied, represented as a decimal string with at most 12 decimal places. */ - association_id?: string; + before_discount_unit_amount_gross_decimal?: string; /** - * The billing period (defaults to monthly) + * The unit net amount before any discount is applied */ - billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; + before_discount_unit_amount_net?: number; /** - * The optional reference date for the price computation (ISO 8601 format) + * The unit net amount before any discount is applied, represented as a decimal string with at most 12 decimal places. */ - reference_date?: string; // date + before_discount_unit_amount_net_decimal?: string; /** - * The type of energy to compute the price + * The discount amount applied for each unit */ - type: "power"; - meter_type?: /* The meter type for power */ PowerMeterType; - } - export interface ComputePriceResult { + unit_discount_amount?: number; /** - * The computed total price + * The discount amount applied for each unit represented as a decimal string */ - amount_total: number; + unit_discount_amount_decimal?: string; /** - * The computed total price as decimal + * The unit gross amount value. */ - amount_total_decimal: string; + unit_amount_gross?: number; /** - * The computed static price + * The unit gross amount value. */ - amount_static?: number; + unit_amount_gross_decimal?: string; /** - * The computed static price as decimal + * Net unit amount without taxes or discounts. */ - amount_static_decimal?: any; + unit_amount_net?: number; /** - * The computed variable price, for the day period + * Net unit amount without taxes or discounts. */ - amount_variable_ht?: number; + unit_amount_net_decimal?: string; /** - * The computed variable price, for the day period, as decimal + * The net discount amount applied for each unit */ - amount_variable_decimal_ht?: string; + unit_discount_amount_net?: number; /** - * The computed unit price, for the day period + * The net discount amount applied for each unit represented as a decimal string */ - unit_amount_variable_ht?: number; + unit_discount_amount_net_decimal?: string; /** - * The computed unit price, for the day period, as decimal + * The discount amount applied to the tax */ - unit_amount_variable_decimal_ht?: string; + tax_discount_amount?: number; /** - * The computed variable price, for the night period + * The discount amount applied to the tax represented as a decimal string */ - amount_variable_nt?: number; + tax_discount_amount_decimal?: string; /** - * The computed variable price, for the night period, as decimal + * The net discount amount applied */ - amount_variable_decimal_nt?: string; + discount_amount_net?: number; /** - * The computed unit price, for the night period + * The net discount amount applied represented as a decimal string */ - unit_amount_variable_nt?: number; + discount_amount_net_decimal?: string; /** - * The computed unit price, for the night period, as decimal + * Total tax amount for this line item. */ - unit_amount_variable_decimal_nt?: string; + amount_tax?: number; /** - * The currency of the computed price (three-letter ISO currency code) + * The tax amount before any discount is applied */ - currency: /* The currency of the computed price (three-letter ISO currency code) */ /** + before_discount_tax_amount?: number; + /** + * The tax amount before any discount is applied represented as a decimal string + */ + before_discount_tax_amount_decimal?: string; + currency?: /** * Three-letter ISO currency code, in lowercase. Must be a supported currency. * ISO 4217 CURRENCY CODES as specified in the documentation: https://www.iso.org/iso-4217-currency-codes.html * @@ -9196,1443 +3305,1071 @@ declare namespace Components { */ Currency; /** - * The billing period - */ - billing_period: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; - breakdown: /* Price breakdown */ ComputedPriceBreakdown; - _meta?: /* Signature meta data payload */ SignatureMeta; - } - /** - * The computed price - */ - export interface ComputedBasePrice { - /** - * The computed price - */ - amount: number; - /** - * The computed price as decimal - */ - amount_decimal: string; - /** - * The computed unit price - */ - unit_amount?: number; - /** - * The computed unit price as decimal - */ - unit_amount_decimal?: string; - } - /** - * Price breakdown - */ - export interface ComputedPriceBreakdown { - static?: /* The computed price components */ ComputedPriceComponents; - variable?: /* The computed price components */ ComputedPriceComponents; - variable_ht?: /* The computed price components */ ComputedPriceComponents; - variable_nt?: /* The computed price components */ ComputedPriceComponents; - } - /** - * The computed price components - */ - export interface ComputedPriceComponents { - [name: string]: /* The computed price */ ComputedBasePrice; - } - /** - * One condition dimension, in the shape a schema's `conditions` array holds it — copy it in - * verbatim. - * - */ - export interface ConditionDefinition { - /** - * Stable identity of the condition, round-tripped unchanged for the lifetime of the - * condition: it is what tells a rename apart from a remove plus an add. The Entity API - * mints none of its own, so whoever creates a condition supplies one — a catalog condition - * arrives with the identity the catalog gives it, the same in every org, and is copied into - * the schema along with the rest of the object. - * - * example: - * d5839b94-ba20-4225-a78e-76951d352bd6 + * The taxes applied to the price item. */ - id: string; // uuid + taxes?: (/* A tax amount associated with a specific tax rate. */ TaxAmount)[]; /** - * How variants and resolve contexts refer to this condition. Independent of attribute - * names: a value needed as an attribute too is duplicated onto the variant. - * - * `default`, and any name beginning with `_`, are reserved for the server: a condition - * declared under one is ignored, since nothing could pin it and no context could address it. - * - * example: - * postal_code + * The sum of amounts of the price items by recurrence. */ - name: string; + recurrences?: (/* An amount associated with a specific recurrence. */ RecurrenceAmount)[]; /** - * Human-readable name of the condition. - * example: - * Postal Code - */ - label: string; - type: /** - * The kind of value a condition holds, which decides how a variant's pinned value is matched - * against a resolve context. - * - * - `string`: an arbitrary string, matched exactly and case-sensitively - * - `number`: a numeric value - * - `date`: a single date - * - `daterange`: a window with a from and an until timestamp; both ends may be left open - * - `boolean`: a true/false value - * - `select`: one of the values declared in `options`, which is always a closed vocabulary - * - `location`: a geographic value, shaped by `format` - * - * There is no condition type for the fallback variant. Being the entity's fallback is a - * property of the variant, set by the `default` flag on a variant write, and needs nothing - * declared in the schema. - * + * The coupons applicable to the composite price item + related (cashback) amounts */ - ConditionType; + _coupons?: ({ + [name: string]: any; + _id: EntityId /* uuid */; + /** + * The auto-generated title for the title + */ + _title: string; + /** + * Organization Id the entity belongs to + */ + _org: string; + /** + * The schema of the entity, for coupons it is always `coupon` + */ + _schema: "coupon"; + _tags?: string[]; + /** + * The creation date for the opportunity + */ + _created_at: string; // date-time + /** + * The date the coupon was last updated + */ + _updated_at: string; // date-time + name: string | null; + description?: string | null; + type: "fixed" | "percentage"; + category: "discount" | "cashback"; + /** + * Use if type is set to percentage. The percentage to be discounted, represented as a whole integer. + */ + percentage_value?: string | null; + /** + * Use if type is set to fixed. The fixed amount in cents to be discounted, represented as a whole integer. + */ + fixed_value?: number; + /** + * Use if type is set to fixed. The unit amount in eur to be discounted, represented as a decimal string with at most 12 decimal places. + */ + fixed_value_decimal?: string; + /** + * Use if type is set to fixed. Three-letter ISO currency code, in lowercase. + */ + fixed_value_currency?: /* Use if type is set to fixed. Three-letter ISO currency code, in lowercase. */ /** + * Three-letter ISO currency code, in lowercase. Must be a supported currency. + * ISO 4217 CURRENCY CODES as specified in the documentation: https://www.iso.org/iso-4217-currency-codes.html + * + * example: + * EUR + */ + Currency; + cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; + active?: boolean; + /** + * Whether the coupon requires a promo code to be applied + */ + requires_promo_code?: boolean; + /** + * The cashback amount. + */ + cashback_amount?: number; + /** + * The cashback amount as a string with all the decimal places. + */ + cashback_amount_decimal?: string; + /** + * Total amount after cashback is applied. + */ + after_cashback_amount_total?: number; + /** + * Total amount after cashback is applied as a string with all the decimal places. + */ + after_cashback_amount_total_decimal?: string; + } & /* The shared properties for the coupon entity and coupon item entity */ (/* The shared properties for the coupon entity and coupon item entity */ CouponItem))[]; /** - * The declared vocabulary of a `select` condition. Absent for every other type. - * - * The same shape a `select` condition's `options` has on the Entity API, item for item: an - * entry is either the value itself or an object carrying that value and an optional display - * `title`. A `title` is never pinned by a variant and never matched — two entries differing - * only in their title are one vocabulary entry. - * - * The vocabulary is always closed: a condition carries no flag widening it, so a pinned - * value outside a declared vocabulary is rejected with `CONDITION_VALUE_INVALID`. A - * vocabulary that declares nothing is closed too — while `options` is absent or empty, or - * holds nothing this deploy can read, the condition admits no pin at all and the same code - * is returned with an empty `options`. It is *not* enforced on resolve — a vocabulary says - * what may be stored, not what may be asked for, so a context value outside it is a query - * that simply matches nothing. - * - * example: - * [ - * "private", - * { - * "value": "commercial", - * "title": "Commercial customers" - * } - * ] + * When set to true on a `_price` displayed as OnRequest (`show_as_on_request: 'on_request'`) this flag means the price has been approved and can now be displayed to the customer. This flag is only valid for prices shown as 'on_request'. */ - options?: (string | { - value: string; - title?: string; - })[]; + on_request_approved?: boolean; /** - * The value shape of a `location` condition. Absent for every other type. + * The flag for prices that contain price components. */ - format?: "zipcode" | "zipcode_town"; - } - /** - * A named bundle of condition definitions, built in for one entity type. - */ - export interface ConditionSet { + is_composite_price: true; /** - * Identifies the set within this entity type's catalog. - * example: - * delivery_area + * Contains price item configurations, per price component, when the main price item is a [composite price](/api/pricing#tag/dynamic_price_schema). */ - id: string; - /** - * Human-readable name of the set. + item_components?: /** + * Represents a price item * example: - * Delivery Area - */ - label: string; - /** - * What the set is for, and when to reach for it. + * { + * "amount_subtotal": 10000, + * "amount_total": 10600, + * "currency": "EUR", + * "description": "Annual internet service", + * "price_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "product_id": "6241487f-b7fd-428b-ab92-24ee0b37fd84", + * "taxes": [ + * { + * "amount": 600, + * "tax": { + * "active": true, + * "description": "Without Behaviour", + * "rate": 6, + * "region": "DE", + * "type": "VAT", + * "_created_at": "2022-02-07T14:49:08.831Z", + * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", + * "_org": "739224", + * "_schema": "tax", + * "_title": "Tax Without Behaviour", + * "_updated_at": "2022-02-07T14:49:08.831Z" + * } + * }, + * { + * "amount": 600, + * "tax": { + * "active": true, + * "description": "Without Behaviour", + * "rate": 6, + * "region": "DE", + * "type": "VAT", + * "_created_at": "2022-02-07T14:49:08.831Z", + * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", + * "_org": "739224", + * "_schema": "tax", + * "_title": "Tax Without Behaviour", + * "_updated_at": "2022-02-07T14:49:08.831Z" + * } + * } + * ], + * "unit_amount": 10000, + * "unit_amount_net": 10000, + * "pricing_model": "per_unit", + * "_price": { + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Solar Panel Module", + * "description": "Solar Panel Module", + * "active": true, + * "tax": { + * "$relation": [ + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * }, + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * } + * ] + * }, + * "_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "_org": "728", + * "_created_at": "2022-06-03T16:04:10.369Z", + * "_updated_at": "2022-06-03T16:04:10.369Z", + * "pricing_model": "per_unit" + * }, + * "_product": { + * "name": "Cool box", + * "type": "product", + * "_id": "73f857a4-0fbc-4aa6-983f-87c0d6d410a6", + * "_title": "Cool box" + * } + * } */ - description: string; + PriceItem[]; + total_details?: /* The total details with tax (and discount) aggregated totals. */ TotalDetails; /** - * The condition definitions to copy into the schema's own `conditions` array. - */ - conditions: /** - * One condition dimension, in the shape a schema's `conditions` array holds it — copy it in - * verbatim. - * + * The price snapshot data. */ - ConditionDefinition[]; - } - export interface ConditionSetCatalog { - /** - * The condition sets built in for the requested entity type, in the order they are offered. - * + _price?: /* The price snapshot data. */ /** + * The composite price entity + * example: + * { + * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_title": "My Composite Price", + * "description": "My Composite Price", + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "is_composite_price": true, + * "price_components": { + * "$relation": [ + * { + * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 1, + * "item": { + * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * }, + * { + * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 2, + * "item": { + * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * } + * ] + * } + * } */ - results: /* A named bundle of condition definitions, built in for one entity type. */ ConditionSet[]; + CompositePrice; } /** - * The kind of value a condition holds, which decides how a variant's pinned value is matched - * against a resolve context. - * - * - `string`: an arbitrary string, matched exactly and case-sensitively - * - `number`: a numeric value - * - `date`: a single date - * - `daterange`: a window with a from and an until timestamp; both ends may be left open - * - `boolean`: a true/false value - * - `select`: one of the values declared in `options`, which is always a closed vocabulary - * - `location`: a geographic value, shaped by `format` - * - * There is no condition type for the fallback variant. Being the entity's fallback is a - * property of the variant, set by the `default` flag on a variant write, and needs nothing - * declared in the schema. - * - */ - export type ConditionType = "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"; - /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - export type ConditionalEntitySlug = "product" | "price" | "coupon"; - /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - export type ConditionalPricingError = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * + * Represents a composite price input to the pricing library. */ - { - code: "SCHEMA_NOT_FOUND"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - }; + export interface CompositePriceItemDto { + metadata?: /* A set of key-value pairs used to store meta data information about an entity. */ MetaData; /** - * Error message + * The quantity of products being purchased. */ - message: string; + quantity?: number; /** - * The HTTP status code + * The id of the product. */ - status?: number; + product_id?: string; /** - * The cause of the error (visible for bad requests - http 400) + * The id of the price. */ - cause?: string; + price_id?: string; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * An arbitrary string attached to the price item. Often useful for displaying to users. Defaults to product name. */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_NOT_FOUND"; - details: { - /** - * The entity type the request addressed. - * example: - * price - */ - schema: string; - /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; + description?: string; /** - * Error message + * The description for the product. */ - message: string; + product_description?: string; /** - * The HTTP status code + * The name for the product. */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) + product_name?: string; + price_mappings?: /** + * example: + * [ + * { + * "price_id": "589B011B-F8D9-4F8E-AD71-BACE4B543C0F", + * "frequency_unit": "weekly", + * "value": 1000.245, + * "name": "avg consumption", + * "metadata": { + * "journey_title": "energy journey", + * "step_name": "avg consumption picker" + * } + * } + * ] */ - cause?: string; + PriceInputMappings; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * Specifies whether the price is considered `inclusive` of taxes or not. */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + is_tax_inclusive?: boolean; + /** + * The snapshot of the product. + * example: + * { + * "type": "product", + * "_schema": "product", + * "_title": "Solar Panel with Battery Storage", + * "name": "Solar Panel with Battery Storage", + * "code": "SOLAR-BATT", + * "active": true, + * "description": "Solar Panel with battery solution, optimized for max efficiency. ", + * "feature": [ + * { + * "_tags": [], + * "feature": "Eco-Panels" + * }, + * { + * "_tags": [], + * "feature": "Remote Management Platform" + * }, + * { + * "_tags": [], + * "feature": "Battery Remote Control" + * }, + * { + * "_tags": [], + * "feature": "Mobile App" + * } + * ], + * "cross_sellable_products": { + * "$relation": [ + * { + * "entity_id": "068d0713-a650-4668-9ed2-eca7be31e337", + * "_schema": "product", + * "_tags": [] + * }, + * { + * "entity_id": "c8402ee7-fba9-4f3d-bffd-6803ca655782", + * "_tags": [] + * } + * ] + * }, + * "product_images": { + * "$relation": [ + * { + * "entity_id": "37bdeaaa-65fe-403e-9894-65b01cd277f1" + * }, + * { + * "entity_id": "56dde657-795c-41bb-bf53-98fd586b7e6e" + * } + * ] + * }, + * "product_downloads": { + * "$relation": [ + * { + * "entity_id": "64211361-8759-414b-81c0-afbf24f83aa9" + * } + * ] + * }, + * "_id": "a7f4771a-6368-4d77-bb01-71f1e4902de5", + * "_org": "728", + * "_created_at": "2022-06-03T15: 52: 27.512Z", + * "_updated_at": "2022-06-03T16: 05: 15.029Z", + * "price_options": { + * "$relation": [ + * { + * "entity_id": "9c36c23b-1574-4193-beff-b1b5e1124bc7", + * "_tags": [] + * }, + * { + * "entity_id": "146aa2cc-f267-4d5e-bda4-cbe2669b7741", + * "_tags": [] + * } + * ] + * } + * } */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { + _product?: { [name: string]: any; - }[]; - } | { - code: "ENTITY_TYPE_MISMATCH"; - details: { /** - * The entity type the request addressed. - * example: - * price + * The description for the product */ - schema: string; + description?: string; /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo + * The product code */ - entity_id: string; + code?: string; /** - * The entity type that id belongs to. Where it is a conditional entity type, it - * is the slug to send instead. + * The type of Product: + * + * | type | description | + * |----| ----| + * | `product` | Represents a physical good | + * | `service` | Represents a service or virtual product | * - * example: - * product */ - actual_schema: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "ENTITY_NOT_CONDITIONAL"; - details: { + type?: "product" | "service"; /** - * The entity type the request addressed. - * example: - * price + * The product main name */ - schema: string; + name?: string; /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo + * The product categories */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_NOT_FOUND"; - details: { + categories?: string[]; + feature?: { + /** + * An arbitrary set of tags attached to a feature + */ + _tags?: string[]; + feature?: string; + }[]; /** - * The conditional entity the request addressed. - * example: - * price-sp26d1yo + * Stores references to products that can be cross sold with the current product. */ - entity_id: string; + cross_sellable_products?: { + $relation?: EntityRelation[]; + }; /** - * The variant the request addressed. - * example: - * var-46045 - */ - variant_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VERSION_NOT_FOUND"; - details: { + * Stores references to a set of file images of the product + */ + product_images?: /* Stores references to a set of file images of the product */ { + $relation?: EntityRelation[]; + } | File[]; /** - * The variant the request addressed. - * example: - * var-46045 + * Stores references to a set of files downloadable from the product. + * e.g: tech specifications, quality control sheets, privacy policy agreements + * + */ + product_downloads?: /** + * Stores references to a set of files downloadable from the product. + * e.g: tech specifications, quality control sheets, privacy policy agreements + * */ - variant_id: string; + { + $relation?: EntityRelation[]; + } | File[]; /** - * The version the request addressed, by the instant it takes effect from. - * example: - * 2027-01-01T00:00:00.000Z + * A set of [prices](/api/pricing#tag/simple_price_schema) or [composite prices](/api/pricing#tag/dynamic_price_schema) for the current product. */ - valid_from: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "NO_MATCHES"; - details: { + price_options?: { + $relation?: EntityRelation[]; + }; /** - * The entity type the request addressed. - * example: - * price + * Stores references to the availability files that define where this product is available. + * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. + * */ - schema: string; + _availability_files?: File[]; /** - * The conditional entity the resolve was scoped to. - * example: - * price-sp26d1yo + * The product id */ - entity_id: string; - }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "NO_ACTIVE_VERSION"; - details: { + _id?: string; /** - * The variant the request addressed. - * example: - * var-46045 + * The autogenerated product title */ - variant_id: string; + _title?: string; /** - * The instant a version in effect was asked for at. - * example: - * 2026-06-01T00:00:00.000Z + * The organization id the product belongs to + */ + _org_id?: string; + /** + * The product creation date + */ + _created_at?: string; + /** + * The product last update date */ - as_of: string; + _updated_at?: string; }; - /** - * Error message - */ - message: string; - /** - * The HTTP status code + external_fees_mappings?: /** + * example: + * [ + * { + * "price_id": "589B011B-F8D9-4F8E-AD71-BACE4B543C0F", + * "frequency_unit": "weekly", + * "amount_total": 1000, + * "amount_total_decimal": "10.00" + * } + * ] */ - status?: number; + ExternalFeeMappings; + external_fees_metadata?: ExternalFeeMetadata; + external_location_metadata?: /* The provider entity */ ExternalLocationMetadata; + external_price_metadata?: ExternalPriceMetadata; + _immutable_pricing_details?: /* The result from the calculation of a set of price items. */ PricingDetails; /** - * The cause of the error (visible for bad requests - http 400) + * The ids of the coupons applicable to the price item */ - cause?: string; + coupon_ids?: string[]; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The taxes applied to the price item. */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "AMBIGUOUS_RESOLUTION"; - details: { - /** - * Every variant that applied, each with the conditions it pins — which is what - * makes the overlap actionable: two variants both apply because their pins do - * not distinguish the context they were both asked about. - * - * Bounded by the same cap `TOO_MANY_MATCHES` reports, which is checked first, - * so this list is never longer than one response may carry. - * - */ - candidates: [ - { - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }, - { - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }, - ...{ - /** - * The candidate variant. - * example: - * var-46045 - */ - variant_id: string; - conditions: /** - * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a - * boolean `default` saying whether this is the entity's fallback. - * - * `default` is always present and always a boolean, so a client can branch on "did I get the - * fallback?" without knowing how one is stored. The reserved condition a fallback is actually - * pinned under never appears here. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - VariantConditions; - }[] - ]; - }; + taxes?: (/* A valid tax rate from a client. */ TaxAmountDto)[]; /** - * Error message + * The taxes applied to the price item. */ - message: string; + recurrences?: (/* An amount associated with a specific recurrence. */ RecurrenceAmountDto)[]; /** - * The HTTP status code + * The coupons applicable to the price item */ - status?: number; + _coupons?: (/* The shared properties for the coupon entity and coupon item entity */ CouponItem)[]; /** - * The cause of the error (visible for bad requests - http 400) + * The flag for prices that contain price components. */ - cause?: string; + is_composite_price: true; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * Contains price item configurations, per price component, when the main price item is a [composite price](/api/pricing#tag/dynamic_price_schema). */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "TUPLE_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The variant already holding the tuple, where the write read it back. - * - * example: - * var-50667 - */ - conflicting_variant_id?: string; - }; + item_components?: /* Represents a price input to the pricing library. */ PriceItemDto[]; /** - * Error message + * The ids of the price components that should be selected for the price calculation. */ - message: string; + selected_price_component_ids?: string[]; /** - * The HTTP status code + * The map of coupon ids applicable to the price components */ - status?: number; - /** - * The cause of the error (visible for bad requests - http 400) + price_component_coupon_ids?: { + [name: string]: string[]; + }; + _price?: /** + * The composite price entity + * example: + * { + * "_id": "c2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_title": "My Composite Price", + * "description": "My Composite Price", + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "is_composite_price": true, + * "price_components": { + * "$relation": [ + * { + * "entity_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 1, + * "item": { + * "_id": "comp1-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * }, + * { + * "entity_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "_schema": "price", + * "_product_id": "target-price-product-id", + * "quantity": 2, + * "item": { + * "_id": "comp2-2a95ca9-7a50-41a4-a73c-b5fb1a57d40f", + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "_schema": "price", + * "_title": "Test 1", + * "description": "Test 1", + * "tax": { + * "$relation": [ + * { + * "entity_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4" + * } + * ] + * }, + * "_org": "739224", + * "_created_at": "2022-02-18T10:10:26.439Z", + * "_updated_at": "2022-02-18T11:53:04.191Z", + * "active": true, + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "is_composite_price": false + * } + * } + * ] + * } + * } */ - cause?: string; + CompositePrice; + } + /** + * Echo of the request parameters used to compute the price, in the caller-facing shape. + */ + export interface ComputePriceInputs { + [name: string]: any; + type?: ProductCategory; + consumptionHT?: number; + consumptionNT?: number; + consumptionType?: ConsumptionTypeGetAg; + zipCode?: string; + city?: string; + providerId?: string; + billingPeriod?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; + referenceDate?: string; // date + } + /** + * The compute price payload + */ + export type ComputePriceParams = /* The compute price payload */ /* The compute price payload for power */ ComputePriceParamsPower | /* The compute price payload for gas */ ComputePriceParamsGas; + export interface ComputePriceParamsBase { /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The postal code to search for providers */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VERSION_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The instant already claimed by a version of that variant. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; + postal_code: string; /** - * Error message + * The consumption type */ - message: string; + consumption_type?: "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; /** - * The HTTP status code + * (DEPRECATED - use consumption_HT) The yearly consumption to compute the price in kWh */ - status?: number; + consumption?: number; /** - * The cause of the error (visible for bad requests - http 400) + * The yearly HT consumption to compute the price in kWh */ - cause?: string; + consumption_HT?: number; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The yearly NT consumption to compute the price in kWh */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CONDITION_UNDEFINED"; - details: { - /** - * The condition named by the request and absent from the schema. - * example: - * postal_code - */ - condition_name: string; - }; + consumption_NT?: number; /** - * Error message + * The association id */ - message: string; + association_id?: string; /** - * The HTTP status code + * The billing period (defaults to monthly) */ - status?: number; + billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; /** - * The cause of the error (visible for bad requests - http 400) + * The optional reference date for the price computation (ISO 8601 format) */ - cause?: string; + reference_date?: string; // date /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + * The city the postal code belongs to. Not used for price computation, + * only echoed back in `inputs` for display purposes. * */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "OPERATOR_UNSUPPORTED"; - details: { - /** - * example: - * postal_code - */ - condition_name: string; - /** - * The type the schema declares that condition with, which is what decides the - * operators it accepts. - * - * example: - * location - */ - condition_type: string; - /** - * The operator the context or filter asked for. - * example: - * between - */ - operator: string; - }; + city?: string; + } + /** + * The compute price payload for gas + */ + export interface ComputePriceParamsGas { /** - * Error message + * The postal code to search for providers */ - message: string; + postal_code: string; /** - * The HTTP status code + * The consumption type */ - status?: number; + consumption_type?: "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; /** - * The cause of the error (visible for bad requests - http 400) + * (DEPRECATED - use consumption_HT) The yearly consumption to compute the price in kWh */ - cause?: string; + consumption?: number; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The yearly HT consumption to compute the price in kWh */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CONTEXT_FORMAT_INVALID"; - details: { - /** - * example: - * postal_code - */ - condition_name: string; - /** - * What a value for that condition has to be, in prose. - * example: - * a postal code - */ - expected: string; - }; + consumption_HT?: number; /** - * Error message + * The yearly NT consumption to compute the price in kWh */ - message: string; + consumption_NT?: number; /** - * The HTTP status code + * The association id */ - status?: number; + association_id?: string; /** - * The cause of the error (visible for bad requests - http 400) + * The billing period (defaults to monthly) */ - cause?: string; + billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The optional reference date for the price computation (ISO 8601 format) */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + reference_date?: string; // date + /** + * The city the postal code belongs to. Not used for price computation, + * only echoed back in `inputs` for display purposes. * */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CONDITION_VALUE_INVALID"; - details: { - /** - * example: - * segment - */ - condition_name: string; - /** - * The value the write pinned, as it arrived. Declared without a type: the - * vocabulary holds strings, so anything else is out of it by definition and is - * reported as sent. - * - * example: - * industrial - */ - value: any; - /** - * The vocabulary *as enforced* — after the entries this deploy cannot read have - * been dropped, so a tenant whose `options` holds a title-only entry is told - * what the API actually checked against rather than what they believe they - * wrote. Empty when the condition declares no vocabulary at all, which is - * itself the reason the pin was refused; the message says which of the two - * (unconfigured, or unreadable) applies. - * - * example: - * [ - * "private", - * "commercial" - * ] - */ - options: string[]; - }; + city?: string; /** - * Error message + * The type of energy to compute the price */ - message: string; + type: "gas"; + concession_type?: /* The concession type for gas */ GasConcessionType; + } + /** + * The compute price payload for power + */ + export interface ComputePriceParamsPower { /** - * The HTTP status code + * The postal code to search for providers */ - status?: number; + postal_code: string; /** - * The cause of the error (visible for bad requests - http 400) + * The consumption type */ - cause?: string; + consumption_type?: "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * (DEPRECATED - use consumption_HT) The yearly consumption to compute the price in kWh */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "TOO_MANY_MATCHES"; - details: { - /** - * The most variants one resolve may compose. - * example: - * 100 - */ - limit: number; - }; + consumption?: number; /** - * Error message + * The yearly HT consumption to compute the price in kWh */ - message: string; + consumption_HT?: number; /** - * The HTTP status code + * The yearly NT consumption to compute the price in kWh */ - status?: number; + consumption_NT?: number; /** - * The cause of the error (visible for bad requests - http 400) + * The association id */ - cause?: string; + association_id?: string; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * - */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The billing period (defaults to monthly) */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "WRITE_CONFLICT"; - details: { - /** - * The variant the write addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the write addressed, where one was addressed. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from?: string; - /** - * The revision the write required the stored version to still be at. - * example: - * 3 - */ - expected_revision?: number; - /** - * The revision the version is actually at, where the failed write read it back. - * Absent when it could not be. - * - * example: - * 4 - */ - current_revision?: number; - }; + billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; /** - * Error message + * The optional reference date for the price computation (ISO 8601 format) */ - message: string; + reference_date?: string; // date /** - * The HTTP status code + * The city the postal code belongs to. Not used for price computation, + * only echoed back in `inputs` for display purposes. + * */ - status?: number; + city?: string; /** - * The cause of the error (visible for bad requests - http 400) + * The type of energy to compute the price */ - cause?: string; + type: "power"; + meter_type?: /* The meter type for power */ PowerMeterType; + } + export interface ComputePriceResult { /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The computed total price */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + amount_total: number; + /** + * The computed total price as decimal */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "OFFSET_WINDOW_EXCEEDED"; - details: { - /** - * The offset the request asked for. - * example: - * 24990 - */ - from: number; - /** - * The page size the request asked for, after clamping. Present because the two - * together are what exceeded the window — an offset inside it can still be - * refused for the page it would have to read. - * - * example: - * 25 - */ - size: number; - /** - * The last row this deploy's index will serve from an offset. Read it to size a - * page control, never to decide when to switch to the cursor — a caller can page - * on with `next` from any page. - * - * example: - * 25000 - */ - window: number; - }; + amount_total_decimal: string; /** - * Error message + * The computed static price */ - message: string; + amount_static?: number; /** - * The HTTP status code + * The computed static price as decimal */ - status?: number; + amount_static_decimal?: any; /** - * The cause of the error (visible for bad requests - http 400) + * The computed variable price, for the day period */ - cause?: string; + amount_variable_ht?: number; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The computed variable price, for the day period, as decimal */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + amount_variable_decimal_ht?: string; + /** + * The computed unit price, for the day period */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "CURSOR_INVALID"; - details: { - /** - * Which check the cursor failed, in prose. - * example: - * The cursor was issued for a different sort order - */ - reason: string; - }; + unit_amount_variable_ht?: number; /** - * Error message + * The computed unit price, for the day period, as decimal */ - message: string; + unit_amount_variable_decimal_ht?: string; /** - * The HTTP status code + * The computed variable price, for the night period */ - status?: number; + amount_variable_nt?: number; /** - * The cause of the error (visible for bad requests - http 400) + * The computed variable price, for the night period, as decimal */ - cause?: string; + amount_variable_decimal_nt?: string; + /** + * The computed unit price, for the night period + */ + unit_amount_variable_nt?: number; + /** + * The computed unit price, for the night period, as decimal + */ + unit_amount_variable_decimal_nt?: string; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + * The currency of the computed price (three-letter ISO currency code) + */ + currency: /* The currency of the computed price (three-letter ISO currency code) */ /** + * Three-letter ISO currency code, in lowercase. Must be a supported currency. + * ISO 4217 CURRENCY CODES as specified in the documentation: https://www.iso.org/iso-4217-currency-codes.html * + * example: + * EUR + */ + Currency; + /** + * The billing period */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + billing_period: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; + breakdown: /* Price breakdown */ ComputedPriceBreakdown; + /** + * A snapshot of the parameters this price was computed from, for display purposes + * (e.g. showing "computed for 3,500 kWh/year"). Included in the `_meta` signature. * */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { + inputs?: { [name: string]: any; - }[]; - } | { - code: "VARIANT_LIMIT_REACHED"; - details: { - /** - * Variants this entity already holds. - * example: - * 5000 - */ - variant_count: number; - /** - * Variants this entity may hold. Configurable per deploy, the same value for - * every organization on it. - * - * example: - * 5000 - */ - cap: number; + type?: ProductCategory; + consumptionHT?: number; + consumptionNT?: number; + consumptionType?: ConsumptionTypeGetAg; + zipCode?: string; + city?: string; + providerId?: string; + billingPeriod?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; + referenceDate?: string; // date }; + _meta?: /* Signature meta data payload */ SignatureMeta; + } + /** + * The computed price + */ + export interface ComputedBasePrice { /** - * Error message + * The computed price */ - message: string; + amount: number; /** - * The HTTP status code + * The computed price as decimal */ - status?: number; + amount_decimal: string; /** - * The cause of the error (visible for bad requests - http 400) + * The computed unit price */ - cause?: string; + unit_amount?: number; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + * The computed unit price as decimal */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + unit_amount_decimal?: string; + } + /** + * Price breakdown + */ + export interface ComputedPriceBreakdown { + static?: /* The computed price components */ ComputedPriceComponents; + variable?: /* The computed price components */ ComputedPriceComponents; + variable_ht?: /* The computed price components */ ComputedPriceComponents; + variable_nt?: /* The computed price components */ ComputedPriceComponents; + } + /** + * The computed price components + */ + export interface ComputedPriceComponents { + [name: string]: /* The computed price */ ComputedBasePrice; + } + /** + * One condition dimension, in the shape a schema's `conditions` array holds it — copy it in + * verbatim. + * + */ + export interface ConditionDefinition { + /** + * How variants and resolve contexts refer to this condition. Independent of attribute + * names: a value needed as an attribute too is duplicated onto the variant. * + * `default`, and any name beginning with `_`, are reserved for the server: a condition + * declared under one is ignored, since nothing could pin it and no context could address it. + * + * example: + * postal_code */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "PIN_FORMAT_INVALID"; - details: { - /** - * example: - * valid_period - */ - condition_name: string; - /** - * The type the schema declares that condition with, which is what decides the - * values it accepts. - * - * example: - * daterange - */ - condition_type: string; - /** - * What a pin for that condition has to be, in prose — the same field - * `CONTEXT_FORMAT_INVALID` carries, worded for the write side. It says what - * `condition_type` cannot: a `location` of format `zipcode` wants a postal code - * and one of format `zipcode_town` wants an object carrying both, and the type - * is `location` either way. - * - * example: - * an object carrying a from and an until date, either may be open - */ - expected: string; - /** - * The value the write pinned, as it arrived. Declared without a type, since - * what makes it invalid is that it is not of the condition's type. - * - * example: - * 2027-01-01/2027-12-31 - */ - value: any; - }; + name: string; /** - * Error message + * Human-readable name of the condition. + * example: + * Postal Code */ - message: string; - /** - * The HTTP status code + label: string; + type: /** + * The kind of value a condition holds, which decides how a variant's pinned value is matched + * against a resolve context. + * + * - `string`: an arbitrary string, matched exactly and case-sensitively + * - `number`: a numeric value + * - `date`: a single date + * - `daterange`: a window with a from and an until timestamp; both ends may be left open + * - `boolean`: a true/false value + * - `select`: one of the values declared in `options`, unless `allow_any` is set + * - `location`: a geographic value, shaped by `format` + * + * There is no condition type for the fallback variant. Being the entity's fallback is a + * property of the variant, set by the `default` flag on a variant write, and needs nothing + * declared in the schema. + * */ - status?: number; + ConditionType; /** - * The cause of the error (visible for bad requests - http 400) + * The declared vocabulary of a `select` condition. Absent for every other type. + * + * The same shape a `select` attribute's `options` has on the Entity API, item for item: an + * entry is either the value itself or an object carrying that value and an optional display + * `title`. A `title` is never pinned by a variant and never matched — two entries differing + * only in their title are one vocabulary entry. + * + * Enforced on variant writes, unless `allow_any` is true: a pinned value outside the + * vocabulary is rejected with `CONDITION_VALUE_INVALID`. It is *not* enforced on resolve — + * a vocabulary says what may be stored, not what may be asked for, so a context value + * outside it is a query that simply matches nothing. + * + * example: + * [ + * "private", + * "commercial" + * ] */ - cause?: string; + options?: ((string | null) | { + value: string; + title?: string; + })[]; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + * Allow arbitrary stored values in addition to the declared `options`. Absent means strict: + * a variant may only pin a declared option. * + * example: + * false */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. - * + allow_any?: boolean; + /** + * The value shape of a `location` condition. Absent for every other type. */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "VARIANT_UNPINNED"; - details: { - /** - * The conditional entity the item addressed. - * example: - * price-sp26d1yo - */ - entity_id: string; - }; + format?: "zipcode" | "zipcode + town"; + } + /** + * A named bundle of condition definitions, built in for one entity type. + */ + export interface ConditionSet { /** - * Error message + * Identifies the set within this entity type's catalog. + * example: + * delivery_area */ - message: string; + id: string; /** - * The HTTP status code + * Human-readable name of the set. + * example: + * Delivery Area */ - status?: number; + label: string; /** - * The cause of the error (visible for bad requests - http 400) + * What the set is for, and when to reach for it. */ - cause?: string; + description: string; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + * The condition definitions to copy into the schema's own `conditions` array. + */ + conditions: /** + * One condition dimension, in the shape a schema's `conditions` array holds it — copy it in + * verbatim. * */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + ConditionDefinition[]; + } + export interface ConditionSetCatalog { + /** + * The condition sets built in for the requested entity type, in the order they are offered. * */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - code: "LAST_VERSION_UNDELETABLE"; - details: { - /** - * The variant whose last version the delete addressed. - * example: - * var-46045 - */ - variant_id: string; - /** - * The version the delete addressed, by the instant it takes effect from. - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - }; + results: /* A named bundle of condition definitions, built in for one entity type. */ ConditionSet[]; + } + /** + * The kind of value a condition holds, which decides how a variant's pinned value is matched + * against a resolve context. + * + * - `string`: an arbitrary string, matched exactly and case-sensitively + * - `number`: a numeric value + * - `date`: a single date + * - `daterange`: a window with a from and an until timestamp; both ends may be left open + * - `boolean`: a true/false value + * - `select`: one of the values declared in `options`, unless `allow_any` is set + * - `location`: a geographic value, shaped by `format` + * + * There is no condition type for the fallback variant. Being the entity's fallback is a + * property of the variant, set by the `default` flag on a variant write, and needs nothing + * declared in the schema. + * + */ + export type ConditionType = "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"; + /** + * Schema slug of an entity type that can be conditional — the `{slug}` of every + * conditional-pricing route. + * + */ + export type ConditionalEntitySlug = "product" | "price" | "coupon"; + /** + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. + * Referenced only by the operations that emit these codes; every other operation + * keeps the plain `Error` shape. + * + */ + export interface ConditionalPricingError { /** * Error message */ @@ -10646,105 +4383,62 @@ declare namespace Components { */ cause?: string; /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + * The error message. Carries the same string as `message`, which the shared `Error` + * schema requires — `error` is the field responses have always used, and every caller + * to date reads. Declared here rather than on the shared `Error` because a request + * validation failure puts a list of validation errors in this field instead of a + * string, and those responses reference `Error` directly. * */ - error?: /** - * What went wrong, in the field responses have always used and every caller to date - * reads. Carries the same string as `message` — which the shared `Error` schema - * requires — except on a request-validation failure, which puts the list of validation - * errors here instead. + error?: string; + code?: /** + * Machine-readable failure mode of a conditional-pricing operation, allowing clients + * to branch on the kind of failure instead of parsing the error message. + * + * - `NOT_FOUND` (404): the addressed entity, variant or version does not exist + * - `AMBIGUOUS_RESOLUTION` (409): several variants match the given context while a single result was requested + * - `TUPLE_CONFLICT` (409): the condition tuple is already claimed by another variant + * - `VERSION_CONFLICT` (409): a version already exists at the given `valid_from` on that variant + * - `CONDITION_UNDEFINED` (400): the context names a condition the entity's schema does not define + * - `OPERATOR_UNSUPPORTED` (400): the requested operator is not applicable to the condition's type + * - `CONTEXT_FORMAT_INVALID` (400): a context value is malformed for its condition type + * - `CONDITION_VALUE_INVALID` (400): a variant write pins a `select` value the condition's declared `options` do not contain + * - `TOO_MANY_MATCHES` (400): a multi-match resolve exceeded its result cap + * - `WRITE_CONFLICT` (409): transient write contention, retryable unlike `TUPLE_CONFLICT` + * + * Each code is emitted with the HTTP status shown above, and only with that status. * */ - string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[] | string | { - [name: string]: any; - }[]; - } | { - /** - * Error message - */ - message: string; - /** - * The HTTP status code - */ - status?: number; + ConditionalPricingErrorCode; /** - * The cause of the error (visible for bad requests - http 400) - */ - cause?: string; - error?: /** - * The `error` field of an error response: the message, or — where the request itself failed - * validation before any handler ran — the validation errors themselves, which those 400s put - * here in place of a string. - * - * A conditional-pricing operation answers a body its schema rejects with the list, and - * everything else it refuses with the message. + * Structured data about the failure, shaped by the accompanying `code` + * (e.g. the candidate variants of an `ambiguous-resolution`). Only present + * when the failure has structured data to report, and never without a `code`. * */ - ReportedError; - }; + details?: { + [name: string]: any; + }; + } /** * Machine-readable failure mode of a conditional-pricing operation, allowing clients * to branch on the kind of failure instead of parsing the error message. * - * - `SCHEMA_NOT_FOUND` (404): no conditional entity type by that slug - * - `ENTITY_NOT_FOUND` (404): the schema holds no entity with that id - * - `ENTITY_TYPE_MISMATCH` (400): that id belongs to an entity of another type than the slug named - * - `ENTITY_NOT_CONDITIONAL` (400): the entity is of the right type but was not created as a conditional one - * - `VARIANT_NOT_FOUND` (404): the entity has no such variant - * - `VERSION_NOT_FOUND` (404): the variant has no version at that `valid_from` - * - `NO_MATCHES` (404): nothing applied to the context and the entity has no `default` variant - * - `NO_ACTIVE_VERSION` (404): the variant has no version in effect at the instant asked about + * - `NOT_FOUND` (404): the addressed entity, variant or version does not exist * - `AMBIGUOUS_RESOLUTION` (409): several variants match the given context while a single result was requested * - `TUPLE_CONFLICT` (409): the condition tuple is already claimed by another variant * - `VERSION_CONFLICT` (409): a version already exists at the given `valid_from` on that variant - * - `CONDITION_UNDEFINED` (400): a resolve context, a listing filter or a variant's pins name a condition the entity's schema does not define + * - `CONDITION_UNDEFINED` (400): the context names a condition the entity's schema does not define * - `OPERATOR_UNSUPPORTED` (400): the requested operator is not applicable to the condition's type - * - `CONTEXT_FORMAT_INVALID` (400): a resolve context or listing filter value is malformed for its condition type - * - `CONDITION_VALUE_INVALID` (400): a variant write pins a `select` value the condition's `options` do not admit, including every pin on a condition whose `options` are absent, empty or unreadable + * - `CONTEXT_FORMAT_INVALID` (400): a context value is malformed for its condition type + * - `CONDITION_VALUE_INVALID` (400): a variant write pins a `select` value the condition's declared `options` do not contain * - `TOO_MANY_MATCHES` (400): a multi-match resolve exceeded its result cap * - `WRITE_CONFLICT` (409): transient write contention, retryable unlike `TUPLE_CONFLICT` - * - `OFFSET_WINDOW_EXCEEDED` (400): a listing's `from` plus `size` reaches past the offset window the search index allows - * - `CURSOR_INVALID` (400): a paging cursor cannot be read, or does not belong to the read it was sent with - * - `VARIANT_LIMIT_REACHED` (400): the entity already holds every variant it may hold - * - `PIN_FORMAT_INVALID` (400): a variant pins a value malformed for its condition's type - * - `VARIANT_UNPINNED` (400): a variant write pins no condition and is not marked `default`, or a batch delete item addresses no variant - * - `LAST_VERSION_UNDELETABLE` (400): the delete would leave the variant with no version at all - * - * In a batch, the last four are the refusals an importer branches on: `VARIANT_LIMIT_REACHED` - * means stop the import, `PIN_FORMAT_INVALID` means one bad row, `LAST_VERSION_UNDELETABLE` - * means delete the variant instead. - * - * Not every refusal has a code. These carry a message and neither `code` nor `details`, and - * each operation's `400` names its own: a write pinning the reserved marker (`default` or - * `_default`), a variant marked `default` that also pins a real condition, a pin on a condition - * whose declared type this deploy cannot read, an id this store cannot key by, a `valid_from` - * this store cannot sort by, and a version write or delete with no `_revision`. Testing `code` - * for absence is how a client tells them from the coded failures. - * - * Four of the 404s say that something the request addressed does not exist, and are fixed by - * correcting an id or accepting the thing is gone. The other two say the opposite: everything - * addressed exists and there is still nothing to serve — no variant applies to this situation, - * or none of a variant's versions is in effect yet. Those are ordinary business outcomes, told - * apart from a wrong id by their code. * - * `ENTITY_TYPE_MISMATCH` and `ENTITY_NOT_CONDITIONAL` are `400`s, not 404s: the entity the - * request addressed **was** found, and the fix is the slug beside it. A slug that names no - * conditional entity type at all is a `400` too. - * - * Each code is emitted with the HTTP status shown above, and only with that status, and each - * one is pinned by a member of `ConditionalPricingError` — which is where the structured data - * that code carries is declared. + * Each code is emitted with the HTTP status shown above, and only with that status. * */ - export type ConditionalPricingErrorCode = "SCHEMA_NOT_FOUND" | "ENTITY_NOT_FOUND" | "ENTITY_TYPE_MISMATCH" | "ENTITY_NOT_CONDITIONAL" | "VARIANT_NOT_FOUND" | "VERSION_NOT_FOUND" | "NO_MATCHES" | "NO_ACTIVE_VERSION" | "AMBIGUOUS_RESOLUTION" | "TUPLE_CONFLICT" | "VERSION_CONFLICT" | "CONDITION_UNDEFINED" | "OPERATOR_UNSUPPORTED" | "CONTEXT_FORMAT_INVALID" | "CONDITION_VALUE_INVALID" | "TOO_MANY_MATCHES" | "WRITE_CONFLICT" | "OFFSET_WINDOW_EXCEEDED" | "CURSOR_INVALID" | "VARIANT_LIMIT_REACHED" | "PIN_FORMAT_INVALID" | "VARIANT_UNPINNED" | "LAST_VERSION_UNDELETABLE"; + export type ConditionalPricingErrorCode = "NOT_FOUND" | "AMBIGUOUS_RESOLUTION" | "TUPLE_CONFLICT" | "VERSION_CONFLICT" | "CONDITION_UNDEFINED" | "OPERATOR_UNSUPPORTED" | "CONTEXT_FORMAT_INVALID" | "CONDITION_VALUE_INVALID" | "TOO_MANY_MATCHES" | "WRITE_CONFLICT"; export type ConsumptionTypeGetAg = "household" | "heating_pump" | "night_storage_heating" | "night_storage_heating_common_meter"; /** * The coupon entity @@ -10830,12 +4524,6 @@ declare namespace Components { Currency; cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; active?: boolean; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Whether the coupon requires a promo code to be applied */ @@ -10947,12 +4635,6 @@ declare namespace Components { Currency; cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; active?: boolean; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Whether the coupon requires a promo code to be applied */ @@ -11042,12 +4724,6 @@ declare namespace Components { Currency; cashback_period?: /* The cashback period, for now it's limited to either 0 months or 12 months */ CashbackPeriod; active?: boolean; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Whether the coupon requires a promo code to be applied */ @@ -11094,15 +4770,14 @@ declare namespace Components { * context says for it, which is what makes adding a condition to a schema non-breaking for the * variants that already exist. * - * Exact values only. A predicate is a read-side thing — a resolve context or a listing's - * condition filter — and is never stored: what a variant applies to is one situation, not a - * range of them. + * Exact values only. Predicates are accepted in a resolve context and nowhere else, so that + * matching is decided in exactly one place. * * Values are typed by their condition and stored canonicalized for that type: a `date` becomes * millisecond-precision UTC, a `daterange` an object carrying `from` and `until` where an empty * string is an open end, a `location` of format `zipcode` the postal code itself and one of - * format `zipcode_town` an object carrying both. A `select` value must be a string, and must - * be one the condition's `options` declare, which is always a closed vocabulary. + * format `zipcode + town` an object carrying both. A `select` value must be a string, and must + * be one the condition's `options` declare unless it sets `allow_any`. * * `default`, and any name beginning with `_`, are reserved for the server and cannot be pinned * here. Whether a variant is the entity's fallback is set through the request's `default` flag. @@ -11116,11 +4791,14 @@ declare namespace Components { /** * Mark this variant as the entity's fallback: the one served when no other variant applies. * - * A property of the variant, never an entry in `conditions`. A default variant cannot pin - * anything else, and an entity can have at most one; a second is refused as - * `TUPLE_CONFLICT`. + * A property of the variant, never an entry in `conditions` — a variant claiming a value for + * the marker would hold a real condition tuple while being permanently unmatchable, since no + * resolve context ever supplies it. A default variant cannot pin anything else, and an + * entity can have at most one. * * Available to every conditional entity: nothing has to be declared in the schema first. + * The variant is stored pinning one reserved condition, which is what makes the ordinary + * condition-tuple guard enforce at-most-one-per-entity with no rule of its own. * */ default?: boolean; @@ -11128,7 +4806,8 @@ declare namespace Components { * When the first version takes effect. Defaults to now. * * An RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time - * (`2026-01-01T00:00:00Z`), to at most millisecond precision. + * (`2026-01-01T00:00:00Z`), to at most millisecond precision. Deliberately not declared as + * `format: date-time`, which would reject the plain-date form that this accepts. * * example: * 2027-01-01T00:00:00Z @@ -11138,26 +4817,19 @@ declare namespace Components { * The attribute values this version overrides on the base entity, keyed by attribute name. * * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. + * (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable + * attributes present here are ignored rather than rejected, so a client working from a slightly + * stale schema snapshot still succeeds instead of failing on fields it could not have known to + * drop. An attribute's `render_condition` says when to show it and has no bearing on whether a + * variant may override it. * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. + * Ignored means *not updated*, never *removed*: a value already stored for an attribute that is + * not currently overridable is preserved, so removing and restoring the flag deactivates and + * then reactivates the same override. * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. + * A composite price's `price_components` is an ordinary overridable relation attribute: a + * composite variant pins its component variants here the same way any other relation value is + * set, with no special handling. * * example: * { @@ -11169,8 +4841,9 @@ declare namespace Components { } export interface CreatedVariant { /** - * Server-generated, always, and never accepted from a client. This is the durable key orders - * and contracts pin. + * Server-generated, always. This is the durable key orders and contracts pin, so it is never + * accepted from a client — a client-suppliable id would risk collisions between independent + * importers. * * example: * var-46045 @@ -11211,26 +4884,19 @@ declare namespace Components { * The attribute values this version overrides on the base entity, keyed by attribute name. * * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. + * (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable + * attributes present here are ignored rather than rejected, so a client working from a slightly + * stale schema snapshot still succeeds instead of failing on fields it could not have known to + * drop. An attribute's `render_condition` says when to show it and has no bearing on whether a + * variant may override it. * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. + * Ignored means *not updated*, never *removed*: a value already stored for an attribute that is + * not currently overridable is preserved, so removing and restoring the flag deactivates and + * then reactivates the same override. * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. + * A composite price's `price_components` is an ordinary overridable relation attribute: a + * composite variant pins its component variants here the same way any other relation value is + * set, with no special handling. * * example: * { @@ -11248,7 +4914,8 @@ declare namespace Components { */ _updated_at: string; /** - * The revision a later write to this version must carry to be accepted. + * The revision a later write to this version must carry to be accepted. Genuinely current, + * unlike one read back later from an eventually-consistent read. * */ _revision: number; @@ -11257,17 +4924,7 @@ declare namespace Components { * reads its length rather than branching on its absence. * */ - warnings: /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. - * - */ - WriteWarning[]; + warnings: VariantWriteWarning[]; } /** * Three-letter ISO currency code, in lowercase. Must be a supported currency. @@ -11351,21 +5008,16 @@ declare namespace Components { */ valid_from: string; /** - * What the delete moved, if anything. Empty when a scheduled version was withdrawn — a - * client reads its length rather than branching on its absence. - * + * What the delete moved, if anything. Empty when a scheduled version was withdrawn. */ warnings: /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. + * Something a version write moved. A version write is never refused for being late — backdating a + * version, and editing or deleting one that has already been superseded, are both accepted — so + * what a caller gets instead is a warning naming exactly what changed. One write can carry both + * codes. * */ - WriteWarning[]; + VersionWriteWarning[]; } export interface DiscountAmounts { /** @@ -11804,10 +5456,24 @@ declare namespace Components { */ billing_period: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; breakdown: /* Price breakdown */ ComputedPriceBreakdown; - _meta?: /* Signature meta data payload */ SignatureMeta; + /** + * A snapshot of the parameters this price was computed from, for display purposes + * (e.g. showing "computed for 3,500 kWh/year"). Included in the `_meta` signature. + * + */ inputs?: { [name: string]: any; + type?: ProductCategory; + consumptionHT?: number; + consumptionNT?: number; + consumptionType?: ConsumptionTypeGetAg; + zipCode?: string; + city?: string; + providerId?: string; + billingPeriod?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly" | "one_time"; + referenceDate?: string; // date }; + _meta?: /* Signature meta data payload */ SignatureMeta; } /** * The provider entity @@ -12122,12 +5788,6 @@ declare namespace Components { * The flag for prices that contain price components. */ is_composite_price: true; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * The price creation date */ @@ -12153,73 +5813,6 @@ declare namespace Components { */ _tags?: string[]; } - /** - * One override that did not apply, and why. - * - * The same entry on both sides of the feature: a write reports the attributes in its body it did - * not store, and a resolved payload reports the stored overrides composition did not apply. Those - * are the same fact observed at two moments, so a client learns one shape and reads it in both - * places. - * - */ - export interface InertOverride { - /** - * The attribute's name, as the request body or the stored version spells it. - * example: - * unit_amount - */ - attribute: string; - reason: /** - * Why one override did not apply. - * - * - `ATTRIBUTE_NOT_OVERRIDABLE`: the entity's schema declares the attribute but has not granted - * it `overridable_attribute`. Granting the flag is an ordinary schema edit, which makes this - * the reason most often worth acting on. - * - `ATTRIBUTE_READONLY`: the attribute is declared readonly, and a readonly attribute cannot - * be granted the flag. - * - `ATTRIBUTE_HIDDEN`: the attribute is declared hidden, and a hidden attribute cannot be - * granted the flag. - * - `ATTRIBUTE_COMPUTED`: the attribute's value is derived (`type: computed` or - * `computed: true`) rather than stored, so an override would be recomputed away. - * - `ATTRIBUTE_UNDECLARED`: the entity's schema declares no attribute of that name. On a write - * that is usually a typo; on a resolved payload it is a stored override whose attribute has - * since left the schema — a stored value outlives the flag being withdrawn, so it can outlive - * its own attribute too. This API keeps no record of what a schema once declared, so it states - * only the observable fact and does not distinguish the two. - * - `TYPE_NOT_OVERRIDABLE`: the attribute's type is not one a variant may override, whatever - * the schema says about that particular attribute. - * - `CAPABILITY_NOT_OVERRIDABLE`: the attribute is contributed by a capability rather than - * declared on the entity's schema. Published for completeness and not emitted in this version, - * in which no capability attribute can be overridden at all. - * - */ - InertOverrideReason; - } - /** - * Why one override did not apply. - * - * - `ATTRIBUTE_NOT_OVERRIDABLE`: the entity's schema declares the attribute but has not granted - * it `overridable_attribute`. Granting the flag is an ordinary schema edit, which makes this - * the reason most often worth acting on. - * - `ATTRIBUTE_READONLY`: the attribute is declared readonly, and a readonly attribute cannot - * be granted the flag. - * - `ATTRIBUTE_HIDDEN`: the attribute is declared hidden, and a hidden attribute cannot be - * granted the flag. - * - `ATTRIBUTE_COMPUTED`: the attribute's value is derived (`type: computed` or - * `computed: true`) rather than stored, so an override would be recomputed away. - * - `ATTRIBUTE_UNDECLARED`: the entity's schema declares no attribute of that name. On a write - * that is usually a typo; on a resolved payload it is a stored override whose attribute has - * since left the schema — a stored value outlives the flag being withdrawn, so it can outlive - * its own attribute too. This API keeps no record of what a schema once declared, so it states - * only the observable fact and does not distinguish the two. - * - `TYPE_NOT_OVERRIDABLE`: the attribute's type is not one a variant may override, whatever - * the schema says about that particular attribute. - * - `CAPABILITY_NOT_OVERRIDABLE`: the attribute is contributed by a capability rather than - * declared on the entity's schema. Published for completeness and not emitted in this version, - * in which no capability attribute can be overridden at all. - * - */ - export type InertOverrideReason = "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"; /** * The auth credentials for external integrations */ @@ -12297,120 +5890,6 @@ declare namespace Components { }; }[]; } - /** - * How to narrow and page a variant listing. Every property is optional, so `{}` is a valid body - * and asks for the first ten variants of the entity in `variant_id` order — the body itself is - * required, and an omitted one is a request-validation `400` rather than an unnarrowed page. - * - * `conditions` and `search` narrow independently and a variant has to satisfy both. - * - */ - export interface ListVariantsRequest { - conditions?: /** - * Which pins a variant must carry to be listed: a flat map keyed by condition name, as the - * entity's schema declares them. A condition left out of the map is not filtered on at all. - * - * Each value is either an exact value, typed by its condition, or a single-operator predicate - * object — the same seven a resolve context accepts, because in both cases a predicate is - * applied to the variant's *pinned* value, so nothing about matching moves: - * - * - `{ "lt": v }`, `{ "lte": v }`, `{ "gt": v }`, `{ "gte": v }` — order against a `number` or - * `date` condition. - * - `{ "in": [...] }` — membership, against a `string`, `select` or `number` condition. - * - `{ "between": "2026-03-01" }` — the explicit spelling of `daterange` containment; a plain - * date supplied for a `daterange` condition means the same thing. - * - `{ "exists": true }` — pinned to any value. `{ "exists": false }` — the condition left - * unpinned. - * - * An `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To - * filter on a condition whatever its pinned value, send `{ "exists": true }` rather than - * enumerating its vocabulary. - * - * **A variant matches only where it pins the condition** — the one place a filter and a resolve - * context differ. On `:resolve` a condition a variant does not pin matches any value; here, - * asking for postal code 46045 does not return the variants that pin no postal code at all. - * `{ "exists": false }` is how those are asked for. - * - * Values are typed and canonicalized exactly as a resolve context's are, by the same code, so - * one instant written two ways filters the same way either way. A condition the schema does not - * declare is `CONDITION_UNDEFINED`, a predicate its type does not support is - * `OPERATOR_UNSUPPORTED`, and a value malformed for its type is `CONTEXT_FORMAT_INVALID`. - * - * **`default` is accepted here**, as the exact boolean every row reports it as: `true` selects - * the entity's fallback variant, `false` every variant that is not it. - * - * It takes no predicate. `default` is not a condition and has no type, so ordering and - * membership have nothing to apply to. It is also the one key the pinned-only rule above does - * not describe literally: a variant that is not the fallback does not pin the marker to `false`, - * it does not pin it at all, so `false` selects the variants that leave it unpinned. - * - * Names beginning with `_` stay reserved for the server and cannot be filtered on — `_default`, - * the marker a fallback is actually stored under, included. `default` is the spelling every read - * reports and the only one this accepts. - * - * example: - * { - * "postal_code": "46045", - * "consumption": { - * "lt": 5000 - * } - * } - */ - VariantConditionFilter; - /** - * Free text matched against the variant's pinned values — how someone finds one postal code - * among 800,000. - * - * Matches `string`, `select` and `number` pins only. A `location` pin is stored as an array - * of its format's parts and a `daterange` pin as an object carrying `from` and `until`, so - * neither is text a user could have typed. - * - * example: - * 460 - */ - search?: string; - /** - * `conditions.:asc` or `conditions.:desc`, for a `string`, `select`, `number` or - * `date` pin. Anything else — another field, or a pin of another type — is a `400`. - * - * **`variant_id:asc` is appended by the server**, always, so the order is total: many - * variants can pin one postal code, and without a tiebreaker a cursor would repeat or skip - * rows between pages. Asking for no sort is `variant_id:asc` alone. - * - * example: - * conditions.postal_code:asc - */ - sort?: string; - /** - * The offset to read from. Not read when a `cursor` is sent, which carries its own position. - * - * Bounded by the search index's offset window, together with `size`: the window bounds the - * last row a page may contain, so the final servable offset is the window minus the page - * size. A page reaching past it is `OFFSET_WINDOW_EXCEEDED`, naming all three numbers, - * rather than a page clamped back inside it as entity listing does. The window is the - * deploy's: read its size from the error, not from here. - * - */ - from?: number; - /** - * Rows per page. Clamped silently at 1000, as entity listing's is. - * - */ - size?: number; - /** - * Continue from a previous response's `next`, which is where a caller goes when the offset - * window runs out. Opaque: it encodes the position and the listing it was issued for, and - * nothing a client should read or construct. - * - * `conditions`, `search` and `sort` must be the ones the cursor was issued with — a cursor - * resumes one listing, and cannot mean anything against a different one. A cursor that is - * malformed, or does not match the listing it is sent with, is a `400`. - * - * example: - * eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0 - */ - cursor?: string; - } /** * Market participant data */ @@ -12609,12 +6088,6 @@ declare namespace Components { * The flag for prices that contain price components. */ is_composite_price: true; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * The price creation date */ @@ -13819,7 +7292,7 @@ declare namespace Components { valid_from?: string; /** * Optional, and never applied. A partial update that tries to change a pinned condition value - * is refused. + * is refused — this is the path that rule is most likely to be broken on by accident. * * example: * { @@ -13852,15 +7325,14 @@ declare namespace Components { * context says for it, which is what makes adding a condition to a schema non-breaking for the * variants that already exist. * - * Exact values only. A predicate is a read-side thing — a resolve context or a listing's - * condition filter — and is never stored: what a variant applies to is one situation, not a - * range of them. + * Exact values only. Predicates are accepted in a resolve context and nowhere else, so that + * matching is decided in exactly one place. * * Values are typed by their condition and stored canonicalized for that type: a `date` becomes * millisecond-precision UTC, a `daterange` an object carrying `from` and `until` where an empty * string is an open end, a `location` of format `zipcode` the postal code itself and one of - * format `zipcode_town` an object carrying both. A `select` value must be a string, and must - * be one the condition's `options` declare, which is always a closed vocabulary. + * format `zipcode + town` an object carrying both. A `select` value must be a string, and must + * be one the condition's `options` declare unless it sets `allow_any`. * * `default`, and any name beginning with `_`, are reserved for the server and cannot be pinned * here. Whether a variant is the entity's fallback is set through the request's `default` flag. @@ -13873,40 +7345,6 @@ declare namespace Components { export interface PinnedConditions { [name: string]: any; } - /** - * The options a pinned resolve accepts — `hydrate` and nothing else. `resolve_one` has nothing - * to change on this branch, where the answer is exactly one result or a 404, so a body sending - * it is a validation `400`. `hydrate` means what `ResolveOptions.hydrate` means. - * - */ - export interface PinnedResolveOptions { - /** - * Return the entities a relation attribute references in place of the references - * themselves, one level deep, exactly as an entity read with hydration does. - * - * A fetch, not a second resolution: a referenced entity comes back as it is read, and one - * that is itself conditional carries its own flag — acting on that is the consumer's - * choice, and this API does not resolve it on their behalf. - * - * Applied after composition, so a relation attribute whose value this variant's version - * replaced is hydrated too. That is what makes a composite price work: the override - * references different component *entities*, which exist only in the composed payload. - * - * A reference that cannot be fetched comes back exactly as entity hydration returns it — - * no drop, no failure, and no field reporting it. A resolved payload behaves as an entity - * of the same shape would, and the discriminators are the only difference. - * - * Costs one fetch per referenced entity per result, and carries no cap of its own: the - * per-attribute limits are entity hydration's, and the 100-result cap on the resolve itself - * is unchanged. - * - * **Published ahead of the behaviour.** Until hydration is built, `true` is answered `501` - * rather than served as unhydrated references; `false`, which asks for what this path - * already does, resolves normally. - * - */ - hydrate?: boolean; - } export interface PortalContext { [name: string]: any; /** @@ -14057,12 +7495,6 @@ declare namespace Components { * The flag for prices that contain price components. */ is_composite_price?: false; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Describes how to compute the price per period. Either `per_unit`, `tiered_graduated` or `tiered_volume`. * - `per_unit` indicates that the fixed amount (specified in unit_amount or unit_amount_decimal) will be charged per unit in quantity @@ -14748,12 +8180,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -15152,12 +8578,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -15330,12 +8750,6 @@ declare namespace Components { * The flag for prices that contain price components. */ is_composite_price?: false; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Describes how to compute the price per period. Either `per_unit`, `tiered_graduated` or `tiered_volume`. * - `per_unit` indicates that the fixed amount (specified in unit_amount or unit_amount_decimal) will be charged per unit in quantity @@ -16185,12 +9599,6 @@ declare namespace Components { price_options?: { $relation?: EntityRelation[]; }; - /** - * The flag for entities whose values vary by context. Resolve the values that apply with - * `POST /v1/conditional-pricing:resolve`. - * - */ - is_conditional?: boolean; /** * Stores references to the availability files that define where this product is available. * These files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block. @@ -16408,6 +9816,179 @@ declare namespace Components { * } */ ProductRecommendation[]; + /** + * Context about what the recommendations were searched against. + */ + source?: { + /** + * The first line item of the contract used as source for the recommendation. + * Carries the amounts the customer currently pays; only present when searching by contract_id. + * + */ + item?: /** + * The first line item of the contract used as source for the recommendation. + * Carries the amounts the customer currently pays; only present when searching by contract_id. + * + */ + /** + * Represents a price item + * example: + * { + * "amount_subtotal": 10000, + * "amount_total": 10600, + * "currency": "EUR", + * "description": "Annual internet service", + * "price_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "product_id": "6241487f-b7fd-428b-ab92-24ee0b37fd84", + * "taxes": [ + * { + * "amount": 600, + * "tax": { + * "active": true, + * "description": "Without Behaviour", + * "rate": 6, + * "region": "DE", + * "type": "VAT", + * "_created_at": "2022-02-07T14:49:08.831Z", + * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", + * "_org": "739224", + * "_schema": "tax", + * "_title": "Tax Without Behaviour", + * "_updated_at": "2022-02-07T14:49:08.831Z" + * } + * }, + * { + * "amount": 600, + * "tax": { + * "active": true, + * "description": "Without Behaviour", + * "rate": 6, + * "region": "DE", + * "type": "VAT", + * "_created_at": "2022-02-07T14:49:08.831Z", + * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", + * "_org": "739224", + * "_schema": "tax", + * "_title": "Tax Without Behaviour", + * "_updated_at": "2022-02-07T14:49:08.831Z" + * } + * } + * ], + * "unit_amount": 10000, + * "unit_amount_net": 10000, + * "pricing_model": "per_unit", + * "_price": { + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Solar Panel Module", + * "description": "Solar Panel Module", + * "active": true, + * "tax": { + * "$relation": [ + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * }, + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * } + * ] + * }, + * "_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "_org": "728", + * "_created_at": "2022-06-03T16:04:10.369Z", + * "_updated_at": "2022-06-03T16:04:10.369Z", + * "pricing_model": "per_unit" + * }, + * "_product": { + * "name": "Cool box", + * "type": "product", + * "_id": "73f857a4-0fbc-4aa6-983f-87c0d6d410a6", + * "_title": "Cool box" + * } + * } + */ + PriceItem | /** + * Represents a composite price input to the pricing library. + * example: + * { + * "amount_subtotal": 10000, + * "amount_total": 10600, + * "currency": "EUR", + * "description": "Annual internet service", + * "price_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "product_id": "6241487f-b7fd-428b-ab92-24ee0b37fd84", + * "taxes": [ + * { + * "amount": 600, + * "tax": { + * "active": true, + * "description": "Without Behaviour", + * "rate": 6, + * "region": "DE", + * "type": "VAT", + * "_created_at": "2022-02-07T14:49:08.831Z", + * "_id": "18bbbc2e-2c37-4f91-924a-07ae60d830e4", + * "_org": "739224", + * "_schema": "tax", + * "_title": "Tax Without Behaviour", + * "_updated_at": "2022-02-07T14:49:08.831Z" + * } + * } + * ], + * "unit_amount": 10000, + * "unit_amount_net": 10000, + * "pricing_model": "per_unit", + * "_price": { + * "unit_amount": 10000, + * "unit_amount_currency": "EUR", + * "unit_amount_decimal": "100.00", + * "sales_tax": "standard", + * "is_tax_inclusive": false, + * "price_display_in_journeys": "show_price", + * "type": "one_time", + * "billing_period": "weekly", + * "billing_duration_unit": "months", + * "notice_time_unit": "months", + * "termination_time_unit": "months", + * "renewal_duration_unit": "months", + * "_schema": "price", + * "_title": "Solar Panel Module", + * "description": "Solar Panel Module", + * "active": true, + * "tax": { + * "$relation": [ + * { + * "entity_id": "24641e82-0690-4135-8b43-ef12a9b1c5dc" + * } + * ] + * }, + * "_id": "7e24ff5d-d580-4136-a32f-19191eed039a", + * "_org": "728", + * "_created_at": "2022-06-03T16:04:10.369Z", + * "_updated_at": "2022-06-03T16:04:10.369Z", + * "pricing_model": "per_unit" + * }, + * "_product": { + * "name": "Cool box", + * "type": "product", + * "_id": "73f857a4-0fbc-4aa6-983f-87c0d6d410a6", + * "_title": "Cool box" + * } + * } + */ + CompositePriceItem; + }; } /** * Product recommendations request payload @@ -16772,8 +10353,10 @@ declare namespace Components { * The complete set of attribute overrides this version carries. An overridable attribute * absent from here stops being overridden. * - * Attributes the variant may not override are not applied where this carries them, and - * their **stored value is kept rather than dropped**. + * Attributes the variant may not override are ignored where this carries them, and their + * **stored value is kept rather than dropped** — otherwise a routine full-snapshot write + * would erase an override the moment its attribute's `overridable_attribute`, `readonly` or + * `hidden` flag happened to be off. * * example: * { @@ -16788,6 +10371,10 @@ declare namespace Components { * The revision marker read from the version being written. The write is refused with * `WRITE_CONFLICT` if the version has been written since. * + * Required rather than optional: an optional one is a guarantee every client can opt out of + * by forgetting a field, and the write it protects is the one that overwrites somebody + * else's edit. + * * example: * 3 */ @@ -16813,33 +10400,7 @@ declare namespace Components { [name: string]: any; }; } - /** - * The `error` field of an error response: the message, or — where the request itself failed - * validation before any handler ran — the validation errors themselves, which those 400s put - * here in place of a string. - * - * A conditional-pricing operation answers a body its schema rejects with the list, and - * everything else it refuses with the message. - * - */ - export type ReportedError = /** - * The `error` field of an error response: the message, or — where the request itself failed - * validation before any handler ran — the validation errors themselves, which those 400s put - * here in place of a string. - * - * A conditional-pricing operation answers a body its schema rejects with the list, and - * everything else it refuses with the message. - * - */ - string | { - [name: string]: any; - }[]; - /** - * Resolve by matching a situation: which of this entity's variants apply to `context`, each - * composed with the version in effect at `as_of`. - * - */ - export interface ResolveByContextRequest { + export interface ResolveConditionalEntityRequest { schema: /** * Schema slug of an entity type that can be conditional — the `{slug}` of every * conditional-pricing route. @@ -16852,7 +10413,7 @@ declare namespace Components { * price-sp26d1yo */ entity_id: string; - context: /** + context?: /** * The situation to resolve for: a flat map keyed by condition name, as the entity's schema * declares them. A condition left out of the map is not a wildcard — it matches only variants * that leave that condition unpinned. @@ -16868,22 +10429,14 @@ declare namespace Components { * - `{ "exists": true }` — pinned to any value. `{ "exists": false }` says what leaving the key * out says. * - * An `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To match - * a condition whatever its value, send `{ "exists": true }` rather than enumerating its - * vocabulary. - * * Exact values are typed by their condition: a `string` or `select` matches exactly and * case-sensitively, with no trimming; a `location` of format `zipcode` is the postal code - * itself, and one of format `zipcode_town` an object carrying both, whose town is compared + * itself, and one of format `zipcode + town` an object carrying both, whose town is compared * case- and whitespace-insensitively while its postal code is not. * * `default`, and any name beginning with `_`, are reserved for the server and cannot be * supplied here. * - * An empty map is valid and means what it says: it supplies no value, so it matches no variant - * that pins a condition, and the entity's `default` variant is what comes back. It is the only way to - * ask for the default variant without knowing its id. - * * example: * { * "postal_code": "46045", @@ -16898,115 +10451,16 @@ declare namespace Components { * before it. Defaults to now. A variant whose first version is later than this is * scheduled rather than applicable, and is excluded from resolution entirely. * - * That exclusion belongs to context matching only: a set of results may quietly drop a - * member, where a pin naming one variant cannot answer with silence and is told - * `NO_ACTIVE_VERSION` instead. - * - * An RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time - * (`2026-01-01T00:00:00Z`), to at most millisecond precision. - * - * example: - * 2027-03-15T00:00:00Z - */ - as_of?: string; - options?: /* The options a context resolve accepts. A pin takes `PinnedResolveOptions` instead. */ ResolveOptions; - } - /** - * Resolve by naming a variant: compose this one, whatever a context would have matched. What an - * order needs to show the numbers a customer agreed to, and what a contract needs to show what - * is billable now — the two differ only in whether `as_of` is supplied. - * - */ - export interface ResolveByPinRequest { - schema: /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - ConditionalEntitySlug; - /** - * The conditional entity to resolve. Resolution is always scoped to exactly one. - * example: - * price-sp26d1yo - */ - entity_id: string; - /** - * The variant to compose. Condition matching is skipped entirely: no `context` is read, the - * `default` fallback does not apply, and `results` carries exactly one entry — a pin asks - * for one variant by name. - * - * A `variant_id` this entity has no variant under is `VARIANT_NOT_FOUND`, and so is one - * naming a variant of a different entity: a variant id alone addresses nothing. - * `SCHEMA_NOT_FOUND` and `ENTITY_NOT_FOUND` are still answered ahead of both. - * - * **Published ahead of the behaviour.** Until the pinned path is built, a body carrying - * this field is answered `501`, ahead of every check above — the field exists so consumers - * can build against it, and declining it is how a deployed stage says so rather than - * quietly returning the `default` variant. - * - * example: - * var-46045 - */ - variant_id: string; - /** - * The instant the version is selected at — the version with the latest `valid_from` at or - * before it. Defaults to now. The same selector, by the same rule, as on a context resolve: - * how the variant was chosen is orthogonal to which of its versions applies, so a caller - * replaying a recorded resolution instant supplies it here. - * - * A pinned variant whose first version is later than this is `NO_ACTIVE_VERSION`, carrying - * the instant in `details.as_of`, rather than being dropped the way context matching drops - * a scheduled variant. - * * An RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time - * (`2026-01-01T00:00:00Z`), to at most millisecond precision. + * (`2026-01-01T00:00:00Z`), to at most millisecond precision. Deliberately not declared as + * `format: date-time`, which would reject the plain-date form that this accepts. * * example: * 2027-03-15T00:00:00Z */ as_of?: string; - options?: /** - * The options a pinned resolve accepts — `hydrate` and nothing else. `resolve_one` has nothing - * to change on this branch, where the answer is exactly one result or a 404, so a body sending - * it is a validation `400`. `hydrate` means what `ResolveOptions.hydrate` means. - * - */ - PinnedResolveOptions; + options?: ResolveOptions; } - /** - * A resolve names one conditional entity, then says which of its variants it means — one of two - * ways, and never both. `context` describes a situation and asks which variants apply to it; - * `variant_id` names one variant and skips matching entirely. - * - * A body carrying both, or neither, is a validation `400`. Asking for the default variant - * without knowing its id is `context: {}`, which matches nothing and therefore falls back to it. - * - * Everything below the variant selection is the same on both branches, `as_of` included. - * - */ - export type ResolveConditionalEntityRequest = /** - * A resolve names one conditional entity, then says which of its variants it means — one of two - * ways, and never both. `context` describes a situation and asks which variants apply to it; - * `variant_id` names one variant and skips matching entirely. - * - * A body carrying both, or neither, is a validation `400`. Asking for the default variant - * without knowing its id is `context: {}`, which matches nothing and therefore falls back to it. - * - * Everything below the variant selection is the same on both branches, `as_of` included. - * - */ - /** - * Resolve by matching a situation: which of this entity's variants apply to `context`, each - * composed with the version in effect at `as_of`. - * - */ - ResolveByContextRequest | /** - * Resolve by naming a variant: compose this one, whatever a context would have matched. What an - * order needs to show the numbers a customer agreed to, and what a contract needs to show what - * is billable now — the two differ only in whether `as_of` is supplied. - * - */ - ResolveByPinRequest; /** * The situation to resolve for: a flat map keyed by condition name, as the entity's schema * declares them. A condition left out of the map is not a wildcard — it matches only variants @@ -17023,22 +10477,14 @@ declare namespace Components { * - `{ "exists": true }` — pinned to any value. `{ "exists": false }` says what leaving the key * out says. * - * An `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To match - * a condition whatever its value, send `{ "exists": true }` rather than enumerating its - * vocabulary. - * * Exact values are typed by their condition: a `string` or `select` matches exactly and * case-sensitively, with no trimming; a `location` of format `zipcode` is the postal code - * itself, and one of format `zipcode_town` an object carrying both, whose town is compared + * itself, and one of format `zipcode + town` an object carrying both, whose town is compared * case- and whitespace-insensitively while its postal code is not. * * `default`, and any name beginning with `_`, are reserved for the server and cannot be * supplied here. * - * An empty map is valid and means what it says: it supplies no value, so it matches no variant - * that pins a condition, and the entity's `default` variant is what comes back. It is the only way to - * ask for the default variant without knowing its id. - * * example: * { * "postal_code": "46045", @@ -17050,53 +10496,20 @@ declare namespace Components { export interface ResolveContext { [name: string]: any; } - /** - * The options a context resolve accepts. A pin takes `PinnedResolveOptions` instead. - */ export interface ResolveOptions { /** * Ask for an unambiguous answer. Several applicable variants become `AMBIGUOUS_RESOLUTION` - * rather than a set, and nothing applicable becomes `NO_MATCHES` rather than an empty one. + * rather than a set, and nothing applicable becomes `NOT_FOUND` rather than an empty one. * The response shape does not change: `results` simply carries exactly one entry. * */ resolve_one?: boolean; - /** - * Return the entities a relation attribute references in place of the references - * themselves, one level deep, exactly as an entity read with hydration does. - * - * A fetch, not a second resolution: a referenced entity comes back as it is read, and one - * that is itself conditional carries its own flag — acting on that is the consumer's - * choice, and this API does not resolve it on their behalf. - * - * Applied after composition, so a relation attribute whose value this variant's version - * replaced is hydrated too. That is what makes a composite price work: the override - * references different component *entities*, which exist only in the composed payload. - * - * A reference that cannot be fetched comes back exactly as entity hydration returns it — - * no drop, no failure, and no field reporting it. A resolved payload behaves as an entity - * of the same shape would, and the discriminators are the only difference. - * - * Costs one fetch per referenced entity per result, and carries no cap of its own: the - * per-attribute limits are entity hydration's, and the 100-result cap on the resolve itself - * is unchanged. - * - * **Published ahead of the behaviour.** Until hydration is built, `true` is answered `501` - * rather than served as unhydrated references; `false`, which asks for what this path - * already does, resolves normally. - * - */ - hydrate?: boolean; } /** * The entity as this variant leaves it — every attribute of a plain entity read, with the * applicable version's overrides applied — plus the discriminators saying where the numbers * came from. * - * With `options.hydrate`, a relation attribute holds the entities it references rather than the - * references themselves. That changes what an attribute holds, not the payload's shape, so - * nothing is declared here for it. - * */ export interface ResolvedVariant { [name: string]: any; @@ -17125,6 +10538,9 @@ declare namespace Components { /** * The conditions this variant pins, plus the boolean `default` discriminator. * + * Underscore-prefixed, like every other discriminator here, so that it cannot collide with + * an attribute an organization happens to have called `conditions`. + * * example: * { * "postal_code": "46045", @@ -17135,33 +10551,12 @@ declare namespace Components { [name: string]: any; default: boolean; }; - /** - * The variant's stored overrides this payload did not apply, and why. Always present, and - * empty in the ordinary case — a client reads its length rather than branching on its - * absence, the same way it reads a write's `warnings`. - * - * Computed per read from the schema as it stands, never stored, so granting or withdrawing - * `overridable_attribute` changes what resolves — and this list — without any data being - * rewritten. A version read reports what is stored and carries no such list; this is the - * only surface that honours the schema. - * - */ - _inert_overrides: /** - * One override that did not apply, and why. - * - * The same entry on both sides of the feature: a write reports the attributes in its body it did - * not store, and a resolved payload reports the stored overrides composition did not apply. Those - * are the same fact observed at two moments, so a client learns one shape and reads it in both - * places. - * - */ - InertOverride[]; } export interface ResolvedVariants { /** * One composed payload per applicable variant, capped at 100 — a context selecting more - * than that is answered with `TOO_MANY_MATCHES` instead. No dominance or specificity - * ordering is applied between them. + * than that is answered with `TOO_MANY_MATCHES` instead, since each result costs its own + * version lookup. No dominance or specificity ordering is applied between them. * */ results: /** @@ -17169,10 +10564,6 @@ declare namespace Components { * applicable version's overrides applied — plus the discriminators saying where the numbers * came from. * - * With `options.hydrate`, a relation attribute holds the entities it references rather than the - * references themselves. That changes what an attribute holds, not the payload's shape, so - * nothing is declared here for it. - * */ ResolvedVariant[]; } @@ -17559,59 +10950,6 @@ declare namespace Components { */ errors: /* The availability rule error */ ValidateAvailabilityFileError[]; } - /** - * Which pins a variant must carry to be listed: a flat map keyed by condition name, as the - * entity's schema declares them. A condition left out of the map is not filtered on at all. - * - * Each value is either an exact value, typed by its condition, or a single-operator predicate - * object — the same seven a resolve context accepts, because in both cases a predicate is - * applied to the variant's *pinned* value, so nothing about matching moves: - * - * - `{ "lt": v }`, `{ "lte": v }`, `{ "gt": v }`, `{ "gte": v }` — order against a `number` or - * `date` condition. - * - `{ "in": [...] }` — membership, against a `string`, `select` or `number` condition. - * - `{ "between": "2026-03-01" }` — the explicit spelling of `daterange` containment; a plain - * date supplied for a `daterange` condition means the same thing. - * - `{ "exists": true }` — pinned to any value. `{ "exists": false }` — the condition left - * unpinned. - * - * An `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To - * filter on a condition whatever its pinned value, send `{ "exists": true }` rather than - * enumerating its vocabulary. - * - * **A variant matches only where it pins the condition** — the one place a filter and a resolve - * context differ. On `:resolve` a condition a variant does not pin matches any value; here, - * asking for postal code 46045 does not return the variants that pin no postal code at all. - * `{ "exists": false }` is how those are asked for. - * - * Values are typed and canonicalized exactly as a resolve context's are, by the same code, so - * one instant written two ways filters the same way either way. A condition the schema does not - * declare is `CONDITION_UNDEFINED`, a predicate its type does not support is - * `OPERATOR_UNSUPPORTED`, and a value malformed for its type is `CONTEXT_FORMAT_INVALID`. - * - * **`default` is accepted here**, as the exact boolean every row reports it as: `true` selects - * the entity's fallback variant, `false` every variant that is not it. - * - * It takes no predicate. `default` is not a condition and has no type, so ordering and - * membership have nothing to apply to. It is also the one key the pinned-only rule above does - * not describe literally: a variant that is not the fallback does not pin the marker to `false`, - * it does not pin it at all, so `false` selects the variants that leave it unpinned. - * - * Names beginning with `_` stay reserved for the server and cannot be filtered on — `_default`, - * the marker a fallback is actually stored under, included. `default` is the spelling every read - * reports and the only one this accepts. - * - * example: - * { - * "postal_code": "46045", - * "consumption": { - * "lt": 5000 - * } - * } - */ - export interface VariantConditionFilter { - [name: string]: any; - } /** * A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a * boolean `default` saying whether this is the entity's fallback. @@ -17626,428 +10964,27 @@ declare namespace Components { * "default": false * } */ - export interface VariantConditions { - [name: string]: any; - default: boolean; - } - export interface VariantList { - /** - * How many variants match, exactly, at any depth — not how many this page carries. Exact, - * as entity listing's is. - * - * example: - * 8128 - */ - hits: number; - results: /** - * One variant as a listing reports it: which variant it is and what it pins. - * - * No `_revision` — a write re-reads its version through that version's own `GET` — and no - * `_inert_overrides`, since a listing reports what is stored and only `:resolve` honours the - * schema. - * - */ - VariantListRow[]; - /** - * The cursor that continues this listing, absent on the last page. Send it back as `cursor`, - * with the same filter, search and sort. - * - * example: - * eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0 - */ - next?: string; - } - /** - * One variant as a listing reports it: which variant it is and what it pins. - * - * No `_revision` — a write re-reads its version through that version's own `GET` — and no - * `_inert_overrides`, since a listing reports what is stored and only `:resolve` honours the - * schema. - * - */ - export interface VariantListRow { - /** - * example: - * var-46045 - */ - variant_id: string; - /** - * example: - * price-sp26d1yo - */ - entity_id: string; - schema: /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - ConditionalEntitySlug; - /** - * The situation this variant applies to, plus the boolean `default` discriminator — the same - * shape a variant write returns. - * - * May lag: a variant just created can be missing from a page, and one just deleted can still - * be on it. The pins shown for a variant are never stale, since a variant's conditions are - * immutable after creation. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - conditions: { - [name: string]: any; - default: boolean; - }; - } - export interface VariantTree { - /** - * How many variants match, exactly, at any depth — not how many this page carries. Exact, - * as entity listing's is. - * - * example: - * 8128 - */ - hits: number; - /** - * One row per matching variant, in the requested order. - * - * A variant the index still holds but whose versions are already gone — a variant - * mid-delete — is **omitted** rather than returned without a `version`. So `results` can be - * shorter than `hits` implies, for the width of that lag and no longer. Paging still ends - * where `next` does. - * - */ - results: /** - * A listing row plus the one version the tree view shows for it, and the status saying which - * version that is. - * - */ - VariantTreeRow[]; - /** - * The cursor that continues this listing, absent on the last page. Send it back as `cursor`, - * with the same filter, search and sort. - * - * `as_of` is free to change between pages. It selects which version each row shows and has - * no bearing on which variants match or on the order they come back in, so a screen whose - * date picker moves mid-listing keeps paging rather than starting over. - * - * example: - * eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0 - */ - next?: string; - } - /** - * The variants list's request plus `as_of`, the instant each row's version is selected at. - * `size` is clamped at 100 here; every other shared property means what it means on the list. - * - */ - export interface VariantTreeRequest { - conditions?: /** - * Which pins a variant must carry to be listed: a flat map keyed by condition name, as the - * entity's schema declares them. A condition left out of the map is not filtered on at all. - * - * Each value is either an exact value, typed by its condition, or a single-operator predicate - * object — the same seven a resolve context accepts, because in both cases a predicate is - * applied to the variant's *pinned* value, so nothing about matching moves: - * - * - `{ "lt": v }`, `{ "lte": v }`, `{ "gt": v }`, `{ "gte": v }` — order against a `number` or - * `date` condition. - * - `{ "in": [...] }` — membership, against a `string`, `select` or `number` condition. - * - `{ "between": "2026-03-01" }` — the explicit spelling of `daterange` containment; a plain - * date supplied for a `daterange` condition means the same thing. - * - `{ "exists": true }` — pinned to any value. `{ "exists": false }` — the condition left - * unpinned. - * - * An `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To - * filter on a condition whatever its pinned value, send `{ "exists": true }` rather than - * enumerating its vocabulary. - * - * **A variant matches only where it pins the condition** — the one place a filter and a resolve - * context differ. On `:resolve` a condition a variant does not pin matches any value; here, - * asking for postal code 46045 does not return the variants that pin no postal code at all. - * `{ "exists": false }` is how those are asked for. - * - * Values are typed and canonicalized exactly as a resolve context's are, by the same code, so - * one instant written two ways filters the same way either way. A condition the schema does not - * declare is `CONDITION_UNDEFINED`, a predicate its type does not support is - * `OPERATOR_UNSUPPORTED`, and a value malformed for its type is `CONTEXT_FORMAT_INVALID`. - * - * **`default` is accepted here**, as the exact boolean every row reports it as: `true` selects - * the entity's fallback variant, `false` every variant that is not it. - * - * It takes no predicate. `default` is not a condition and has no type, so ordering and - * membership have nothing to apply to. It is also the one key the pinned-only rule above does - * not describe literally: a variant that is not the fallback does not pin the marker to `false`, - * it does not pin it at all, so `false` selects the variants that leave it unpinned. - * - * Names beginning with `_` stay reserved for the server and cannot be filtered on — `_default`, - * the marker a fallback is actually stored under, included. `default` is the spelling every read - * reports and the only one this accepts. - * - * example: - * { - * "postal_code": "46045", - * "consumption": { - * "lt": 5000 - * } - * } - */ - VariantConditionFilter; - /** - * Free text matched against the variant's pinned values — how someone finds one postal code - * among 800,000. - * - * Matches `string`, `select` and `number` pins only. A `location` pin is stored as an array - * of its format's parts and a `daterange` pin as an object carrying `from` and `until`, so - * neither is text a user could have typed. - * - * example: - * 460 - */ - search?: string; - /** - * `conditions.:asc` or `conditions.:desc`, for a `string`, `select`, `number` or - * `date` pin. Anything else — another field, or a pin of another type — is a `400`. - * - * **`variant_id:asc` is appended by the server**, always, so the order is total: many - * variants can pin one postal code, and without a tiebreaker a cursor would repeat or skip - * rows between pages. Asking for no sort is `variant_id:asc` alone. - * - * example: - * conditions.postal_code:asc - */ - sort?: string; - /** - * The offset to read from. Not read when a `cursor` is sent, which carries its own position. - * - * Bounded by the search index's offset window, together with `size`: the window bounds the - * last row a page may contain, so the final servable offset is the window minus the page - * size. A page reaching past it is `OFFSET_WINDOW_EXCEEDED`, naming all three numbers, - * rather than a page clamped back inside it as entity listing does. The window is the - * deploy's: read its size from the error, not from here. - * - */ - from?: number; - /** - * Rows per page. Clamped silently at 100, a tenth of the variants list's cap: every row here - * costs its own version lookup. - * - */ - size?: number; - /** - * Continue from a previous response's `next`, which is where a caller goes when the offset - * window runs out. Opaque: it encodes the position and the listing it was issued for, and - * nothing a client should read or construct. - * - * `conditions`, `search` and `sort` must be the ones the cursor was issued with — a cursor - * resumes one listing, and cannot mean anything against a different one. A cursor that is - * malformed, or does not match the listing it is sent with, is a `400`. - * - * example: - * eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0 - */ - cursor?: string; - /** - * The instant each row's version is selected at — the version with the latest `valid_from` - * at or before it. Defaults to now. The same selector, by the same rule, as `:resolve`'s. - * - * A variant whose first version is later than this is not dropped the way context matching - * drops it: it is a row with `status: scheduled` carrying that upcoming first version, which - * is what makes a staged price visible on the editing screen. - * - * An RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time - * (`2026-01-01T00:00:00Z`), to at most millisecond precision. - * - * example: - * 2027-03-15T00:00:00Z - */ - as_of?: string; - } - /** - * A listing row plus the one version the tree view shows for it, and the status saying which - * version that is. - * - */ - export interface VariantTreeRow { - /** - * example: - * var-46045 - */ - variant_id: string; - /** - * example: - * price-sp26d1yo - */ - entity_id: string; - schema: /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - ConditionalEntitySlug; - /** - * The situation this variant applies to, plus the boolean `default` discriminator — the same - * shape a variant write returns. - * - * May lag: a variant just created can be missing from a page, and one just deleted can still - * be on it. The pins shown for a variant are never stale, since a variant's conditions are - * immutable after creation. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - conditions: { - [name: string]: any; - default: boolean; - }; - status: /** - * Whether a tree row's version is the one in effect at `as_of`, or one still ahead of it. - * - * Exactly two values, and every row has one: a variant always has at least one version, so - * either a version is in effect at `as_of` or every version of that variant is still to come. - * - * - `active`: `version` is the version with the latest `valid_from` at or before `as_of` — - * the same version `active_valid_from` and `NO_ACTIVE_VERSION` speak of. - * - `scheduled`: the variant's first version is later than `as_of`, and `version` is that - * upcoming first version. - * - */ - VariantTreeRowStatus; - /** - * The version this row shows: the one in effect at `as_of`, or — where every version of the - * variant is still ahead of it — that upcoming first one. `status` says which of the two it - * is. - * - * Always present. A variant always has at least one version, and the one case where a row - * could have none — a variant whose delete has removed its versions but not yet its index - * document — is omitted from `results` instead, so a consumer never reads this field - * defensively. - * - */ - version: { - /** - * example: - * var-46045 - */ - variant_id: string; - /** - * example: - * price-sp26d1yo - */ - entity_id: string; - schema: /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - ConditionalEntitySlug; - /** - * The situation the variant applies to, plus the boolean `default` discriminator. A property - * of the variant rather than of this version: every version of a variant carries the same - * one, and no version write can change it. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - conditions: { - [name: string]: any; - default: boolean; - }; - /** - * When this version takes effect, canonicalized to millisecond-precision UTC. A version's - * identity within its variant — it never moves. - * - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - values: /** - * The attribute values this version overrides on the base entity, keyed by attribute name. - * - * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. - * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. - * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. - * - * example: - * { - * "unit_amount": 2499, - * "unit_amount_decimal": "24.99" - * } - */ - VariantValues; - /** - * When this version was created. - */ - _created_at: string; - /** - * When this version was last written. - */ - _updated_at: string; - }; - } - /** - * Whether a tree row's version is the one in effect at `as_of`, or one still ahead of it. - * - * Exactly two values, and every row has one: a variant always has at least one version, so - * either a version is in effect at `as_of` or every version of that variant is still to come. - * - * - `active`: `version` is the version with the latest `valid_from` at or before `as_of` — - * the same version `active_valid_from` and `NO_ACTIVE_VERSION` speak of. - * - `scheduled`: the variant's first version is later than `as_of`, and `version` is that - * upcoming first version. - * - */ - export type VariantTreeRowStatus = "active" | "scheduled"; + export interface VariantConditions { + [name: string]: any; + default: boolean; + } /** * The attribute values this version overrides on the base entity, keyed by attribute name. * * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. + * (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable + * attributes present here are ignored rather than rejected, so a client working from a slightly + * stale schema snapshot still succeeds instead of failing on fields it could not have known to + * drop. An attribute's `render_condition` says when to show it and has no bearing on whether a + * variant may override it. * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. + * Ignored means *not updated*, never *removed*: a value already stored for an attribute that is + * not currently overridable is preserved, so removing and restoring the flag deactivates and + * then reactivates the same override. * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. + * A composite price's `price_components` is an ordinary overridable relation attribute: a + * composite variant pins its component variants here the same way any other relation value is + * set, with no special handling. * * example: * { @@ -18111,26 +11048,19 @@ declare namespace Components { * The attribute values this version overrides on the base entity, keyed by attribute name. * * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. + * (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable + * attributes present here are ignored rather than rejected, so a client working from a slightly + * stale schema snapshot still succeeds instead of failing on fields it could not have known to + * drop. An attribute's `render_condition` says when to show it and has no bearing on whether a + * variant may override it. * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. + * Ignored means *not updated*, never *removed*: a value already stored for an attribute that is + * not currently overridable is preserved, so removing and restoring the flag deactivates and + * then reactivates the same override. * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. + * A composite price's `price_components` is an ordinary overridable relation attribute: a + * composite variant pins its component variants here the same way any other relation value is + * set, with no special handling. * * example: * { @@ -18157,132 +11087,41 @@ declare namespace Components { */ _revision: number; } - export interface VariantVersionList { + export interface VariantWriteWarning { /** - * A page of the variant's timeline, in the requested `order`. + * - `VARIANT_COUNT_APPROACHING_CAP`: this entity is nearing the number of variants it may + * hold. Surfaced rather than rejected, so an importer finds out with a whole run's notice + * instead of discovering the limit halfway through a refresh. * */ - results: /** - * One version of one variant as a listing reports it: `VariantVersion` without `_revision`. - * - * The revision is missing on purpose. An editing screen re-reads the one version it is about to - * write through that version's own `GET`, which is strongly consistent, and writes with the - * revision it gets back. - * - * Everything else is `VariantVersion` field for field, including the variant's `conditions`, - * which every version of a variant repeats. - * + code: "VARIANT_COUNT_APPROACHING_CAP"; + message: string; + /** + * Variants this entity holds, including the one just created. */ - VariantVersionSnapshot[]; + variant_count: number; /** - * The cursor that continues this timeline, absent only on the last page. - * - * The only end-of-data signal: a page shorter than `limit`, or an empty one, can still carry - * a cursor, so a client pages until this field is absent rather than until a page looks - * short. Send it back as `cursor`, against the same variant and the same `order`. - * - * example: - * eyJzayI6IlYjcHJpY2Utc3AyNmQxeW8jdmFyLTQ2MDQ1IzIwMjYtMDEtMDFUMDA6MDA6MDAuMDAwWiIsIm9yZGVyIjoiYXNjIn0 + * Variants this entity may hold. Configurable per organization. */ - next?: string; + cap: number; } /** - * One version of one variant as a listing reports it: `VariantVersion` without `_revision`. - * - * The revision is missing on purpose. An editing screen re-reads the one version it is about to - * write through that version's own `GET`, which is strongly consistent, and writes with the - * revision it gets back. - * - * Everything else is `VariantVersion` field for field, including the variant's `conditions`, - * which every version of a variant repeats. + * Something a version write moved. A version write is never refused for being late — backdating a + * version, and editing or deleting one that has already been superseded, are both accepted — so + * what a caller gets instead is a warning naming exactly what changed. One write can carry both + * codes. * */ - export interface VariantVersionSnapshot { - /** - * example: - * var-46045 - */ - variant_id: string; - /** - * example: - * price-sp26d1yo - */ - entity_id: string; - schema: /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - ConditionalEntitySlug; + export interface VersionWriteWarning { /** - * The situation the variant applies to, plus the boolean `default` discriminator. A property - * of the variant rather than of this version: every version of a variant carries the same - * one, and no version write can change it. - * - * example: - * { - * "postal_code": "46045", - * "default": false - * } - */ - conditions: { - [name: string]: any; - default: boolean; - }; - /** - * When this version takes effect, canonicalized to millisecond-precision UTC. A version's - * identity within its variant — it never moves. - * - * example: - * 2027-01-01T00:00:00.000Z - */ - valid_from: string; - values: /** - * The attribute values this version overrides on the base entity, keyed by attribute name. + * - `ACTIVE_VERSION_REPLACED`: what resolves **now** changed, other than by a newer version + * taking effect. The version in effect was written behind, or removed. + * - `SUPERSEDED_VERSION_WRITTEN`: what a past-dated (`as_of`) read returns changed. The write + * landed on, or created, a version that is not the one currently in effect. * - * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. - * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. - * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. - * - * example: - * { - * "unit_amount": 2499, - * "unit_amount_decimal": "24.99" - * } - */ - VariantValues; - /** - * When this version was created. - */ - _created_at: string; - /** - * When this version was last written. */ - _updated_at: string; - } - /** - * Which version a write moved, and which one was in effect while it did. - * - */ - export interface VersionMoved { + code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"; + message: string; /** * The version this write created, changed or removed. * example: @@ -18293,94 +11132,11 @@ declare namespace Components { * The version in effect when the write landed, before it did. Absent when the variant had * none — every version of it still scheduled. * - * May lag the variant's timeline by milliseconds, so a version written moments earlier may - * not be named here. Advisory, like the warning carrying it: nothing branches on it except a - * human reading the message. - * * example: * 2026-01-01T00:00:00.000Z */ active_valid_from?: string; } - /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. - * - */ - export type WriteWarning = /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. - * - */ - { - code: "VARIANT_COUNT_APPROACHING_CAP"; - message: string; - details: { - /** - * Variants this entity holds, including the one just written. - */ - variant_count: number; - /** - * Variants this entity may hold. Configurable per deploy, the same value for every - * organization on it. - * - */ - cap: number; - }; - } | { - code: "ACTIVE_VERSION_CHANGED"; - message: string; - details: /** - * Which version a write moved, and which one was in effect while it did. - * - */ - VersionMoved; - } | { - code: "SUPERSEDED_VERSION_WRITTEN"; - message: string; - details: /** - * Which version a write moved, and which one was in effect while it did. - * - */ - VersionMoved; - } | { - code: "ATTRIBUTES_NOT_APPLIED"; - message: string; - details: { - attributes: [ - /** - * One override that did not apply, and why. - * - * The same entry on both sides of the feature: a write reports the attributes in its body it did - * not store, and a resolved payload reports the stored overrides composition did not apply. Those - * are the same fact observed at two moments, so a client learns one shape and reads it in both - * places. - * - */ - InertOverride, - .../** - * One override that did not apply, and why. - * - * The same entry on both sides of the feature: a write reports the attributes in its body it did - * not store, and a resolved payload reports the stored overrides composition did not apply. Those - * are the same fact observed at two moments, so a client learns one shape and reads it in both - * places. - * - */ - InertOverride[] - ]; - }; - }; /** * A version as a write left it, together with anything the write moved. * @@ -18429,26 +11185,19 @@ declare namespace Components { * The attribute values this version overrides on the base entity, keyed by attribute name. * * Only attributes currently declaring `overridable_attribute` are applied. Metadata fields - * (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes, - * attributes of a type no variant may override and non-overridable attributes present here are - * not applied rather than rejected, and every one but the metadata is named in the write's - * `warnings`, so a client working from a slightly stale schema snapshot still succeeds instead - * of failing on fields it could not have known to drop, and still learns which of them did not - * land. Metadata is never named, since a client echoing back a payload it read carries it in - * every body. An attribute's `render_condition` says when to show it and has no - * bearing on whether a variant may override it. + * (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable + * attributes present here are ignored rather than rejected, so a client working from a slightly + * stale schema snapshot still succeeds instead of failing on fields it could not have known to + * drop. An attribute's `render_condition` says when to show it and has no bearing on whether a + * variant may override it. * - * Not applied means *not updated*, never *removed*: a value already stored for an attribute that - * is not currently overridable is preserved, so removing and restoring the flag deactivates and - * then reactivates the same override. An append seeds the attributes the variant may not - * override from the version in effect at its own `valid_from`, so its stored values are not a - * pure function of the body that wrote it; a variant's first version, and an append dated before - * the variant's earliest version, inherit nothing. + * Ignored means *not updated*, never *removed*: a value already stored for an attribute that is + * not currently overridable is preserved, so removing and restoring the flag deactivates and + * then reactivates the same override. * - * A composite price's `price_components` is an ordinary overridable relation attribute. A - * composite variant's override references different component *entities*, never a variant or a - * version of one, and holds whatever a relation attribute ordinarily holds — this API defines no - * reference shape of its own. + * A composite price's `price_components` is an ordinary overridable relation attribute: a + * composite variant pins its component variants here the same way any other relation value is + * set, with no special handling. * * example: * { @@ -18475,21 +11224,18 @@ declare namespace Components { */ _revision: number; /** - * What this write moved, and anything in the body it did not store. Empty in the - * ordinary case — a client reads its length rather than branching on its absence. + * What this write moved, if anything. Empty in the ordinary case — a client reads its + * length rather than branching on its absence. * */ warnings: /** - * Something worth knowing that did not stop a write. - * - * One vocabulary for every write, so a client branches on what happened rather than on which - * endpoint it called. `code` and `message` are the only two fields every code shares; everything - * else lives in a `details` object typed per code, so narrowing on `code` yields a payload the - * client can read rather than an untyped bag. A write raises each code at most once, and in the - * ordinary case raises none of them. + * Something a version write moved. A version write is never refused for being late — backdating a + * version, and editing or deleting one that has already been superseded, are both accepted — so + * what a caller gets instead is a warning naming exactly what changed. One write can carry both + * codes. * */ - WriteWarning[]; + VersionWriteWarning[]; } } } @@ -18518,60 +11264,30 @@ declare namespace Paths { */ Components.Schemas.WrittenVariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -18625,135 +11341,6 @@ declare namespace Paths { export type $404 = Components.Schemas.Error; } } - namespace $BatchDeleteConditionalVariants { - namespace Parameters { - export type Slug = /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - Components.Schemas.ConditionalEntitySlug; - } - export interface PathParameters { - slug: Parameters.Slug; - } - export type RequestBody = /** - * A batch of variant and version deletes under one schema, each item naming the entity it - * removes from. - * - */ - Components.Schemas.BatchDeleteVariantsRequest; - namespace Responses { - export type $200 = /** - * What a batch delete did: one entry per item, in request order, and a count per outcome. - * - */ - Components.Schemas.BatchDeleteResult; - export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $501 = Components.Schemas.Error; - } - } - namespace $BatchUpsertConditionalVariants { - namespace Parameters { - export type Slug = /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - Components.Schemas.ConditionalEntitySlug; - } - export interface PathParameters { - slug: Parameters.Slug; - } - export type RequestBody = /** - * A batch of variant writes under one schema, each item naming the entity it writes to. - * - */ - Components.Schemas.BatchUpsertVariantsRequest; - namespace Responses { - export type $200 = /** - * What a batch upsert did: one entry per item, in request order, and a count per outcome. - * - */ - Components.Schemas.BatchUpsertResult; - export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $501 = Components.Schemas.Error; - } - } namespace $CalculatePricingDetails { export interface RequestBody { line_items?: /* A valid set of product prices, quantities, (discounts) and taxes from a client. */ Components.Schemas.PriceItemsDto; @@ -18813,60 +11400,30 @@ declare namespace Paths { namespace Responses { export type $201 = Components.Schemas.CreatedVariant; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -18890,60 +11447,30 @@ declare namespace Paths { namespace Responses { export type $200 = Components.Schemas.DeletedVariant; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -18973,60 +11500,30 @@ declare namespace Paths { namespace Responses { export type $200 = Components.Schemas.DeletedVariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -19070,125 +11567,42 @@ declare namespace Paths { * the entity is what `:resolve` answers. * */ - Components.Schemas.VariantVersion; - export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - } - } - namespace $GetConditionSets { - namespace Parameters { - export type Slug = /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - Components.Schemas.ConditionalEntitySlug; - } - export interface PathParameters { - slug: Parameters.Slug; - } - namespace Responses { - export type $200 = Components.Schemas.ConditionSetCatalog; - export type $400 = Components.Schemas.Error; - } - } - namespace $GetConditionalVariantTree { - namespace Parameters { - export type EntityId = string; - export type Slug = /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - Components.Schemas.ConditionalEntitySlug; - } - export interface PathParameters { - slug: Parameters.Slug; - entity_id: Parameters.EntityId; - } - export type RequestBody = /** - * The variants list's request plus `as_of`, the instant each row's version is selected at. - * `size` is clamped at 100 here; every other shared property means what it means on the list. - * - */ - Components.Schemas.VariantTreeRequest; - namespace Responses { - export type $200 = Components.Schemas.VariantTree; + Components.Schemas.VariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; - export type $501 = Components.Schemas.Error; + } + } + namespace $GetConditionSets { + namespace Parameters { + export type Slug = /** + * Schema slug of an entity type that can be conditional — the `{slug}` of every + * conditional-pricing route. + * + */ + Components.Schemas.ConditionalEntitySlug; + } + export interface PathParameters { + slug: Parameters.Slug; + } + namespace Responses { + export type $200 = Components.Schemas.ConditionSetCatalog; + export type $400 = Components.Schemas.Error; } } namespace $GetConditionalVariantVersion { @@ -19221,41 +11635,21 @@ declare namespace Paths { */ Components.Schemas.VariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -19406,139 +11800,6 @@ declare namespace Paths { export type $404 = Components.Schemas.Error; } } - namespace $ListConditionalVariantVersions { - namespace Parameters { - export type Cursor = string; - export type EntityId = string; - export type Limit = number; - export type Order = "asc" | "desc"; - export type Slug = /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - Components.Schemas.ConditionalEntitySlug; - export type VariantId = string; - } - export interface PathParameters { - slug: Parameters.Slug; - entity_id: Parameters.EntityId; - variant_id: Parameters.VariantId; - } - export interface QueryParameters { - limit?: Parameters.Limit; - order?: Parameters.Order; - cursor?: Parameters.Cursor; - } - namespace Responses { - export type $200 = Components.Schemas.VariantVersionList; - export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $501 = Components.Schemas.Error; - } - } - namespace $ListConditionalVariants { - namespace Parameters { - export type EntityId = string; - export type Slug = /** - * Schema slug of an entity type that can be conditional — the `{slug}` of every - * conditional-pricing route. - * - */ - Components.Schemas.ConditionalEntitySlug; - } - export interface PathParameters { - slug: Parameters.Slug; - entity_id: Parameters.EntityId; - } - export type RequestBody = /** - * How to narrow and page a variant listing. Every property is optional, so `{}` is a valid body - * and asks for the first ten variants of the entity in `variant_id` order — the body itself is - * required, and an omitted one is a request-validation `400` rather than an unnarrowed page. - * - * `conditions` and `search` narrow independently and a variant has to satisfy both. - * - */ - Components.Schemas.ListVariantsRequest; - namespace Responses { - export type $200 = Components.Schemas.VariantList; - export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. - * Referenced only by the operations that emit these codes; every other operation - * keeps the plain `Error` shape. - * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * - */ - Components.Schemas.ConditionalPricingError; - export type $501 = Components.Schemas.Error; - } - } namespace $PatchActiveConditionalVariantVersion { namespace Parameters { export type EntityId = string; @@ -19563,60 +11824,30 @@ declare namespace Paths { */ Components.Schemas.WrittenVariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -19647,60 +11878,30 @@ declare namespace Paths { */ Components.Schemas.WrittenVariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -19776,60 +11977,30 @@ declare namespace Paths { */ Components.Schemas.WrittenVariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } @@ -19860,137 +12031,65 @@ declare namespace Paths { */ Components.Schemas.WrittenVariantVersion; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; } } namespace $ResolveConditionalEntity { - export type RequestBody = /** - * A resolve names one conditional entity, then says which of its variants it means — one of two - * ways, and never both. `context` describes a situation and asks which variants apply to it; - * `variant_id` names one variant and skips matching entirely. - * - * A body carrying both, or neither, is a validation `400`. Asking for the default variant - * without knowing its id is `context: {}`, which matches nothing and therefore falls back to it. - * - * Everything below the variant selection is the same on both branches, `as_of` included. - * - */ - Components.Schemas.ResolveConditionalEntityRequest; + export type RequestBody = Components.Schemas.ResolveConditionalEntityRequest; namespace Responses { export type $200 = Components.Schemas.ResolvedVariants; export type $400 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $404 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; export type $409 = /** - * An error from a conditional-pricing operation, carrying a machine-readable `code` from the - * conditional-pricing vocabulary plus the structured data that code explains, so a client can - * branch on the kind of failure rather than parse the message. + * An error from a conditional-pricing operation, carrying a machine-readable `code` + * from the conditional-pricing vocabulary plus any structured data about the failure, + * so a client can branch on the kind of failure rather than parse the message. * Referenced only by the operations that emit these codes; every other operation * keeps the plain `Error` shape. * - * `details` is typed per code. Narrow on `code` and the object under it declares exactly the - * fields that code sends — never a field it does not send, and nothing beyond the declaration — - * so the conflicting variant id, or the value and vocabulary behind a rejected pin, is read - * directly. - * - * Not every failure these operations raise is in the vocabulary. A request body that is simply - * malformed earns a message and nothing to branch on, and is answered with neither `code` nor - * `details` — the last member of the union, so testing `code` for absence is how a client tells - * one of those from the twenty-three coded failures. - * */ Components.Schemas.ConditionalPricingError; - export type $501 = Components.Schemas.Error; } } namespace $SaveCredentials { @@ -21560,17 +13659,12 @@ export interface OperationMethods { /** * $resolveConditionalEntity - $resolveConditionalEntity * - * Resolves which of a conditional entity's variants apply, and returns each one composed: the - * base entity overlaid with the values of the version in effect at `as_of`. - * - * Resolution is two selections in a fixed order — the variant, then the version by `as_of`. It - * is always scoped to one logical entity, so it stays a cheap, predictable lookup rather than - * an open search. + * Resolves which of a conditional entity's variants apply to a situation, and returns each one + * composed: the base entity overlaid with the values of the version in effect at `as_of`. * - * **The variant is selected one of two ways, and the body says which.** A `context` describes a - * situation and is matched against the conditions each variant pins. A `variant_id` names one - * variant and skips matching entirely. Exactly one of the two: a body carrying both, or - * neither, is a `400`. + * Resolution is two selections in a fixed order — the variant, by matching `context` against + * the conditions each variant pins; then the version, by `as_of`. It is always scoped to one + * logical entity, so it stays a cheap, predictable lookup rather than an open search. * * Matching follows two rules worth knowing before assembling a context. A condition a variant * does **not** pin matches any value, which is what lets a condition be added to a schema @@ -21579,12 +13673,8 @@ export interface OperationMethods { * nothing rather than silently matching another segment's variants. * * When nothing matches, the entity's `default` variant is returned if it has one. There is no - * implicit fallback to the unmodified base entity: an empty `results` means nothing applies to - * this situation, and the base entity's values are not an answer to it. A pin does not reach - * that fallback at all: it asks for one variant by name, and answers with it or with a 404. - * - * `options.hydrate` returns the entities a relation attribute references in place of the - * references, on either branch. + * implicit fallback to the unmodified base entity — its values are the ones no variant + * overrode, which is not an answer to "what applies here". * * Availability is a separate mechanism and is never consulted here. * @@ -21598,7 +13688,8 @@ export interface OperationMethods { * $createConditionalVariant - $createConditionalVariant * * Creates one variant of a conditional entity, together with the first version carrying its - * values: a variant always has at least one version. + * values. Never two calls: a variant that existed without a version would be an entity holding + * a condition tuple it cannot answer with. * * The body pins the situation the variant applies to. Pins are exact values only — predicates * are a read-side concept and are rejected here — and are stored canonicalized for their @@ -21612,8 +13703,8 @@ export interface OperationMethods { * than a fallback and far easier to create by accident. * - `default` is a property of the variant, set by the `default` flag, and is never a value in * `conditions` — not even `false`. A `default` variant cannot pin anything else, and an entity - * can have only one; a second is refused as `TUPLE_CONFLICT`. Any entity may have one; - * nothing is declared in the schema to allow it. + * can have only one, enforced by the ordinary condition-tuple guard rather than by a rule of + * its own. Any entity may have one; nothing is declared in the schema to allow it. * - Condition values are immutable afterwards. A variant's identity is the situation it applies * to, and orders and contracts pin it. **A condition added to a schema that already has * variants is effectively one-way**: every existing variant is a wildcard on the new @@ -21621,14 +13712,12 @@ export interface OperationMethods { * retro-pinning the others is blocked by this same rule. * * Attribute values are applied only for attributes currently carrying `overridable_attribute`. - * Metadata and non-overridable fields present in the body are not applied rather than rejected, - * and every one but the metadata is named in the response's `warnings`, so a client working from - * a slightly stale schema snapshot still succeeds and still learns which fields did not land. - * Metadata is never named, since a client echoing back a payload it read carries it in every - * body. + * Metadata and non-overridable fields present in the body are ignored rather than rejected, so a + * client working from a slightly stale schema snapshot still succeeds. * * `variant_id` is always server-generated and returned, and is not accepted in the body — the - * request schema admits no such property. It is the durable key orders and contracts pin. + * request schema admits no such property. It is the durable key orders and contracts pin, so it + * cannot be something two independent importers could collide on. * */ '$createConditionalVariant'( @@ -21636,72 +13725,6 @@ export interface OperationMethods { data?: Paths.$CreateConditionalVariant.RequestBody, config?: AxiosRequestConfig ): OperationResponse - /** - * $listConditionalVariants - $listConditionalVariants - * - * Lists a conditional entity's variants and the conditions each one pins — the browse, filter - * and search read behind the Entity UI's variant screens. - * - * A `POST` because the condition filter is a structured object and needs a body; nothing is - * written. Every property in that body is optional, so `{}` is the whole of "the first ten - * variants, in `variant_id` order" — but the body itself is required, so send `{}` rather than - * nothing at all. - * - * Three ways to narrow, and they combine. `conditions` filters on the pins themselves and takes - * the same seven predicates a resolve context does; `search` is free text over pinned values; - * `sort` orders by one pin. **A variant matches the filter only where it pins the condition** — - * the one place a filter and a resolve context differ: asking for the variants pinning postal - * code 46045 does not return every variant that pins no postal code at all. - * - * Rows report what is *stored*, not what resolves: no version data, no `_revision` and no - * `_inert_overrides`. - * - * Paging is by offset for the first pages and by an opaque `cursor` beyond them. `size` defaults - * to 10 and is clamped at 1000; a `from` past the offset window is refused rather than clamped, - * and the refusal names the cursor to continue with. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. The examples below are what a consumer builds against in the meantime. - * - */ - '$listConditionalVariants'( - parameters?: Parameters | null, - data?: Paths.$ListConditionalVariants.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse - /** - * $getConditionalVariantTree - $getConditionalVariantTree - * - * The variants list, each row carrying the version in effect at `as_of` — the Entity UI's main - * editing screen in one call rather than one call per row. - * - * Everything the variants list accepts, filtering, search, sort and paging alike, means the same - * here. Three differences, all from the version lookup each row costs: the body takes an - * `as_of`, `size` is clamped at 100 rather than 1000, and a variant with no version to show is - * omitted from `results` (see `VariantTree`). - * - * Every row carries a `version`, and a `status` saying which one it got. A variant always has at - * least one version, so at any instant either a version is in effect (`active`) or every - * version of that variant is still ahead of it (`scheduled`) — in which case `version` is that - * upcoming first one, which is what makes a staged variant visible on the screen rather than - * blank. - * - * The version on a row carries no `_revision`. An editing screen re-reads the one version it is - * about to write through that version's own `GET`, which is strongly consistent, and writes with - * the revision it returns. - * - * The base entity is not part of this response. The screen's standard-price row is an ordinary - * entity read, and a variant's full timeline is the versions list. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. - * - */ - '$getConditionalVariantTree'( - parameters?: Parameters | null, - data?: Paths.$GetConditionalVariantTree.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse /** * $getActiveConditionalVariantVersion - $getActiveConditionalVariantVersion * @@ -21731,7 +13754,9 @@ export interface OperationMethods { * * The body is the complete set of attribute overrides: an attribute the variant may override and * that is absent from it stops being overridden. Attributes the variant may **not** override are - * not applied where the body carries them, and their stored value is kept rather than dropped. + * ignored where the body carries them, and their stored value is kept rather than dropped — a + * routine full-snapshot write must not erase an override the moment its attribute's flag happens + * to be off. * * Editing the version in effect is the ordinary way a live price is corrected, and warns about * nothing: what changes is what that version *says*, not which version is in effect. @@ -21755,8 +13780,9 @@ export interface OperationMethods { * `null` is a value like any other rather than a deletion; a client that wants an attribute to * stop being overridden sends the complete snapshot without it through `PUT`. * - * Attempting to change a pinned condition value is refused, as on every version write: a - * variant's conditions are fixed at creation. + * Attempting to change a pinned condition value is refused here in particular: a partial update + * is the path a caller reaches for by accident, and a variant's conditions are the situation it + * applies to, which the orders and contracts pinning it depend on not shifting. * */ '$patchActiveConditionalVariantVersion'( @@ -21782,7 +13808,8 @@ export interface OperationMethods { * * This removes the **variant**, not one of its versions. To remove a single version, name it on * `…/variants/{variant_id}/versions/{valid_from}` — including the one currently in effect, which - * has no shorthand delete: a delete names the version it removes. + * deliberately has no "delete whichever is live" shorthand: that is exactly the write nobody + * should be able to ask for without saying which version they meant. * */ '$deleteConditionalVariant'( @@ -21790,34 +13817,6 @@ export interface OperationMethods { data?: any, config?: AxiosRequestConfig ): OperationResponse - /** - * $listConditionalVariantVersions - $listConditionalVariantVersions - * - * Lists one variant's versions — its whole timeline, oldest first, which is what expanding a row - * of the tree loads. - * - * Its paging differs from the two variant reads: cursor paging only, no `from` and no `size`, - * and **no `hits`**. - * - * Two paging facts a client gets wrong if it assumes otherwise. **A page may be shorter than - * `limit`, or empty, and still carry a `next`**, so a client pages until `next` is absent rather - * than until a page looks short. And **a cursor belongs to one variant and one `order`**: - * replaying one against another variant, or against the opposite order, is a `400` rather than a - * plausible-looking wrong page. - * - * Versions carry no `_revision` here. An editing screen re-reads the one version it is about to - * write through that version's own `GET`, which is strongly consistent, and writes with the - * revision it returns. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. - * - */ - '$listConditionalVariantVersions'( - parameters?: Parameters | null, - data?: any, - config?: AxiosRequestConfig - ): OperationResponse /** * $appendConditionalVariantVersion - $appendConditionalVariantVersion * @@ -21831,7 +13830,8 @@ export interface OperationMethods { * **A version is never refused for being late.** A `valid_from` in the past is written like any * other and answered with warnings in `warnings` naming what it moved — what resolves now, what a * past-dated read returns, or both. Correcting a price that took effect last week is ordinary - * work. + * work; the alternative, deleting and recreating the variant, breaks every order and contract + * pinning its id. * * What is refused is appending at a `valid_from` the variant already has: that write means either * "replace it" or "and also this", and only the caller knows which. The two operations both @@ -21866,10 +13866,13 @@ export interface OperationMethods { * * Replaces one version's values wholesale, addressed by its `valid_from`. * - * Editable whatever its date, scheduled or past. Writing a superseded version is answered with a - * warning naming what a past-dated read now returns; it is not refused. + * Editable whatever its date, at both ends of the timeline: a scheduled version must stay + * editable so a staged price can be corrected before it goes live rather than accumulating dead + * versions beside it, and a past one must stay editable because correcting history is ordinary + * work. Writing a superseded version is answered with a warning naming what a past-dated read now + * returns; it is not refused. * - * Attributes the variant may not override are not applied where the body carries them, and their + * Attributes the variant may not override are ignored where the body carries them, and their * stored value is preserved rather than dropped. * */ @@ -21884,7 +13887,8 @@ export interface OperationMethods { * Changes only the fields it names on one version, addressed by its `valid_from`. * * Everything the body does not mention is left as stored. A partial update that tries to change a - * pinned condition value is refused: condition values are immutable after a variant is created. + * pinned condition value is refused: condition values are immutable after a variant is created, + * and this is the path that rule is most likely to be broken on by accident. * */ '$patchConditionalVariantVersion'( @@ -21914,108 +13918,6 @@ export interface OperationMethods { data?: any, config?: AxiosRequestConfig ): OperationResponse - /** - * $batchUpsertConditionalVariants - $batchUpsertConditionalVariants - * - * Writes up to 100 variants or versions in one call — the endpoint a bulk importer drives a - * refresh cycle through, so hundreds of thousands of keys are a stream of calls rather than a - * call per key. - * - * **One schema in the path, one entity per item.** A single call may name several entities, so - * it can refresh a whole tariff hierarchy — a composite price and its components together — - * and the entity id rides each item instead of the path. - * - * **An item addresses a condition tuple, never a `variant_id`.** An upsert creates a variant - * that has no id yet. The id it created, or found, is on the result entry. - * - * Each item's outcome is derived from what is stored, with no mode for the caller to declare, - * in this order: an unknown tuple is `variant_created`, a known tuple with no version at the - * item's `valid_from` is `version_created`, and an existing version at that exact instant is - * `updated` — or `skipped`, which is reserved for a write whose values are identical to what is - * stored, so re-running an unchanged import still reads as a no-op. `version_created` is - * distinct from `variant_created` so an importer's counts can tell "new postal codes appeared" - * from "existing variants got their scheduled adjustment". - * - * An item without `valid_from` is a current-state, last-write-wins write, and has no `skipped` - * detection. A `valid_from` in the past changes nothing about the outcome — it is written like - * any other and answered with the timeline warnings on that item. An importer stamping one - * `valid_from` across a batch therefore sees backdate warnings on every item; omitting the - * field is how it avoids them. - * - * **Items addressing the same variant apply in array order; items addressing different - * variants are processed in parallel.** Here "the same variant" is the same `(entity_id, - * condition tuple)`, so two items sharing a tuple and a `valid_from` apply in order and the - * last one wins. There is no cross-item rollback. - * - * **This write is unguarded.** No `_revision` is accepted on an item or returned on an entry; - * an editing screen that needs a guard re-reads the one version it is about to write through - * its own `GET`. - * - * Three refusals a client would otherwise expect do not occur here. `VERSION_CONFLICT` never - * does: an existing `valid_from` is a replacement rather than a collision. A tuple-uniqueness - * guard lost to a concurrent writer is not reported as `TUPLE_CONFLICT` either — the item is - * re-read against current state and re-derived through the same outcome order above, which is - * content-aware. `WRITE_CONFLICT` marks the case that is genuinely worth retrying: transient - * contention on one entity's rows. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. The examples below are what an importer builds against in the meantime. - * - */ - '$batchUpsertConditionalVariants'( - parameters?: Parameters | null, - data?: Paths.$BatchUpsertConditionalVariants.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse - /** - * $batchDeleteConditionalVariants - $batchDeleteConditionalVariants - * - * Removes up to 100 variants or versions in one call — the symmetric bulk withdrawal, so - * retiring a generation of variants, or a scheduled adjustment across many of them, is as - * cheap as creating it was. - * - * The noun is `variants` on both batch endpoints, although an item carrying `valid_from` - * removes one **version** rather than the variant: an item without it removes the whole variant - * — its condition tuple, its registration in the index, and every version it accumulated — and - * an item with it removes exactly that version, under the single-item rules. A future version - * and a superseded one are both deletable and both answered with the warnings that say what - * moved; a variant's last remaining version is refused - * (`LAST_VERSION_UNDELETABLE`), because such a variant would still hold its tuple and still - * resolve to nothing. Delete the variant instead. - * - * **An item addresses its variant one of two ways, and never both**: by `variant_id`, or by the - * condition tuple it pins. Use ids once the schema has drifted: a tuple naming a condition the - * schema no longer declares cannot be canonicalized, so it addresses nothing. An item naming - * both fails validation and is an envelope `400`, not a per-item error: the request validator - * rejects the body before any item runs. - * - * **`entity_id` is required beside a `variant_id`, and is not redundant.** A variant id alone - * addresses nothing in this API. - * - * **Items addressing the same variant apply in array order; items addressing different variants - * are processed in parallel.** Because an item addresses its variant two ways, "the same - * variant" is decided after addressing, in three steps: every condition tuple is resolved to a - * variant id, items are grouped by that id, and each group is applied in array order. So one - * call may hold an item naming `var-46045` and an item naming the tuple that variant pins, and - * the guarantee holds across both. There is no cross-item rollback. - * - * **An item that addresses nothing is `skipped` — but only when the variant or the version is - * what is missing.** A missing *entity* is a per-item `ENTITY_NOT_FOUND`. - * - * An interrupted call is safe to send again. A whole-variant delete frees the tuple in its - * first phase and removes the version rows afterwards, so a re-run picks up where it stopped - * and reports `skipped` for what has already gone. Nothing is archived: a variant an order or - * contract pins stops resolving, and a pinned `:resolve` naming it answers `VARIANT_NOT_FOUND`. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. - * - */ - '$batchDeleteConditionalVariants'( - parameters?: Parameters | null, - data?: Paths.$BatchDeleteConditionalVariants.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse } export interface PathsDictionary { @@ -22320,17 +14222,12 @@ export interface PathsDictionary { /** * $resolveConditionalEntity - $resolveConditionalEntity * - * Resolves which of a conditional entity's variants apply, and returns each one composed: the - * base entity overlaid with the values of the version in effect at `as_of`. + * Resolves which of a conditional entity's variants apply to a situation, and returns each one + * composed: the base entity overlaid with the values of the version in effect at `as_of`. * - * Resolution is two selections in a fixed order — the variant, then the version by `as_of`. It - * is always scoped to one logical entity, so it stays a cheap, predictable lookup rather than - * an open search. - * - * **The variant is selected one of two ways, and the body says which.** A `context` describes a - * situation and is matched against the conditions each variant pins. A `variant_id` names one - * variant and skips matching entirely. Exactly one of the two: a body carrying both, or - * neither, is a `400`. + * Resolution is two selections in a fixed order — the variant, by matching `context` against + * the conditions each variant pins; then the version, by `as_of`. It is always scoped to one + * logical entity, so it stays a cheap, predictable lookup rather than an open search. * * Matching follows two rules worth knowing before assembling a context. A condition a variant * does **not** pin matches any value, which is what lets a condition be added to a schema @@ -22339,12 +14236,8 @@ export interface PathsDictionary { * nothing rather than silently matching another segment's variants. * * When nothing matches, the entity's `default` variant is returned if it has one. There is no - * implicit fallback to the unmodified base entity: an empty `results` means nothing applies to - * this situation, and the base entity's values are not an answer to it. A pin does not reach - * that fallback at all: it asks for one variant by name, and answers with it or with a 404. - * - * `options.hydrate` returns the entities a relation attribute references in place of the - * references, on either branch. + * implicit fallback to the unmodified base entity — its values are the ones no variant + * overrode, which is not an answer to "what applies here". * * Availability is a separate mechanism and is never consulted here. * @@ -22360,7 +14253,8 @@ export interface PathsDictionary { * $createConditionalVariant - $createConditionalVariant * * Creates one variant of a conditional entity, together with the first version carrying its - * values: a variant always has at least one version. + * values. Never two calls: a variant that existed without a version would be an entity holding + * a condition tuple it cannot answer with. * * The body pins the situation the variant applies to. Pins are exact values only — predicates * are a read-side concept and are rejected here — and are stored canonicalized for their @@ -22374,8 +14268,8 @@ export interface PathsDictionary { * than a fallback and far easier to create by accident. * - `default` is a property of the variant, set by the `default` flag, and is never a value in * `conditions` — not even `false`. A `default` variant cannot pin anything else, and an entity - * can have only one; a second is refused as `TUPLE_CONFLICT`. Any entity may have one; - * nothing is declared in the schema to allow it. + * can have only one, enforced by the ordinary condition-tuple guard rather than by a rule of + * its own. Any entity may have one; nothing is declared in the schema to allow it. * - Condition values are immutable afterwards. A variant's identity is the situation it applies * to, and orders and contracts pin it. **A condition added to a schema that already has * variants is effectively one-way**: every existing variant is a wildcard on the new @@ -22383,14 +14277,12 @@ export interface PathsDictionary { * retro-pinning the others is blocked by this same rule. * * Attribute values are applied only for attributes currently carrying `overridable_attribute`. - * Metadata and non-overridable fields present in the body are not applied rather than rejected, - * and every one but the metadata is named in the response's `warnings`, so a client working from - * a slightly stale schema snapshot still succeeds and still learns which fields did not land. - * Metadata is never named, since a client echoing back a payload it read carries it in every - * body. + * Metadata and non-overridable fields present in the body are ignored rather than rejected, so a + * client working from a slightly stale schema snapshot still succeeds. * * `variant_id` is always server-generated and returned, and is not accepted in the body — the - * request schema admits no such property. It is the durable key orders and contracts pin. + * request schema admits no such property. It is the durable key orders and contracts pin, so it + * cannot be something two independent importers could collide on. * */ 'post'( @@ -22399,76 +14291,6 @@ export interface PathsDictionary { config?: AxiosRequestConfig ): OperationResponse } - ['/v1/conditional-pricing/{slug}/entities/{entity_id}/variants:list']: { - /** - * $listConditionalVariants - $listConditionalVariants - * - * Lists a conditional entity's variants and the conditions each one pins — the browse, filter - * and search read behind the Entity UI's variant screens. - * - * A `POST` because the condition filter is a structured object and needs a body; nothing is - * written. Every property in that body is optional, so `{}` is the whole of "the first ten - * variants, in `variant_id` order" — but the body itself is required, so send `{}` rather than - * nothing at all. - * - * Three ways to narrow, and they combine. `conditions` filters on the pins themselves and takes - * the same seven predicates a resolve context does; `search` is free text over pinned values; - * `sort` orders by one pin. **A variant matches the filter only where it pins the condition** — - * the one place a filter and a resolve context differ: asking for the variants pinning postal - * code 46045 does not return every variant that pins no postal code at all. - * - * Rows report what is *stored*, not what resolves: no version data, no `_revision` and no - * `_inert_overrides`. - * - * Paging is by offset for the first pages and by an opaque `cursor` beyond them. `size` defaults - * to 10 and is clamped at 1000; a `from` past the offset window is refused rather than clamped, - * and the refusal names the cursor to continue with. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. The examples below are what a consumer builds against in the meantime. - * - */ - 'post'( - parameters?: Parameters | null, - data?: Paths.$ListConditionalVariants.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse - } - ['/v1/conditional-pricing/{slug}/entities/{entity_id}/variants:tree']: { - /** - * $getConditionalVariantTree - $getConditionalVariantTree - * - * The variants list, each row carrying the version in effect at `as_of` — the Entity UI's main - * editing screen in one call rather than one call per row. - * - * Everything the variants list accepts, filtering, search, sort and paging alike, means the same - * here. Three differences, all from the version lookup each row costs: the body takes an - * `as_of`, `size` is clamped at 100 rather than 1000, and a variant with no version to show is - * omitted from `results` (see `VariantTree`). - * - * Every row carries a `version`, and a `status` saying which one it got. A variant always has at - * least one version, so at any instant either a version is in effect (`active`) or every - * version of that variant is still ahead of it (`scheduled`) — in which case `version` is that - * upcoming first one, which is what makes a staged variant visible on the screen rather than - * blank. - * - * The version on a row carries no `_revision`. An editing screen re-reads the one version it is - * about to write through that version's own `GET`, which is strongly consistent, and writes with - * the revision it returns. - * - * The base entity is not part of this response. The screen's standard-price row is an ordinary - * entity read, and a variant's full timeline is the versions list. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. - * - */ - 'post'( - parameters?: Parameters | null, - data?: Paths.$GetConditionalVariantTree.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse - } ['/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}']: { /** * $getActiveConditionalVariantVersion - $getActiveConditionalVariantVersion @@ -22499,7 +14321,9 @@ export interface PathsDictionary { * * The body is the complete set of attribute overrides: an attribute the variant may override and * that is absent from it stops being overridden. Attributes the variant may **not** override are - * not applied where the body carries them, and their stored value is kept rather than dropped. + * ignored where the body carries them, and their stored value is kept rather than dropped — a + * routine full-snapshot write must not erase an override the moment its attribute's flag happens + * to be off. * * Editing the version in effect is the ordinary way a live price is corrected, and warns about * nothing: what changes is what that version *says*, not which version is in effect. @@ -22523,8 +14347,9 @@ export interface PathsDictionary { * `null` is a value like any other rather than a deletion; a client that wants an attribute to * stop being overridden sends the complete snapshot without it through `PUT`. * - * Attempting to change a pinned condition value is refused, as on every version write: a - * variant's conditions are fixed at creation. + * Attempting to change a pinned condition value is refused here in particular: a partial update + * is the path a caller reaches for by accident, and a variant's conditions are the situation it + * applies to, which the orders and contracts pinning it depend on not shifting. * */ 'patch'( @@ -22550,7 +14375,8 @@ export interface PathsDictionary { * * This removes the **variant**, not one of its versions. To remove a single version, name it on * `…/variants/{variant_id}/versions/{valid_from}` — including the one currently in effect, which - * has no shorthand delete: a delete names the version it removes. + * deliberately has no "delete whichever is live" shorthand: that is exactly the write nobody + * should be able to ask for without saying which version they meant. * */ 'delete'( @@ -22560,34 +14386,6 @@ export interface PathsDictionary { ): OperationResponse } ['/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions']: { - /** - * $listConditionalVariantVersions - $listConditionalVariantVersions - * - * Lists one variant's versions — its whole timeline, oldest first, which is what expanding a row - * of the tree loads. - * - * Its paging differs from the two variant reads: cursor paging only, no `from` and no `size`, - * and **no `hits`**. - * - * Two paging facts a client gets wrong if it assumes otherwise. **A page may be shorter than - * `limit`, or empty, and still carry a `next`**, so a client pages until `next` is absent rather - * than until a page looks short. And **a cursor belongs to one variant and one `order`**: - * replaying one against another variant, or against the opposite order, is a `400` rather than a - * plausible-looking wrong page. - * - * Versions carry no `_revision` here. An editing screen re-reads the one version it is about to - * write through that version's own `GET`, which is strongly consistent, and writes with the - * revision it returns. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. - * - */ - 'get'( - parameters?: Parameters | null, - data?: any, - config?: AxiosRequestConfig - ): OperationResponse /** * $appendConditionalVariantVersion - $appendConditionalVariantVersion * @@ -22601,7 +14399,8 @@ export interface PathsDictionary { * **A version is never refused for being late.** A `valid_from` in the past is written like any * other and answered with warnings in `warnings` naming what it moved — what resolves now, what a * past-dated read returns, or both. Correcting a price that took effect last week is ordinary - * work. + * work; the alternative, deleting and recreating the variant, breaks every order and contract + * pinning its id. * * What is refused is appending at a `valid_from` the variant already has: that write means either * "replace it" or "and also this", and only the caller knows which. The two operations both @@ -22638,10 +14437,13 @@ export interface PathsDictionary { * * Replaces one version's values wholesale, addressed by its `valid_from`. * - * Editable whatever its date, scheduled or past. Writing a superseded version is answered with a - * warning naming what a past-dated read now returns; it is not refused. + * Editable whatever its date, at both ends of the timeline: a scheduled version must stay + * editable so a staged price can be corrected before it goes live rather than accumulating dead + * versions beside it, and a past one must stay editable because correcting history is ordinary + * work. Writing a superseded version is answered with a warning naming what a past-dated read now + * returns; it is not refused. * - * Attributes the variant may not override are not applied where the body carries them, and their + * Attributes the variant may not override are ignored where the body carries them, and their * stored value is preserved rather than dropped. * */ @@ -22656,7 +14458,8 @@ export interface PathsDictionary { * Changes only the fields it names on one version, addressed by its `valid_from`. * * Everything the body does not mention is left as stored. A partial update that tries to change a - * pinned condition value is refused: condition values are immutable after a variant is created. + * pinned condition value is refused: condition values are immutable after a variant is created, + * and this is the path that rule is most likely to be broken on by accident. * */ 'patch'( @@ -22687,112 +14490,6 @@ export interface PathsDictionary { config?: AxiosRequestConfig ): OperationResponse } - ['/v1/conditional-pricing/{slug}/variants:batchUpsert']: { - /** - * $batchUpsertConditionalVariants - $batchUpsertConditionalVariants - * - * Writes up to 100 variants or versions in one call — the endpoint a bulk importer drives a - * refresh cycle through, so hundreds of thousands of keys are a stream of calls rather than a - * call per key. - * - * **One schema in the path, one entity per item.** A single call may name several entities, so - * it can refresh a whole tariff hierarchy — a composite price and its components together — - * and the entity id rides each item instead of the path. - * - * **An item addresses a condition tuple, never a `variant_id`.** An upsert creates a variant - * that has no id yet. The id it created, or found, is on the result entry. - * - * Each item's outcome is derived from what is stored, with no mode for the caller to declare, - * in this order: an unknown tuple is `variant_created`, a known tuple with no version at the - * item's `valid_from` is `version_created`, and an existing version at that exact instant is - * `updated` — or `skipped`, which is reserved for a write whose values are identical to what is - * stored, so re-running an unchanged import still reads as a no-op. `version_created` is - * distinct from `variant_created` so an importer's counts can tell "new postal codes appeared" - * from "existing variants got their scheduled adjustment". - * - * An item without `valid_from` is a current-state, last-write-wins write, and has no `skipped` - * detection. A `valid_from` in the past changes nothing about the outcome — it is written like - * any other and answered with the timeline warnings on that item. An importer stamping one - * `valid_from` across a batch therefore sees backdate warnings on every item; omitting the - * field is how it avoids them. - * - * **Items addressing the same variant apply in array order; items addressing different - * variants are processed in parallel.** Here "the same variant" is the same `(entity_id, - * condition tuple)`, so two items sharing a tuple and a `valid_from` apply in order and the - * last one wins. There is no cross-item rollback. - * - * **This write is unguarded.** No `_revision` is accepted on an item or returned on an entry; - * an editing screen that needs a guard re-reads the one version it is about to write through - * its own `GET`. - * - * Three refusals a client would otherwise expect do not occur here. `VERSION_CONFLICT` never - * does: an existing `valid_from` is a replacement rather than a collision. A tuple-uniqueness - * guard lost to a concurrent writer is not reported as `TUPLE_CONFLICT` either — the item is - * re-read against current state and re-derived through the same outcome order above, which is - * content-aware. `WRITE_CONFLICT` marks the case that is genuinely worth retrying: transient - * contention on one entity's rows. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. The examples below are what an importer builds against in the meantime. - * - */ - 'post'( - parameters?: Parameters | null, - data?: Paths.$BatchUpsertConditionalVariants.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse - } - ['/v1/conditional-pricing/{slug}/variants:batchDelete']: { - /** - * $batchDeleteConditionalVariants - $batchDeleteConditionalVariants - * - * Removes up to 100 variants or versions in one call — the symmetric bulk withdrawal, so - * retiring a generation of variants, or a scheduled adjustment across many of them, is as - * cheap as creating it was. - * - * The noun is `variants` on both batch endpoints, although an item carrying `valid_from` - * removes one **version** rather than the variant: an item without it removes the whole variant - * — its condition tuple, its registration in the index, and every version it accumulated — and - * an item with it removes exactly that version, under the single-item rules. A future version - * and a superseded one are both deletable and both answered with the warnings that say what - * moved; a variant's last remaining version is refused - * (`LAST_VERSION_UNDELETABLE`), because such a variant would still hold its tuple and still - * resolve to nothing. Delete the variant instead. - * - * **An item addresses its variant one of two ways, and never both**: by `variant_id`, or by the - * condition tuple it pins. Use ids once the schema has drifted: a tuple naming a condition the - * schema no longer declares cannot be canonicalized, so it addresses nothing. An item naming - * both fails validation and is an envelope `400`, not a per-item error: the request validator - * rejects the body before any item runs. - * - * **`entity_id` is required beside a `variant_id`, and is not redundant.** A variant id alone - * addresses nothing in this API. - * - * **Items addressing the same variant apply in array order; items addressing different variants - * are processed in parallel.** Because an item addresses its variant two ways, "the same - * variant" is decided after addressing, in three steps: every condition tuple is resolved to a - * variant id, items are grouped by that id, and each group is applied in array order. So one - * call may hold an item naming `var-46045` and an item naming the tuple that variant pins, and - * the guarantee holds across both. There is no cross-item rollback. - * - * **An item that addresses nothing is `skipped` — but only when the variant or the version is - * what is missing.** A missing *entity* is a per-item `ENTITY_NOT_FOUND`. - * - * An interrupted call is safe to send again. A whole-variant delete frees the tuple in its - * first phase and removes the version rows afterwards, so a re-run picks up where it stopped - * and reports `skipped` for what has already gone. Nothing is archived: a variant an order or - * contract pins stops resolving, and a pinned `:resolve` naming it answers `VARIANT_NOT_FOUND`. - * - * **Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers - * `501`. - * - */ - 'post'( - parameters?: Parameters | null, - data?: Paths.$BatchDeleteConditionalVariants.RequestBody, - config?: AxiosRequestConfig - ): OperationResponse - } } export type Client = OpenAPIClient @@ -22816,20 +14513,6 @@ export type BasePriceItemCommon = Components.Schemas.BasePriceItemCommon; export type BasePriceItemDto = Components.Schemas.BasePriceItemDto; export type BasicAuthCredentials = Components.Schemas.BasicAuthCredentials; export type BasicAuthIntegration = Components.Schemas.BasicAuthIntegration; -export type BatchDeleteByConditions = Components.Schemas.BatchDeleteByConditions; -export type BatchDeleteByVariantId = Components.Schemas.BatchDeleteByVariantId; -export type BatchDeleteCounts = Components.Schemas.BatchDeleteCounts; -export type BatchDeleteItem = Components.Schemas.BatchDeleteItem; -export type BatchDeleteOutcome = Components.Schemas.BatchDeleteOutcome; -export type BatchDeleteResult = Components.Schemas.BatchDeleteResult; -export type BatchDeleteResultEntry = Components.Schemas.BatchDeleteResultEntry; -export type BatchDeleteVariantsRequest = Components.Schemas.BatchDeleteVariantsRequest; -export type BatchUpsertCounts = Components.Schemas.BatchUpsertCounts; -export type BatchUpsertItem = Components.Schemas.BatchUpsertItem; -export type BatchUpsertOutcome = Components.Schemas.BatchUpsertOutcome; -export type BatchUpsertResult = Components.Schemas.BatchUpsertResult; -export type BatchUpsertResultEntry = Components.Schemas.BatchUpsertResultEntry; -export type BatchUpsertVariantsRequest = Components.Schemas.BatchUpsertVariantsRequest; export type BillingPeriod = Components.Schemas.BillingPeriod; export type CartDto = Components.Schemas.CartDto; export type CashbackAmount = Components.Schemas.CashbackAmount; @@ -22844,6 +14527,7 @@ export type CheckoutMode = Components.Schemas.CheckoutMode; export type CompositePrice = Components.Schemas.CompositePrice; export type CompositePriceItem = Components.Schemas.CompositePriceItem; export type CompositePriceItemDto = Components.Schemas.CompositePriceItemDto; +export type ComputePriceInputs = Components.Schemas.ComputePriceInputs; export type ComputePriceParams = Components.Schemas.ComputePriceParams; export type ComputePriceParamsBase = Components.Schemas.ComputePriceParamsBase; export type ComputePriceParamsGas = Components.Schemas.ComputePriceParamsGas; @@ -22894,13 +14578,10 @@ export type GasMarketAreaDetails = Components.Schemas.GasMarketAreaDetails; export type HistoricMarketPriceRecord = Components.Schemas.HistoricMarketPriceRecord; export type HistoricMarketPricesResult = Components.Schemas.HistoricMarketPricesResult; export type HydratedCompositePrice = Components.Schemas.HydratedCompositePrice; -export type InertOverride = Components.Schemas.InertOverride; -export type InertOverrideReason = Components.Schemas.InertOverrideReason; export type IntegrationAuthCredentials = Components.Schemas.IntegrationAuthCredentials; export type IntegrationCredentialsResult = Components.Schemas.IntegrationCredentialsResult; export type IntegrationId = Components.Schemas.IntegrationId; export type JourneyContext = Components.Schemas.JourneyContext; -export type ListVariantsRequest = Components.Schemas.ListVariantsRequest; export type MarketParticipant = Components.Schemas.MarketParticipant; export type MarkupPricingModel = Components.Schemas.MarkupPricingModel; export type MetaData = Components.Schemas.MetaData; @@ -22919,7 +14600,6 @@ export type OrderStatus = Components.Schemas.OrderStatus; export type PatchVersionRequest = Components.Schemas.PatchVersionRequest; export type PaymentMethod = Components.Schemas.PaymentMethod; export type PinnedConditions = Components.Schemas.PinnedConditions; -export type PinnedResolveOptions = Components.Schemas.PinnedResolveOptions; export type PortalContext = Components.Schemas.PortalContext; export type PowerMarketAreaDetails = Components.Schemas.PowerMarketAreaDetails; export type PowerMeterType = Components.Schemas.PowerMeterType; @@ -22954,9 +14634,6 @@ export type RecurrenceAmountDto = Components.Schemas.RecurrenceAmountDto; export type RecurrenceAmountWithTax = Components.Schemas.RecurrenceAmountWithTax; export type RedeemedPromo = Components.Schemas.RedeemedPromo; export type ReplaceVersionRequest = Components.Schemas.ReplaceVersionRequest; -export type ReportedError = Components.Schemas.ReportedError; -export type ResolveByContextRequest = Components.Schemas.ResolveByContextRequest; -export type ResolveByPinRequest = Components.Schemas.ResolveByPinRequest; export type ResolveConditionalEntityRequest = Components.Schemas.ResolveConditionalEntityRequest; export type ResolveContext = Components.Schemas.ResolveContext; export type ResolveOptions = Components.Schemas.ResolveOptions; @@ -22988,18 +14665,9 @@ export type TotalDetails = Components.Schemas.TotalDetails; export type TypeGetAg = Components.Schemas.TypeGetAg; export type ValidateAvailabilityFileError = Components.Schemas.ValidateAvailabilityFileError; export type ValidateAvailabilityFileResult = Components.Schemas.ValidateAvailabilityFileResult; -export type VariantConditionFilter = Components.Schemas.VariantConditionFilter; export type VariantConditions = Components.Schemas.VariantConditions; -export type VariantList = Components.Schemas.VariantList; -export type VariantListRow = Components.Schemas.VariantListRow; -export type VariantTree = Components.Schemas.VariantTree; -export type VariantTreeRequest = Components.Schemas.VariantTreeRequest; -export type VariantTreeRow = Components.Schemas.VariantTreeRow; -export type VariantTreeRowStatus = Components.Schemas.VariantTreeRowStatus; export type VariantValues = Components.Schemas.VariantValues; export type VariantVersion = Components.Schemas.VariantVersion; -export type VariantVersionList = Components.Schemas.VariantVersionList; -export type VariantVersionSnapshot = Components.Schemas.VariantVersionSnapshot; -export type VersionMoved = Components.Schemas.VersionMoved; -export type WriteWarning = Components.Schemas.WriteWarning; +export type VariantWriteWarning = Components.Schemas.VariantWriteWarning; +export type VersionWriteWarning = Components.Schemas.VersionWriteWarning; export type WrittenVariantVersion = Components.Schemas.WrittenVariantVersion; diff --git a/clients/pricing-client/src/openapi.json b/clients/pricing-client/src/openapi.json index 09b19cc31..4540dc8ea 100644 --- a/clients/pricing-client/src/openapi.json +++ b/clients/pricing-client/src/openapi.json @@ -2534,6 +2534,7 @@ "type": "power", "billing_period": "monthly", "postal_code": "04109", + "city": "Leipzig", "consumption": 3500, "association_id": "123456789" } @@ -2574,6 +2575,13 @@ "amount_decimal": "50.00" } } + }, + "inputs": { + "type": "power", + "consumptionHT": 3500, + "zipCode": "04109", + "city": "Leipzig", + "billingPeriod": "monthly" } } } @@ -3458,7 +3466,7 @@ }, "/v1/conditional-pricing:resolve": { "post": { - "description": "Resolves which of a conditional entity's variants apply, and returns each one composed: the\nbase entity overlaid with the values of the version in effect at `as_of`.\n\nResolution is two selections in a fixed order — the variant, then the version by `as_of`. It\nis always scoped to one logical entity, so it stays a cheap, predictable lookup rather than\nan open search.\n\n**The variant is selected one of two ways, and the body says which.** A `context` describes a\nsituation and is matched against the conditions each variant pins. A `variant_id` names one\nvariant and skips matching entirely. Exactly one of the two: a body carrying both, or\nneither, is a `400`.\n\nMatching follows two rules worth knowing before assembling a context. A condition a variant\ndoes **not** pin matches any value, which is what lets a condition be added to a schema\nwithout breaking the variants that already exist. A condition **missing from `context`**,\nhowever, does not satisfy one a variant pinned: an incomplete integration resolves to\nnothing rather than silently matching another segment's variants.\n\nWhen nothing matches, the entity's `default` variant is returned if it has one. There is no\nimplicit fallback to the unmodified base entity: an empty `results` means nothing applies to\nthis situation, and the base entity's values are not an answer to it. A pin does not reach\nthat fallback at all: it asks for one variant by name, and answers with it or with a 404.\n\n`options.hydrate` returns the entities a relation attribute references in place of the\nreferences, on either branch.\n\nAvailability is a separate mechanism and is never consulted here.\n", + "description": "Resolves which of a conditional entity's variants apply to a situation, and returns each one\ncomposed: the base entity overlaid with the values of the version in effect at `as_of`.\n\nResolution is two selections in a fixed order — the variant, by matching `context` against\nthe conditions each variant pins; then the version, by `as_of`. It is always scoped to one\nlogical entity, so it stays a cheap, predictable lookup rather than an open search.\n\nMatching follows two rules worth knowing before assembling a context. A condition a variant\ndoes **not** pin matches any value, which is what lets a condition be added to a schema\nwithout breaking the variants that already exist. A condition **missing from `context`**,\nhowever, does not satisfy one a variant pinned: an incomplete integration resolves to\nnothing rather than silently matching another segment's variants.\n\nWhen nothing matches, the entity's `default` variant is returned if it has one. There is no\nimplicit fallback to the unmodified base entity — its values are the ones no variant\noverrode, which is not an answer to \"what applies here\".\n\nAvailability is a separate mechanism and is never consulted here.\n", "operationId": "$resolveConditionalEntity", "summary": "$resolveConditionalEntity", "tags": [ @@ -3470,119 +3478,23 @@ "application/json": { "schema": { "$ref": "#/components/schemas/ResolveConditionalEntityRequest" - }, - "examples": { - "Pin a variant at a recorded instant": { - "summary": "What an order shows — the numbers the customer agreed to", - "value": { - "schema": "price", - "entity_id": "price-sp26d1yo", - "variant_id": "var-46045", - "as_of": "2026-01-01T00:00:00Z" - } - }, - "Pin a variant as it stands now": { - "summary": "What a contract shows — what is billable today", - "value": { - "schema": "price", - "entity_id": "price-sp26d1yo", - "variant_id": "var-46045" - } - }, - "Match a context, hydrating relations": { - "summary": "A composite price and its components in one round trip", - "value": { - "schema": "price", - "entity_id": "price-composite-9f2", - "context": { - "postal_code": "46045" - }, - "options": { - "hydrate": true - } - } - } } } } }, "responses": { "200": { - "description": "The variants that apply, each composed with the version in effect. Empty when nothing\napplies and the entity has no `default` variant. With `resolve_one`, exactly one result;\nwith a pin, exactly one or a 404.\n", + "description": "The variants that apply, each composed with the version in effect. Empty when nothing\napplies and the entity has no `default` variant. With `resolve_one`, exactly one result.\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResolvedVariants" - }, - "examples": { - "A hydrated composite price": { - "summary": "`price_components` holds the component entities the variant's override names, fetched after composition", - "value": { - "results": [ - { - "_id": "price-composite-9f2", - "_variant_id": "var-46045", - "_version_valid_from": "2027-01-01T00:00:00.000Z", - "_conditions": { - "postal_code": "46045", - "default": false - }, - "_inert_overrides": [], - "_schema": "price", - "is_composite_price": true, - "price_components": [ - { - "_id": "price-base-fee-46045", - "_schema": "price", - "unit_amount": 1290, - "unit_amount_currency": "EUR" - }, - { - "_id": "price-kwh-46045", - "_schema": "price", - "unit_amount": 32, - "unit_amount_currency": "EUR" - } - ] - } - ] - } - }, - "A variant carrying overrides that did not apply": { - "summary": "`unit_amount_currency` reads as the entity's own value rather than the variant's, and `_inert_overrides` says why each stored override was passed over", - "value": { - "results": [ - { - "_id": "price-sp26d1yo", - "_variant_id": "var-46045", - "_version_valid_from": "2027-01-01T00:00:00.000Z", - "_conditions": { - "postal_code": "46045", - "default": false - }, - "_inert_overrides": [ - { - "attribute": "unit_amount_currency", - "reason": "ATTRIBUTE_NOT_OVERRIDABLE" - }, - { - "attribute": "legacy_surcharge", - "reason": "ATTRIBUTE_UNDECLARED" - } - ], - "_schema": "price", - "unit_amount": 2499, - "unit_amount_currency": "EUR" - } - ] - } - } } } } }, "400": { - "description": "The context is not usable against this schema: it names an undefined condition\n(`CONDITION_UNDEFINED`), applies an operator the condition's type does not support\n(`OPERATOR_UNSUPPORTED`), carries a value malformed for its type (`CONTEXT_FORMAT_INVALID`),\nor selects more variants than one response may carry (`TOO_MANY_MATCHES`).\n\nOr the body did not pick a branch: it carries both `context` and `variant_id`, or\nneither, or sends `resolve_one` beside a pin. Those are request-validation failures, so\nthey carry a message and neither `code` nor `details` — testing `code` for absence is how\na client tells one from the four coded failures above.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The context is not usable against this schema: it names an undefined condition\n(`CONDITION_UNDEFINED`), applies an operator the condition's type does not support\n(`OPERATOR_UNSUPPORTED`), carries a value malformed for its type (`CONTEXT_FORMAT_INVALID`),\nor selects more variants than one response may carry (`TOO_MANY_MATCHES`).\n", "content": { "application/json": { "schema": { @@ -3592,7 +3504,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`) or entity (`ENTITY_NOT_FOUND`).\n\nOn the pinned branch: the entity has no such variant, or the variant belongs to another\nentity (`VARIANT_NOT_FOUND`), or it has no version in effect at `as_of` because its first\none is later (`NO_ACTIVE_VERSION`, carrying the instant in `details.as_of`). Context\nmatching drops such a variant from the results instead — a set may lose a member where a\npin naming one cannot answer with silence. It is not `VERSION_NOT_FOUND`: a pin names no\n`valid_from`, and the variant's versions all exist — none is in effect yet.\n\nOn the context branch, with `resolve_one`: nothing applied to the context and the entity\nhas no `default` variant (`NO_MATCHES`). That says the addressing was right and nothing\nserves this situation; without `resolve_one` it is a `200` carrying an empty `results`.\n", + "description": "No such schema or entity, or — with `resolve_one` — nothing applied and the entity has no\n`default` variant (`NOT_FOUND`).\n", "content": { "application/json": { "schema": { @@ -3610,23 +3522,13 @@ } } } - }, - "501": { - "description": "A field published ahead of its behaviour was used: `variant_id`, or `options.hydrate` set\nto `true`. Declining it is how a deployed stage says the field exists and does not work\nyet, rather than quietly returning the `default` variant or unhydrated references.\n\nAnswered ahead of every other check, so a body that also names a schema that does not\nexist gets this rather than a `404`.\n\nRead `message`. The body is the shared `Error` shape rather than\n`ConditionalPricingError` — there is no code for \"not built yet\" — as it is on every 501\nthis API answers, so one branch covers all of them.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } } } } }, "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants": { "post": { - "description": "Creates one variant of a conditional entity, together with the first version carrying its\nvalues: a variant always has at least one version.\n\nThe body pins the situation the variant applies to. Pins are exact values only — predicates\nare a read-side concept and are rejected here — and are stored canonicalized for their\ncondition's type, so two spellings of one instant, or one town written two ways, are one\nvariant rather than two that no context can tell apart.\n\nThree write rules are worth knowing before the first call:\n\n- A variant must pin at least one condition or be marked `default`. A variant pinning nothing\n would be a universal wildcard matching every resolve, which is a far more dangerous thing\n than a fallback and far easier to create by accident.\n- `default` is a property of the variant, set by the `default` flag, and is never a value in\n `conditions` — not even `false`. A `default` variant cannot pin anything else, and an entity\n can have only one; a second is refused as `TUPLE_CONFLICT`. Any entity may have one;\n nothing is declared in the schema to allow it.\n- Condition values are immutable afterwards. A variant's identity is the situation it applies\n to, and orders and contracts pin it. **A condition added to a schema that already has\n variants is effectively one-way**: every existing variant is a wildcard on the new\n dimension, but the first variant that pins it is ambiguous against all of them, and\n retro-pinning the others is blocked by this same rule.\n\nAttribute values are applied only for attributes currently carrying `overridable_attribute`.\nMetadata and non-overridable fields present in the body are not applied rather than rejected,\nand every one but the metadata is named in the response's `warnings`, so a client working from\na slightly stale schema snapshot still succeeds and still learns which fields did not land.\nMetadata is never named, since a client echoing back a payload it read carries it in every\nbody.\n\n`variant_id` is always server-generated and returned, and is not accepted in the body — the\nrequest schema admits no such property. It is the durable key orders and contracts pin.\n", + "description": "Creates one variant of a conditional entity, together with the first version carrying its\nvalues. Never two calls: a variant that existed without a version would be an entity holding\na condition tuple it cannot answer with.\n\nThe body pins the situation the variant applies to. Pins are exact values only — predicates\nare a read-side concept and are rejected here — and are stored canonicalized for their\ncondition's type, so two spellings of one instant, or one town written two ways, are one\nvariant rather than two that no context can tell apart.\n\nThree write rules are worth knowing before the first call:\n\n- A variant must pin at least one condition or be marked `default`. A variant pinning nothing\n would be a universal wildcard matching every resolve, which is a far more dangerous thing\n than a fallback and far easier to create by accident.\n- `default` is a property of the variant, set by the `default` flag, and is never a value in\n `conditions` — not even `false`. A `default` variant cannot pin anything else, and an entity\n can have only one, enforced by the ordinary condition-tuple guard rather than by a rule of\n its own. Any entity may have one; nothing is declared in the schema to allow it.\n- Condition values are immutable afterwards. A variant's identity is the situation it applies\n to, and orders and contracts pin it. **A condition added to a schema that already has\n variants is effectively one-way**: every existing variant is a wildcard on the new\n dimension, but the first variant that pins it is ambiguous against all of them, and\n retro-pinning the others is blocked by this same rule.\n\nAttribute values are applied only for attributes currently carrying `overridable_attribute`.\nMetadata and non-overridable fields present in the body are ignored rather than rejected, so a\nclient working from a slightly stale schema snapshot still succeeds.\n\n`variant_id` is always server-generated and returned, and is not accepted in the body — the\nrequest schema admits no such property. It is the durable key orders and contracts pin, so it\ncannot be something two independent importers could collide on.\n", "operationId": "$createConditionalVariant", "summary": "$createConditionalVariant", "tags": [ @@ -3671,51 +3573,12 @@ "application/json": { "schema": { "$ref": "#/components/schemas/CreatedVariant" - }, - "examples": { - "A body naming attributes this variant may not override": { - "summary": "The write succeeded and `values` holds what was stored, so the two attributes the warning names are absent from it", - "value": { - "variant_id": "var-46045", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "46045", - "default": false - }, - "valid_from": "2027-01-01T00:00:00.000Z", - "values": { - "unit_amount": 2499 - }, - "_created_at": "2026-12-01T09:15:00.000Z", - "_updated_at": "2026-12-01T09:15:00.000Z", - "_revision": 1, - "warnings": [ - { - "code": "ATTRIBUTES_NOT_APPLIED", - "message": "The values sent for 2 attributes were not applied: unit_amount_currency, legacy_surcharge", - "details": { - "attributes": [ - { - "attribute": "unit_amount_currency", - "reason": "ATTRIBUTE_NOT_OVERRIDABLE" - }, - { - "attribute": "legacy_surcharge", - "reason": "ATTRIBUTE_UNDECLARED" - } - ] - } - } - ] - } - } } } } }, "400": { - "description": "The variant cannot be created as described: it pins nothing and is not the default\n(`VARIANT_UNPINNED`), pins a condition the schema does not declare\n(`CONDITION_UNDEFINED`), pins a `select` value the condition's vocabulary does not admit\n(`CONDITION_VALUE_INVALID`), carries a value malformed for its condition's type\n(`PIN_FORMAT_INVALID`), or the entity already holds every variant it may hold\n(`VARIANT_LIMIT_REACHED`).\n\nSeveral refusals on this response carry no code, and testing `code` for absence is how\nthey are told from the five above: pinning the fallback marker directly under either of\nits names (`default` or `_default`), marking a variant `default` while it also pins a\nreal condition, pinning a condition whose declared type this deploy cannot read, and a\n`valid_from` this store cannot sort by. Each is an integration mistake rather than one\nbad row in a source file.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The variant cannot be created as described: it pins nothing and is not the default, pins\na condition the schema does not declare (`CONDITION_UNDEFINED`), pins a `select` value\noutside the vocabulary the condition declares (`CONDITION_VALUE_INVALID`), pins the\nfallback marker directly under either of its names (`default` or `_default`), carries a\nvalue malformed for its condition's type, or the entity already holds every variant it\nmay hold.\n", "content": { "application/json": { "schema": { @@ -3725,7 +3588,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), or no such entity under it (`ENTITY_NOT_FOUND`).\n", + "description": "No such schema, or no such entity (`NOT_FOUND`).", "content": { "application/json": { "schema": { @@ -3747,11 +3610,11 @@ } } }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants:list": { - "post": { - "description": "Lists a conditional entity's variants and the conditions each one pins — the browse, filter\nand search read behind the Entity UI's variant screens.\n\nA `POST` because the condition filter is a structured object and needs a body; nothing is\nwritten. Every property in that body is optional, so `{}` is the whole of \"the first ten\nvariants, in `variant_id` order\" — but the body itself is required, so send `{}` rather than\nnothing at all.\n\nThree ways to narrow, and they combine. `conditions` filters on the pins themselves and takes\nthe same seven predicates a resolve context does; `search` is free text over pinned values;\n`sort` orders by one pin. **A variant matches the filter only where it pins the condition** —\nthe one place a filter and a resolve context differ: asking for the variants pinning postal\ncode 46045 does not return every variant that pins no postal code at all.\n\nRows report what is *stored*, not what resolves: no version data, no `_revision` and no\n`_inert_overrides`.\n\nPaging is by offset for the first pages and by an opaque `cursor` beyond them. `size` defaults\nto 10 and is clamped at 1000; a `from` past the offset window is refused rather than clamped,\nand the refusal names the cursor to continue with.\n\n**Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers\n`501`. The examples below are what a consumer builds against in the meantime.\n", - "operationId": "$listConditionalVariants", - "summary": "$listConditionalVariants", + "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}": { + "get": { + "description": "Returns the version of this variant that is currently in effect — the one with the latest\n`valid_from` at or before now.\n\nThe \"open this variant\" read: no date arithmetic is asked of the caller, and what comes back\ncarries the `_revision` a write to that version has to be sent with, so an editing screen can\nload and save without working out which version it is looking at.\n\nWhat is returned is the version's own attribute overrides, not the base entity overlaid with\nthem. Composing the two is what `:resolve` answers.\n\nA variant staged ahead of its launch has versions but none of them in effect, and is reported\nas having none rather than as not existing — the two are fixed differently.\n", + "operationId": "$getActiveConditionalVariantVersion", + "summary": "$getActiveConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -3759,7 +3622,7 @@ { "in": "path", "name": "slug", - "description": "The conditional entity type the variants belong to", + "description": "The conditional entity type this variant belongs to", "schema": { "$ref": "#/components/schemas/ConditionalEntitySlug" }, @@ -3769,107 +3632,37 @@ { "in": "path", "name": "entity_id", - "description": "The conditional entity whose variants to list", + "description": "The conditional entity the variant belongs to", "schema": { "type": "string" }, "required": true, "example": "price-sp26d1yo" + }, + { + "in": "path", + "name": "variant_id", + "description": "The variant whose timeline this call addresses", + "schema": { + "type": "string" + }, + "required": true, + "example": "var-46045" } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListVariantsRequest" - }, - "examples": { - "The first page": { - "summary": "The smallest valid body — the first ten variants, in `variant_id` order", - "value": {} - }, - "Find the entity's fallback variant": { - "summary": "The variant served when nothing else applies — at most one per entity", - "value": { - "conditions": { - "default": true - } - } - }, - "Filter, search and sort together": { - "summary": "The variants pinning a consumption band in either segment, ordered by postal code", - "value": { - "conditions": { - "segment": { - "in": [ - "private", - "commercial" - ] - }, - "consumption": { - "lt": 5000 - } - }, - "search": "460", - "sort": "conditions.postal_code:asc", - "size": 25 - } - }, - "Continue past the offset window": { - "summary": "What a caller sends instead of the `from` that was refused", - "value": { - "cursor": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0", - "sort": "conditions.postal_code:asc", - "size": 25 - } - } - } - } - } - }, "responses": { "200": { - "description": "The page of matching variants, and how many match in total", + "description": "The version, as stored", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VariantList" - }, - "examples": { - "A page of a postal-code price": { - "summary": "Two of 8,128 matches, with the cursor that continues the listing", - "value": { - "hits": 8128, - "results": [ - { - "variant_id": "var-46045", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "46045", - "default": false - } - }, - { - "variant_id": "var-50667", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "50667", - "default": false - } - } - ], - "next": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0" - } - } + "$ref": "#/components/schemas/VariantVersion" } } } }, "400": { - "description": "The listing cannot be served as described.\n\nThe filter is checked against the schema exactly as a resolve context is, by the same\ncode, so it reports the same three codes: a condition the schema does not declare\n(`CONDITION_UNDEFINED`), a predicate the condition's type does not support\n(`OPERATOR_UNSUPPORTED`), or a value malformed for its type (`CONTEXT_FORMAT_INVALID`).\n\nTwo paging refusals carry codes of their own, and the fix for each is a different request:\na `from` plus `size` reaching past the offset window (`OFFSET_WINDOW_EXCEEDED`, naming all\nthree numbers in `details`; page on with the last response's `next` instead), and a\n`cursor` that is malformed or was issued for a different listing (`CURSOR_INVALID`; start\nthe listing again without one).\n\nA `sort` naming something other than a `conditions.` of a sortable type carries a\nmessage and neither `code` nor `details`, as does a body this schema rejects outright.\nTesting `code` for absence is how those are told from the five above.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "Invalid request, e.g. the slug names no conditional entity type.\n", "content": { "application/json": { "schema": { @@ -3879,7 +3672,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), or no such entity under it (`ENTITY_NOT_FOUND`).\n\nAn entity that exists and has no variants is a `200` carrying an empty `results` and\n`hits: 0` — having none is an answer, not a missing resource.\n", + "description": "No such variant under this schema, or it has no version at the instant addressed\n(`NOT_FOUND`). A variant whose versions are all still scheduled has none in effect, which is\nreported as such rather than as a missing variant.\n", "content": { "application/json": { "schema": { @@ -3887,25 +3680,13 @@ } } } - }, - "501": { - "description": "Published ahead of the behaviour. This operation is declared and not yet dispatched, so\nevery request to it is answered here until the listing behaviour lands — which is how a\ndeployed stage says \"this exists and does not work yet\" rather than answering with an\nempty page a client would read as an empty entity.\n\nRead `message`. The body is the shared `Error` shape, as it is on every 501 this API\nanswers, so one \"not built yet\" branch covers all of them.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } } } - } - }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants:tree": { - "post": { - "description": "The variants list, each row carrying the version in effect at `as_of` — the Entity UI's main\nediting screen in one call rather than one call per row.\n\nEverything the variants list accepts, filtering, search, sort and paging alike, means the same\nhere. Three differences, all from the version lookup each row costs: the body takes an\n`as_of`, `size` is clamped at 100 rather than 1000, and a variant with no version to show is\nomitted from `results` (see `VariantTree`).\n\nEvery row carries a `version`, and a `status` saying which one it got. A variant always has at\nleast one version, so at any instant either a version is in effect (`active`) or every\nversion of that variant is still ahead of it (`scheduled`) — in which case `version` is that\nupcoming first one, which is what makes a staged variant visible on the screen rather than\nblank.\n\nThe version on a row carries no `_revision`. An editing screen re-reads the one version it is\nabout to write through that version's own `GET`, which is strongly consistent, and writes with\nthe revision it returns.\n\nThe base entity is not part of this response. The screen's standard-price row is an ordinary\nentity read, and a variant's full timeline is the versions list.\n\n**Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers\n`501`.\n", - "operationId": "$getConditionalVariantTree", - "summary": "$getConditionalVariantTree", + }, + "put": { + "description": "Replaces the values of the version currently in effect, wholesale.\n\nThe body is the complete set of attribute overrides: an attribute the variant may override and\nthat is absent from it stops being overridden. Attributes the variant may **not** override are\nignored where the body carries them, and their stored value is kept rather than dropped — a\nroutine full-snapshot write must not erase an override the moment its attribute's flag happens\nto be off.\n\nEditing the version in effect is the ordinary way a live price is corrected, and warns about\nnothing: what changes is what that version *says*, not which version is in effect.\n\nNeither `valid_from` nor `conditions` can be changed here. Both are accepted when they match\nwhat is stored, so a client building its body from the version it loaded need not strip them\nout first, and both are refused when they name something else.\n", + "operationId": "$replaceActiveConditionalVariantVersion", + "summary": "$replaceActiveConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -3913,7 +3694,7 @@ { "in": "path", "name": "slug", - "description": "The conditional entity type the variants belong to", + "description": "The conditional entity type this variant belongs to", "schema": { "$ref": "#/components/schemas/ConditionalEntitySlug" }, @@ -3923,12 +3704,22 @@ { "in": "path", "name": "entity_id", - "description": "The conditional entity whose variants to list", + "description": "The conditional entity the variant belongs to", "schema": { "type": "string" }, "required": true, "example": "price-sp26d1yo" + }, + { + "in": "path", + "name": "variant_id", + "description": "The variant whose timeline this call addresses", + "schema": { + "type": "string" + }, + "required": true, + "example": "var-46045" } ], "requestBody": { @@ -3936,111 +3727,24 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VariantTreeRequest" - }, - "examples": { - "The screen as it opens": { - "summary": "The first page as of now, ordered by postal code", - "value": { - "sort": "conditions.postal_code:asc", - "size": 25 - } - }, - "The screen at a future date": { - "summary": "What the table will look like once next year's versions take effect", - "value": { - "as_of": "2027-03-15T00:00:00Z", - "conditions": { - "postal_code": { - "in": [ - "46045", - "50667" - ] - } - }, - "size": 25 - } - } + "$ref": "#/components/schemas/ReplaceVersionRequest" } } } }, "responses": { "200": { - "description": "The page of matching variants, each with the version its `status` names", + "description": "The version, as the write left it, together with anything the write moved", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VariantTree" - }, - "examples": { - "One live row and one staged row": { - "summary": "A variant whose version is in effect, beside one whose first version is still ahead of `as_of`", - "value": { - "hits": 8128, - "results": [ - { - "variant_id": "var-46045", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "46045", - "default": false - }, - "status": "active", - "version": { - "variant_id": "var-46045", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "46045", - "default": false - }, - "valid_from": "2026-01-01T00:00:00.000Z", - "values": { - "unit_amount": 3261, - "unit_amount_decimal": "32.61" - }, - "_created_at": "2025-11-14T09:12:44.101Z", - "_updated_at": "2025-11-14T09:12:44.101Z" - } - }, - { - "variant_id": "var-50667", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "50667", - "default": false - }, - "status": "scheduled", - "version": { - "variant_id": "var-50667", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "50667", - "default": false - }, - "valid_from": "2027-01-01T00:00:00.000Z", - "values": { - "unit_amount": 3412, - "unit_amount_decimal": "34.12" - }, - "_created_at": "2026-08-02T16:40:03.882Z", - "_updated_at": "2026-08-02T16:40:03.882Z" - } - } - ], - "next": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0" - } - } + "$ref": "#/components/schemas/WrittenVariantVersion" } } } }, "400": { - "description": "The listing cannot be served as described — the variants list's `400` word for word, plus\nan `as_of` that is not a timestamp this API can read.\n\nThe filter is checked against the schema exactly as a resolve context is, by the same\ncode, so it reports the same three codes: a condition the schema does not declare\n(`CONDITION_UNDEFINED`), a predicate the condition's type does not support\n(`OPERATOR_UNSUPPORTED`), or a value malformed for its type (`CONTEXT_FORMAT_INVALID`).\n\nTwo paging refusals carry codes of their own, and the fix for each is a different request:\na `from` plus `size` reaching past the offset window (`OFFSET_WINDOW_EXCEEDED`, naming all\nthree numbers in `details`; page on with the last response's `next` instead), and a\n`cursor` that is malformed or was issued for a different listing (`CURSOR_INVALID`; start\nthe listing again without one).\n\nA `sort` naming something other than a `conditions.` of a sortable type carries a\nmessage and neither `code` nor `details`, as does a body this schema rejects outright.\nTesting `code` for absence is how those are told from the five above.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n", "content": { "application/json": { "schema": { @@ -4050,7 +3754,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), or no such entity under it (`ENTITY_NOT_FOUND`).\n\nAn entity that exists and has no variants is a `200` carrying an empty `results` and\n`hits: 0` — having none is an answer, not a missing resource.\n", + "description": "No such variant under this schema, or it has no version at the instant addressed\n(`NOT_FOUND`). A variant whose versions are all still scheduled has none in effect, which is\nreported as such rather than as a missing variant.\n", "content": { "application/json": { "schema": { @@ -4059,24 +3763,22 @@ } } }, - "501": { - "description": "Published ahead of the behaviour. This operation is declared and not yet dispatched, so\nevery request to it is answered here until the listing behaviour lands — which is how a\ndeployed stage says \"this exists and does not work yet\" rather than answering with an\nempty page a client would read as an empty entity.\n\nRead `message`. The body is the shared `Error` shape, as it is on every 501 this API\nanswers, so one \"not built yet\" branch covers all of them.\n", + "409": { + "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/ConditionalPricingError" } } } } } - } - }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}": { - "get": { - "description": "Returns the version of this variant that is currently in effect — the one with the latest\n`valid_from` at or before now.\n\nThe \"open this variant\" read: no date arithmetic is asked of the caller, and what comes back\ncarries the `_revision` a write to that version has to be sent with, so an editing screen can\nload and save without working out which version it is looking at.\n\nWhat is returned is the version's own attribute overrides, not the base entity overlaid with\nthem. Composing the two is what `:resolve` answers.\n\nA variant staged ahead of its launch has versions but none of them in effect, and is reported\nas having none rather than as not existing — the two are fixed differently.\n", - "operationId": "$getActiveConditionalVariantVersion", - "summary": "$getActiveConditionalVariantVersion", + }, + "patch": { + "description": "Changes only the fields it names on the version currently in effect.\n\nEverything the body does not mention is left as stored — the \"just nudge this number\" write. A\n`null` is a value like any other rather than a deletion; a client that wants an attribute to\nstop being overridden sends the complete snapshot without it through `PUT`.\n\nAttempting to change a pinned condition value is refused here in particular: a partial update\nis the path a caller reaches for by accident, and a variant's conditions are the situation it\napplies to, which the orders and contracts pinning it depend on not shifting.\n", + "operationId": "$patchActiveConditionalVariantVersion", + "summary": "$patchActiveConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -4112,19 +3814,29 @@ "example": "var-46045" } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchVersionRequest" + } + } + } + }, "responses": { "200": { - "description": "The version, as stored", + "description": "The version, as the write left it, together with anything the write moved", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VariantVersion" + "$ref": "#/components/schemas/WrittenVariantVersion" } } } }, "400": { - "description": "Invalid request, e.g. the slug names no conditional entity type.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n", "content": { "application/json": { "schema": { @@ -4134,7 +3846,17 @@ } }, "404": { - "description": "No entity with that id (`ENTITY_NOT_FOUND`), no such variant under it\n(`VARIANT_NOT_FOUND`), or it has no version in effect at the instant addressed\n(`NO_ACTIVE_VERSION`). A variant whose versions are all still\nscheduled has none in effect, which is reported as such rather than as a missing\nvariant. Selecting the\nversion in effect and reading it are two reads, so a delete landing between them is\nanswered `VERSION_NOT_FOUND`.\n", + "description": "No such variant under this schema, or it has no version at the instant addressed\n(`NOT_FOUND`). A variant whose versions are all still scheduled has none in effect, which is\nreported as such rather than as a missing variant.\n", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConditionalPricingError" + } + } + } + }, + "409": { + "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", "content": { "application/json": { "schema": { @@ -4145,10 +3867,10 @@ } } }, - "put": { - "description": "Replaces the values of the version currently in effect, wholesale.\n\nThe body is the complete set of attribute overrides: an attribute the variant may override and\nthat is absent from it stops being overridden. Attributes the variant may **not** override are\nnot applied where the body carries them, and their stored value is kept rather than dropped.\n\nEditing the version in effect is the ordinary way a live price is corrected, and warns about\nnothing: what changes is what that version *says*, not which version is in effect.\n\nNeither `valid_from` nor `conditions` can be changed here. Both are accepted when they match\nwhat is stored, so a client building its body from the version it loaded need not strip them\nout first, and both are refused when they name something else.\n", - "operationId": "$replaceActiveConditionalVariantVersion", - "summary": "$replaceActiveConditionalVariantVersion", + "delete": { + "description": "Removes one variant of a conditional entity: the condition tuple it holds, its registration\nin the search index, and every version it accumulated.\n\nTwo phases. The first frees the tuple and deregisters the variant, and is what makes the\ncombination of condition values immediately reusable — the second removes the version rows in\nbatches afterwards. A response arrives only once both have finished for this request, but the\ntuple is reusable from the moment the first completes, whether or not the second did: a\nvariant with more versions than one transaction can carry is the ordinary case, not an edge\none. An interrupted delete is safe to send again; it picks up where it stopped.\n\nNothing is archived. A variant an order or contract pins stops resolving, and hydration drops\nthe reference leniently rather than failing the read.\n\nThis removes the **variant**, not one of its versions. To remove a single version, name it on\n`…/variants/{variant_id}/versions/{valid_from}` — including the one currently in effect, which\ndeliberately has no \"delete whichever is live\" shorthand: that is exactly the write nobody\nshould be able to ask for without saying which version they meant.\n", + "operationId": "$deleteConditionalVariant", + "summary": "$deleteConditionalVariant", "tags": [ "Conditional Pricing API" ], @@ -4176,7 +3898,7 @@ { "in": "path", "name": "variant_id", - "description": "The variant whose timeline this call addresses", + "description": "The variant to remove", "schema": { "type": "string" }, @@ -4184,29 +3906,19 @@ "example": "var-46045" } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReplaceVersionRequest" - } - } - } - }, "responses": { "200": { - "description": "The version, as the write left it, together with anything the write moved", + "description": "What the delete removed", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WrittenVariantVersion" + "$ref": "#/components/schemas/DeletedVariant" } } } }, "400": { - "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "Invalid request, e.g. the slug names no conditional entity type", "content": { "application/json": { "schema": { @@ -4216,7 +3928,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), no entity with that id (`ENTITY_NOT_FOUND`), no such\nvariant under it (`VARIANT_NOT_FOUND`), or the variant has no version in effect at the\ninstant addressed (`NO_ACTIVE_VERSION`). A\nvariant whose versions are all still scheduled has none in effect, which is reported as\nsuch rather than as a missing variant. Selecting the\nversion in effect and reading it are two reads, so a delete landing between them is\nanswered `VERSION_NOT_FOUND`.\n", + "description": "This entity has no such variant (`NOT_FOUND`).", "content": { "application/json": { "schema": { @@ -4226,7 +3938,7 @@ } }, "409": { - "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", + "description": "The variant's items are being written concurrently (`WRITE_CONFLICT`, retryable).", "content": { "application/json": { "schema": { @@ -4236,12 +3948,14 @@ } } } - }, - "patch": { - "description": "Changes only the fields it names on the version currently in effect.\n\nEverything the body does not mention is left as stored — the \"just nudge this number\" write. A\n`null` is a value like any other rather than a deletion; a client that wants an attribute to\nstop being overridden sends the complete snapshot without it through `PUT`.\n\nAttempting to change a pinned condition value is refused, as on every version write: a\nvariant's conditions are fixed at creation.\n", - "operationId": "$patchActiveConditionalVariantVersion", - "summary": "$patchActiveConditionalVariantVersion", - "tags": [ + } + }, + "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions": { + "post": { + "description": "Appends a version to a variant: a new set of values taking effect at its own instant.\n\nThis is how a price changes. No version carries an end date and nothing is superseded\nexplicitly — the version in effect at an instant is simply the one with the latest `valid_from`\nat or before it, so appending a later version is the whole of \"this is the new price from then\non\". A version dated in the future is staged and excluded from resolution until its date.\n\n**A version is never refused for being late.** A `valid_from` in the past is written like any\nother and answered with warnings in `warnings` naming what it moved — what resolves now, what a\npast-dated read returns, or both. Correcting a price that took effect last week is ordinary\nwork; the alternative, deleting and recreating the variant, breaks every order and contract\npinning its id.\n\nWhat is refused is appending at a `valid_from` the variant already has: that write means either\n\"replace it\" or \"and also this\", and only the caller knows which. The two operations both\nexist, on the dated version path.\n\nThe variant's `conditions` are its identity and are fixed at creation; they may be sent back\nunchanged but never changed.\n", + "operationId": "$appendConditionalVariantVersion", + "summary": "$appendConditionalVariantVersion", + "tags": [ "Conditional Pricing API" ], "parameters": [ @@ -4281,14 +3995,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PatchVersionRequest" + "$ref": "#/components/schemas/AppendVersionRequest" } } } }, "responses": { - "200": { - "description": "The version, as the write left it, together with anything the write moved", + "201": { + "description": "The version, as appended, together with anything the write moved", "content": { "application/json": { "schema": { @@ -4298,89 +4012,7 @@ } }, "400": { - "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } - }, - "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), no entity with that id (`ENTITY_NOT_FOUND`), no such\nvariant under it (`VARIANT_NOT_FOUND`), or the variant has no version in effect at the\ninstant addressed (`NO_ACTIVE_VERSION`). A\nvariant whose versions are all still scheduled has none in effect, which is reported as\nsuch rather than as a missing variant. Selecting the\nversion in effect and reading it are two reads, so a delete landing between them is\nanswered `VERSION_NOT_FOUND`.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } - }, - "409": { - "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } - } - } - }, - "delete": { - "description": "Removes one variant of a conditional entity: the condition tuple it holds, its registration\nin the search index, and every version it accumulated.\n\nTwo phases. The first frees the tuple and deregisters the variant, and is what makes the\ncombination of condition values immediately reusable — the second removes the version rows in\nbatches afterwards. A response arrives only once both have finished for this request, but the\ntuple is reusable from the moment the first completes, whether or not the second did: a\nvariant with more versions than one transaction can carry is the ordinary case, not an edge\none. An interrupted delete is safe to send again; it picks up where it stopped.\n\nNothing is archived. A variant an order or contract pins stops resolving, and hydration drops\nthe reference leniently rather than failing the read.\n\nThis removes the **variant**, not one of its versions. To remove a single version, name it on\n`…/variants/{variant_id}/versions/{valid_from}` — including the one currently in effect, which\nhas no shorthand delete: a delete names the version it removes.\n", - "operationId": "$deleteConditionalVariant", - "summary": "$deleteConditionalVariant", - "tags": [ - "Conditional Pricing API" - ], - "parameters": [ - { - "in": "path", - "name": "slug", - "description": "The conditional entity type this variant belongs to", - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "required": true, - "example": "price" - }, - { - "in": "path", - "name": "entity_id", - "description": "The conditional entity the variant belongs to", - "schema": { - "type": "string" - }, - "required": true, - "example": "price-sp26d1yo" - }, - { - "in": "path", - "name": "variant_id", - "description": "The variant to remove", - "schema": { - "type": "string" - }, - "required": true, - "example": "var-46045" - } - ], - "responses": { - "200": { - "description": "What the delete removed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeletedVariant" - } - } - } - }, - "400": { - "description": "Invalid request, e.g. the slug names no conditional entity type.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The version cannot be appended as described: the body would change the variant's conditions,\nor `valid_from` is not a timestamp this store can sort by.\n", "content": { "application/json": { "schema": { @@ -4390,7 +4022,7 @@ } }, "404": { - "description": "No entity with that id (`ENTITY_NOT_FOUND`), or it has no such variant\n(`VARIANT_NOT_FOUND`).\n", + "description": "No such schema, or no such variant under it (`NOT_FOUND`).\n", "content": { "application/json": { "schema": { @@ -4400,7 +4032,7 @@ } }, "409": { - "description": "The variant's items are being written concurrently (`WRITE_CONFLICT`, retryable).", + "description": "The variant already has a version at that `valid_from` (`VERSION_CONFLICT`) — append means\nappend, never an implicit overwrite. Replace or patch that version instead.\n", "content": { "application/json": { "schema": { @@ -4412,11 +4044,11 @@ } } }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions": { + "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions/{valid_from}": { "get": { - "description": "Lists one variant's versions — its whole timeline, oldest first, which is what expanding a row\nof the tree loads.\n\nIts paging differs from the two variant reads: cursor paging only, no `from` and no `size`,\nand **no `hits`**.\n\nTwo paging facts a client gets wrong if it assumes otherwise. **A page may be shorter than\n`limit`, or empty, and still carry a `next`**, so a client pages until `next` is absent rather\nthan until a page looks short. And **a cursor belongs to one variant and one `order`**:\nreplaying one against another variant, or against the opposite order, is a `400` rather than a\nplausible-looking wrong page.\n\nVersions carry no `_revision` here. An editing screen re-reads the one version it is about to\nwrite through that version's own `GET`, which is strongly consistent, and writes with the\nrevision it returns.\n\n**Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers\n`501`.\n", - "operationId": "$listConditionalVariantVersions", - "summary": "$listConditionalVariantVersions", + "description": "Returns one specific version of a variant, by the instant it takes effect — what a form editing\nthat version loads.\n\nExact, never nearest: an instant the variant has no version at is a not-found rather than the\nversion that would be in effect at it. That question is the shorthand read's, or `:resolve`'s.\n", + "operationId": "$getConditionalVariantVersion", + "summary": "$getConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -4444,7 +4076,7 @@ { "in": "path", "name": "variant_id", - "description": "The variant whose timeline to list", + "description": "The variant whose timeline this call addresses", "schema": { "type": "string" }, @@ -4452,105 +4084,29 @@ "example": "var-46045" }, { - "in": "query", - "name": "limit", - "description": "Versions per page. Defaults to 100, which is also the maximum; a larger value is clamped\nsilently. A variant's timeline is usually short enough to fit one page.\n", - "schema": { - "type": "integer", - "minimum": 1, - "default": 100 - }, - "required": false, - "example": 100 - }, - { - "in": "query", - "name": "order", - "description": "Which end of the timeline to read from: `asc` oldest first, `desc` newest first. Defaults\nto `asc`.\n\nBaked into every cursor this read issues: a cursor resumes one direction, and replaying it\nagainst the other is a `400`.\n", - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "asc" - }, - "required": false, - "example": "asc" - }, - { - "in": "query", - "name": "cursor", - "description": "Continue from a previous response's `next`. Opaque: it encodes the position and the order\nit was issued for, and nothing a client should read or construct.\n", + "in": "path", + "name": "valid_from", + "description": "The version to address, by the instant it takes effect.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Written any accepted way: it is\ncanonicalized before it is matched, so the spelling a read returned and the spelling a\nhuman typed address the same version.\n", "schema": { "type": "string" }, - "required": false, - "example": "eyJzayI6IlYjcHJpY2Utc3AyNmQxeW8jdmFyLTQ2MDQ1IzIwMjYtMDEtMDFUMDA6MDA6MDAuMDAwWiIsIm9yZGVyIjoiYXNjIn0" + "required": true, + "example": "2027-01-01T00:00:00.000Z" } ], "responses": { "200": { - "description": "A page of the variant's timeline, and the cursor that continues it", + "description": "The version, as stored", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VariantVersionList" - }, - "examples": { - "A short page that is not the last one": { - "summary": "One version and a `next` — a page shorter than `limit` says nothing about whether the timeline has ended", - "value": { - "results": [ - { - "variant_id": "var-46045", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "46045", - "default": false - }, - "valid_from": "2026-01-01T00:00:00.000Z", - "values": { - "unit_amount": 3261, - "unit_amount_decimal": "32.61" - }, - "_created_at": "2025-11-14T09:12:44.101Z", - "_updated_at": "2025-11-14T09:12:44.101Z" - } - ], - "next": "eyJzayI6IlYjcHJpY2Utc3AyNmQxeW8jdmFyLTQ2MDQ1IzIwMjYtMDEtMDFUMDA6MDA6MDAuMDAwWiIsIm9yZGVyIjoiYXNjIn0" - } - }, - "The last page": { - "summary": "No `next`, which is the only reliable end of the timeline", - "value": { - "results": [ - { - "variant_id": "var-46045", - "entity_id": "price-sp26d1yo", - "schema": "price", - "conditions": { - "postal_code": "46045", - "default": false - }, - "valid_from": "2027-01-01T00:00:00.000Z", - "values": { - "unit_amount": 3412, - "unit_amount_decimal": "34.12" - }, - "_created_at": "2026-08-02T16:40:03.882Z", - "_updated_at": "2026-08-02T16:40:03.882Z" - } - ] - } - } + "$ref": "#/components/schemas/VariantVersion" } } } }, "400": { - "description": "A `cursor` that is malformed, belongs to another variant, or was issued for the opposite\norder is `CURSOR_INVALID`, with `details.reason` saying which. The fix is the same for all\nthree: read the timeline again without a cursor.\n\nA `limit` below 1 and an `order` that is neither `asc` nor `desc` carry a message and\nneither `code` nor `details`; testing `code` for absence is how they are told from the one\nabove.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "Invalid request, e.g. a `valid_from` that is not a timestamp this store can sort by.\n", "content": { "application/json": { "schema": { @@ -4560,7 +4116,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), no such entity under it (`ENTITY_NOT_FOUND`), or the\nentity has no such variant (`VARIANT_NOT_FOUND`) — which is also the answer for a variant\nbelonging to a *different* entity: a variant id alone addresses nothing.\n\nThe entity is established before the timeline is read, so a caller who mistyped the entity\nid is never sent to fix the variant id, and one who sent the wrong slug hears about the\nslug.\n", + "description": "This variant has no version at that instant (`NOT_FOUND`).\n", "content": { "application/json": { "schema": { @@ -4568,23 +4124,13 @@ } } } - }, - "501": { - "description": "Published ahead of the behaviour. This operation is declared and not yet dispatched, so\nevery request to it is answered here until the listing behaviour lands — which is how a\ndeployed stage says \"this exists and does not work yet\" rather than answering with an\nempty page a client would read as an empty entity.\n\nRead `message`. The body is the shared `Error` shape, as it is on every 501 this API\nanswers, so one \"not built yet\" branch covers all of them.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } } } }, - "post": { - "description": "Appends a version to a variant: a new set of values taking effect at its own instant.\n\nThis is how a price changes. No version carries an end date and nothing is superseded\nexplicitly — the version in effect at an instant is simply the one with the latest `valid_from`\nat or before it, so appending a later version is the whole of \"this is the new price from then\non\". A version dated in the future is staged and excluded from resolution until its date.\n\n**A version is never refused for being late.** A `valid_from` in the past is written like any\nother and answered with warnings in `warnings` naming what it moved — what resolves now, what a\npast-dated read returns, or both. Correcting a price that took effect last week is ordinary\nwork.\n\nWhat is refused is appending at a `valid_from` the variant already has: that write means either\n\"replace it\" or \"and also this\", and only the caller knows which. The two operations both\nexist, on the dated version path.\n\nThe variant's `conditions` are its identity and are fixed at creation; they may be sent back\nunchanged but never changed.\n", - "operationId": "$appendConditionalVariantVersion", - "summary": "$appendConditionalVariantVersion", + "put": { + "description": "Replaces one version's values wholesale, addressed by its `valid_from`.\n\nEditable whatever its date, at both ends of the timeline: a scheduled version must stay\neditable so a staged price can be corrected before it goes live rather than accumulating dead\nversions beside it, and a past one must stay editable because correcting history is ordinary\nwork. Writing a superseded version is answered with a warning naming what a past-dated read now\nreturns; it is not refused.\n\nAttributes the variant may not override are ignored where the body carries them, and their\nstored value is preserved rather than dropped.\n", + "operationId": "$replaceConditionalVariantVersion", + "summary": "$replaceConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -4618,6 +4164,16 @@ }, "required": true, "example": "var-46045" + }, + { + "in": "path", + "name": "valid_from", + "description": "The version to address, by the instant it takes effect.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Written any accepted way: it is\ncanonicalized before it is matched, so the spelling a read returned and the spelling a\nhuman typed address the same version.\n", + "schema": { + "type": "string" + }, + "required": true, + "example": "2027-01-01T00:00:00.000Z" } ], "requestBody": { @@ -4625,14 +4181,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AppendVersionRequest" + "$ref": "#/components/schemas/ReplaceVersionRequest" } } } }, "responses": { - "201": { - "description": "The version, as appended, together with anything the write moved", + "200": { + "description": "The version, as the write left it, together with anything the write moved", "content": { "application/json": { "schema": { @@ -4642,7 +4198,7 @@ } }, "400": { - "description": "The version cannot be appended as described: the body would change the variant's conditions,\nor `valid_from` is not a timestamp this store can sort by.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n", "content": { "application/json": { "schema": { @@ -4652,7 +4208,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), no entity with that id (`ENTITY_NOT_FOUND`), or no\nsuch variant under it (`VARIANT_NOT_FOUND`).\n", + "description": "This variant has no version at that instant (`NOT_FOUND`).\n", "content": { "application/json": { "schema": { @@ -4662,7 +4218,7 @@ } }, "409": { - "description": "The variant already has a version at that `valid_from` (`VERSION_CONFLICT`) — append means\nappend, never an implicit overwrite. Replace or patch that version instead.\n", + "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", "content": { "application/json": { "schema": { @@ -4672,13 +4228,11 @@ } } } - } - }, - "/v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions/{valid_from}": { - "get": { - "description": "Returns one specific version of a variant, by the instant it takes effect — what a form editing\nthat version loads.\n\nExact, never nearest: an instant the variant has no version at is a not-found rather than the\nversion that would be in effect at it. That question is the shorthand read's, or `:resolve`'s.\n", - "operationId": "$getConditionalVariantVersion", - "summary": "$getConditionalVariantVersion", + }, + "patch": { + "description": "Changes only the fields it names on one version, addressed by its `valid_from`.\n\nEverything the body does not mention is left as stored. A partial update that tries to change a\npinned condition value is refused: condition values are immutable after a variant is created,\nand this is the path that rule is most likely to be broken on by accident.\n", + "operationId": "$patchConditionalVariantVersion", + "summary": "$patchConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -4724,19 +4278,29 @@ "example": "2027-01-01T00:00:00.000Z" } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PatchVersionRequest" + } + } + } + }, "responses": { "200": { - "description": "The version, as stored", + "description": "The version, as the write left it, together with anything the write moved", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VariantVersion" + "$ref": "#/components/schemas/WrittenVariantVersion" } } } }, "400": { - "description": "Invalid request, e.g. a `valid_from` that is not a timestamp this store can sort by.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n", "content": { "application/json": { "schema": { @@ -4746,7 +4310,17 @@ } }, "404": { - "description": "No entity with that id (`ENTITY_NOT_FOUND`), no such variant under this schema\n(`VARIANT_NOT_FOUND`), or no version at that instant (`VERSION_NOT_FOUND`).\n", + "description": "This variant has no version at that instant (`NOT_FOUND`).\n", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConditionalPricingError" + } + } + } + }, + "409": { + "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", "content": { "application/json": { "schema": { @@ -4757,10 +4331,10 @@ } } }, - "put": { - "description": "Replaces one version's values wholesale, addressed by its `valid_from`.\n\nEditable whatever its date, scheduled or past. Writing a superseded version is answered with a\nwarning naming what a past-dated read now returns; it is not refused.\n\nAttributes the variant may not override are not applied where the body carries them, and their\nstored value is preserved rather than dropped.\n", - "operationId": "$replaceConditionalVariantVersion", - "summary": "$replaceConditionalVariantVersion", + "delete": { + "description": "Removes one version of a variant.\n\nWithdrawing a scheduled adjustment is what this is for, and deleting a future version warns\nabout nothing — nothing that has resolved, or could have resolved, changes. Deleting a version\nthat has taken effect is allowed too and answered with a warning: it changes what a past-dated\nread returns, and if it was the version in effect it changes what resolves now.\n\n**A variant's last remaining version cannot be deleted.** Such a variant would still hold its\ncondition tuple and still be selectable, and then resolve to nothing — which is a variant delete\nwearing a version delete's clothes. Delete the variant instead; that frees the tuple too.\n\nThe variant itself is untouched: it keeps its conditions, its tuple and its place in the index.\n", + "operationId": "$deleteConditionalVariantVersion", + "summary": "$deleteConditionalVariantVersion", "tags": [ "Conditional Pricing API" ], @@ -4804,31 +4378,32 @@ }, "required": true, "example": "2027-01-01T00:00:00.000Z" + }, + { + "in": "query", + "name": "_revision", + "description": "The revision marker read from the version being deleted. The delete is refused if the\nversion has been written since.\n\nA query parameter rather than a body field, since a DELETE carrying a body travels badly\nthrough clients and proxies; it is the same marker the write bodies carry as `_revision`.\n", + "schema": { + "type": "integer", + "minimum": 1 + }, + "required": true, + "example": 3 } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReplaceVersionRequest" - } - } - } - }, "responses": { "200": { - "description": "The version, as the write left it, together with anything the write moved", + "description": "The version removed, together with anything the delete moved", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WrittenVariantVersion" + "$ref": "#/components/schemas/DeletedVariantVersion" } } } }, "400": { - "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", + "description": "The version cannot be removed: it is the variant's only one, `_revision` is missing, or\n`valid_from` is not a timestamp this store can sort by.\n", "content": { "application/json": { "schema": { @@ -4838,7 +4413,7 @@ } }, "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), no entity with that id (`ENTITY_NOT_FOUND`), no such\nvariant under it (`VARIANT_NOT_FOUND`), or no version at that instant\n(`VERSION_NOT_FOUND`).\n", + "description": "This variant has no version at that instant (`NOT_FOUND`).\n", "content": { "application/json": { "schema": { @@ -4858,1221 +4433,610 @@ } } } + } + } + }, + "components": { + "securitySchemes": { + "EpilotAuth": { + "type": "http", + "scheme": "bearer", + "description": "Epilot Bearer Token" }, - "patch": { - "description": "Changes only the fields it names on one version, addressed by its `valid_from`.\n\nEverything the body does not mention is left as stored. A partial update that tries to change a\npinned condition value is refused: condition values are immutable after a variant is created.\n", - "operationId": "$patchConditionalVariantVersion", - "summary": "$patchConditionalVariantVersion", - "tags": [ - "Conditional Pricing API" + "EpilotPublicAuth": { + "type": "http", + "scheme": "bearer", + "description": "Epilot Public Access Bearer Token", + "bearerFormat": "JWT" + } + }, + "schemas": { + "IntegrationId": { + "type": "string", + "enum": [ + "getag", + "external-catalog" + ] + }, + "ConditionalEntitySlug": { + "type": "string", + "description": "Schema slug of an entity type that can be conditional — the `{slug}` of every\nconditional-pricing route.\n", + "enum": [ + "product", + "price", + "coupon" + ] + }, + "ConditionType": { + "type": "string", + "description": "The kind of value a condition holds, which decides how a variant's pinned value is matched\nagainst a resolve context.\n\n- `string`: an arbitrary string, matched exactly and case-sensitively\n- `number`: a numeric value\n- `date`: a single date\n- `daterange`: a window with a from and an until timestamp; both ends may be left open\n- `boolean`: a true/false value\n- `select`: one of the values declared in `options`, unless `allow_any` is set\n- `location`: a geographic value, shaped by `format`\n\nThere is no condition type for the fallback variant. Being the entity's fallback is a\nproperty of the variant, set by the `default` flag on a variant write, and needs nothing\ndeclared in the schema.\n", + "enum": [ + "string", + "number", + "date", + "daterange", + "boolean", + "select", + "location" + ] + }, + "ConditionDefinition": { + "type": "object", + "description": "One condition dimension, in the shape a schema's `conditions` array holds it — copy it in\nverbatim.\n", + "required": [ + "name", + "label", + "type" ], - "parameters": [ - { - "in": "path", - "name": "slug", - "description": "The conditional entity type this variant belongs to", - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "required": true, - "example": "price" - }, - { - "in": "path", - "name": "entity_id", - "description": "The conditional entity the variant belongs to", - "schema": { - "type": "string" - }, - "required": true, - "example": "price-sp26d1yo" + "properties": { + "name": { + "type": "string", + "description": "How variants and resolve contexts refer to this condition. Independent of attribute\nnames: a value needed as an attribute too is duplicated onto the variant.\n\n`default`, and any name beginning with `_`, are reserved for the server: a condition\ndeclared under one is ignored, since nothing could pin it and no context could address it.\n", + "example": "postal_code" }, - { - "in": "path", - "name": "variant_id", - "description": "The variant whose timeline this call addresses", - "schema": { - "type": "string" - }, - "required": true, - "example": "var-46045" + "label": { + "type": "string", + "description": "Human-readable name of the condition.", + "example": "Postal Code" }, - { - "in": "path", - "name": "valid_from", - "description": "The version to address, by the instant it takes effect.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Written any accepted way: it is\ncanonicalized before it is matched, so the spelling a read returned and the spelling a\nhuman typed address the same version.\n", - "schema": { - "type": "string" - }, - "required": true, - "example": "2027-01-01T00:00:00.000Z" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PatchVersionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "The version, as the write left it, together with anything the write moved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WrittenVariantVersion" - } - } - } + "type": { + "$ref": "#/components/schemas/ConditionType" }, - "400": { - "description": "The write cannot be applied as described: it would move the version it addresses to another\n`valid_from`, or change the conditions its variant is pinned to — both identity rather than\ncontent, and both fixed at creation. Also when `_revision` is missing or is not a revision\nmarker.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" + "options": { + "type": "array", + "description": "The declared vocabulary of a `select` condition. Absent for every other type.\n\nThe same shape a `select` attribute's `options` has on the Entity API, item for item: an\nentry is either the value itself or an object carrying that value and an optional display\n`title`. A `title` is never pinned by a variant and never matched — two entries differing\nonly in their title are one vocabulary entry.\n\nEnforced on variant writes, unless `allow_any` is true: a pinned value outside the\nvocabulary is rejected with `CONDITION_VALUE_INVALID`. It is *not* enforced on resolve —\na vocabulary says what may be stored, not what may be asked for, so a context value\noutside it is a query that simply matches nothing.\n", + "items": { + "anyOf": [ + { + "type": "string", + "nullable": true + }, + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "string" + }, + "title": { + "type": "string" + } + } } - } - } + ] + }, + "example": [ + "private", + "commercial" + ] }, - "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`), no entity with that id (`ENTITY_NOT_FOUND`), no such\nvariant under it (`VARIANT_NOT_FOUND`), or no version at that instant\n(`VERSION_NOT_FOUND`).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "allow_any": { + "type": "boolean", + "description": "Allow arbitrary stored values in addition to the declared `options`. Absent means strict:\na variant may only pin a declared option.\n", + "example": false }, - "409": { - "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "format": { + "type": "string", + "description": "The value shape of a `location` condition. Absent for every other type.", + "enum": [ + "zipcode", + "zipcode + town" + ] } } }, - "delete": { - "description": "Removes one version of a variant.\n\nWithdrawing a scheduled adjustment is what this is for, and deleting a future version warns\nabout nothing — nothing that has resolved, or could have resolved, changes. Deleting a version\nthat has taken effect is allowed too and answered with a warning: it changes what a past-dated\nread returns, and if it was the version in effect it changes what resolves now.\n\n**A variant's last remaining version cannot be deleted.** Such a variant would still hold its\ncondition tuple and still be selectable, and then resolve to nothing — which is a variant delete\nwearing a version delete's clothes. Delete the variant instead; that frees the tuple too.\n\nThe variant itself is untouched: it keeps its conditions, its tuple and its place in the index.\n", - "operationId": "$deleteConditionalVariantVersion", - "summary": "$deleteConditionalVariantVersion", - "tags": [ - "Conditional Pricing API" + "ConditionSet": { + "type": "object", + "description": "A named bundle of condition definitions, built in for one entity type.", + "required": [ + "id", + "label", + "description", + "conditions" ], - "parameters": [ - { - "in": "path", - "name": "slug", - "description": "The conditional entity type this variant belongs to", - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "required": true, - "example": "price" - }, - { - "in": "path", - "name": "entity_id", - "description": "The conditional entity the variant belongs to", - "schema": { - "type": "string" - }, - "required": true, - "example": "price-sp26d1yo" + "properties": { + "id": { + "type": "string", + "description": "Identifies the set within this entity type's catalog.", + "example": "delivery_area" }, - { - "in": "path", - "name": "variant_id", - "description": "The variant whose timeline this call addresses", - "schema": { - "type": "string" - }, - "required": true, - "example": "var-46045" + "label": { + "type": "string", + "description": "Human-readable name of the set.", + "example": "Delivery Area" }, - { - "in": "path", - "name": "valid_from", - "description": "The version to address, by the instant it takes effect.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Written any accepted way: it is\ncanonicalized before it is matched, so the spelling a read returned and the spelling a\nhuman typed address the same version.\n", - "schema": { - "type": "string" - }, - "required": true, - "example": "2027-01-01T00:00:00.000Z" + "description": { + "type": "string", + "description": "What the set is for, and when to reach for it." }, - { - "in": "query", - "name": "_revision", - "description": "The revision marker read from the version being deleted. The delete is refused if the\nversion has been written since.\n\nThe same marker the write bodies carry as `_revision`.\n", - "schema": { - "type": "integer", - "minimum": 1 - }, - "required": true, - "example": 3 + "conditions": { + "type": "array", + "description": "The condition definitions to copy into the schema's own `conditions` array.", + "items": { + "$ref": "#/components/schemas/ConditionDefinition" + } } + } + }, + "ConditionSetCatalog": { + "type": "object", + "required": [ + "results" ], - "responses": { - "200": { - "description": "The version removed, together with anything the delete moved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeletedVariantVersion" - } - } + "properties": { + "results": { + "type": "array", + "description": "The condition sets built in for the requested entity type, in the order they are offered.\n", + "items": { + "$ref": "#/components/schemas/ConditionSet" } + } + } + }, + "ConditionalPricingErrorCode": { + "type": "string", + "description": "Machine-readable failure mode of a conditional-pricing operation, allowing clients\nto branch on the kind of failure instead of parsing the error message.\n\n- `NOT_FOUND` (404): the addressed entity, variant or version does not exist\n- `AMBIGUOUS_RESOLUTION` (409): several variants match the given context while a single result was requested\n- `TUPLE_CONFLICT` (409): the condition tuple is already claimed by another variant\n- `VERSION_CONFLICT` (409): a version already exists at the given `valid_from` on that variant\n- `CONDITION_UNDEFINED` (400): the context names a condition the entity's schema does not define\n- `OPERATOR_UNSUPPORTED` (400): the requested operator is not applicable to the condition's type\n- `CONTEXT_FORMAT_INVALID` (400): a context value is malformed for its condition type\n- `CONDITION_VALUE_INVALID` (400): a variant write pins a `select` value the condition's declared `options` do not contain\n- `TOO_MANY_MATCHES` (400): a multi-match resolve exceeded its result cap\n- `WRITE_CONFLICT` (409): transient write contention, retryable unlike `TUPLE_CONFLICT`\n\nEach code is emitted with the HTTP status shown above, and only with that status.\n", + "enum": [ + "NOT_FOUND", + "AMBIGUOUS_RESOLUTION", + "TUPLE_CONFLICT", + "VERSION_CONFLICT", + "CONDITION_UNDEFINED", + "OPERATOR_UNSUPPORTED", + "CONTEXT_FORMAT_INVALID", + "CONDITION_VALUE_INVALID", + "TOO_MANY_MATCHES", + "WRITE_CONFLICT" + ] + }, + "ResolveConditionalEntityRequest": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "entity_id" + ], + "properties": { + "schema": { + "$ref": "#/components/schemas/ConditionalEntitySlug" }, - "400": { - "description": "The version cannot be removed because it is the variant's only one\n(`LAST_VERSION_UNDELETABLE`) — such a variant would keep its condition tuple, stay\nselectable and resolve to nothing, so delete the variant instead, which frees the tuple\ntoo.\n\nThe refusals around it carry no code, and testing `code` for absence is how they are told\nfrom it: a missing or unreadable `_revision`, a `valid_from` this store cannot sort by,\nand an id this store cannot key by.\n\nAlso refused here: an entity id belonging to another type than the slug names\n(`ENTITY_TYPE_MISMATCH`), and an entity that was never created as a conditional one\n(`ENTITY_NOT_CONDITIONAL`).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "entity_id": { + "type": "string", + "description": "The conditional entity to resolve. Resolution is always scoped to exactly one.", + "example": "price-sp26d1yo" }, - "404": { - "description": "No entity with that id (`ENTITY_NOT_FOUND`), no such variant under this schema\n(`VARIANT_NOT_FOUND`), or no version at that instant (`VERSION_NOT_FOUND`).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "context": { + "$ref": "#/components/schemas/ResolveContext" }, - "409": { - "description": "The version has been written since `_revision` was read (`WRITE_CONFLICT`, retryable after\nre-reading the version).\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "as_of": { + "type": "string", + "description": "The instant the version is selected at — the version with the latest `valid_from` at or\nbefore it. Defaults to now. A variant whose first version is later than this is\nscheduled rather than applicable, and is excluded from resolution entirely.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Deliberately not declared as\n`format: date-time`, which would reject the plain-date form that this accepts.\n", + "example": "2027-03-15T00:00:00Z" + }, + "options": { + "$ref": "#/components/schemas/ResolveOptions" } } - } - }, - "/v1/conditional-pricing/{slug}/variants:batchUpsert": { - "post": { - "description": "Writes up to 100 variants or versions in one call — the endpoint a bulk importer drives a\nrefresh cycle through, so hundreds of thousands of keys are a stream of calls rather than a\ncall per key.\n\n**One schema in the path, one entity per item.** A single call may name several entities, so\nit can refresh a whole tariff hierarchy — a composite price and its components together —\nand the entity id rides each item instead of the path.\n\n**An item addresses a condition tuple, never a `variant_id`.** An upsert creates a variant\nthat has no id yet. The id it created, or found, is on the result entry.\n\nEach item's outcome is derived from what is stored, with no mode for the caller to declare,\nin this order: an unknown tuple is `variant_created`, a known tuple with no version at the\nitem's `valid_from` is `version_created`, and an existing version at that exact instant is\n`updated` — or `skipped`, which is reserved for a write whose values are identical to what is\nstored, so re-running an unchanged import still reads as a no-op. `version_created` is\ndistinct from `variant_created` so an importer's counts can tell \"new postal codes appeared\"\nfrom \"existing variants got their scheduled adjustment\".\n\nAn item without `valid_from` is a current-state, last-write-wins write, and has no `skipped`\ndetection. A `valid_from` in the past changes nothing about the outcome — it is written like\nany other and answered with the timeline warnings on that item. An importer stamping one\n`valid_from` across a batch therefore sees backdate warnings on every item; omitting the\nfield is how it avoids them.\n\n**Items addressing the same variant apply in array order; items addressing different\nvariants are processed in parallel.** Here \"the same variant\" is the same `(entity_id,\ncondition tuple)`, so two items sharing a tuple and a `valid_from` apply in order and the\nlast one wins. There is no cross-item rollback.\n\n**This write is unguarded.** No `_revision` is accepted on an item or returned on an entry;\nan editing screen that needs a guard re-reads the one version it is about to write through\nits own `GET`.\n\nThree refusals a client would otherwise expect do not occur here. `VERSION_CONFLICT` never\ndoes: an existing `valid_from` is a replacement rather than a collision. A tuple-uniqueness\nguard lost to a concurrent writer is not reported as `TUPLE_CONFLICT` either — the item is\nre-read against current state and re-derived through the same outcome order above, which is\ncontent-aware. `WRITE_CONFLICT` marks the case that is genuinely worth retrying: transient\ncontention on one entity's rows.\n\n**Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers\n`501`. The examples below are what an importer builds against in the meantime.\n", - "operationId": "$batchUpsertConditionalVariants", - "summary": "$batchUpsertConditionalVariants", - "tags": [ - "Conditional Pricing API" - ], - "parameters": [ - { - "in": "path", - "name": "slug", - "description": "The conditional entity type every item in this call writes under", - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "required": true, - "example": "price" + }, + "ResolveContext": { + "type": "object", + "additionalProperties": true, + "description": "The situation to resolve for: a flat map keyed by condition name, as the entity's schema\ndeclares them. A condition left out of the map is not a wildcard — it matches only variants\nthat leave that condition unpinned.\n\nEach value is either an exact value, typed by its condition, or a single-operator predicate\nobject:\n\n- `{ \"lt\": v }`, `{ \"lte\": v }`, `{ \"gt\": v }`, `{ \"gte\": v }` — order against a `number` or\n `date` condition.\n- `{ \"in\": [...] }` — membership, against a `string`, `select` or `number` condition.\n- `{ \"between\": \"2026-03-01\" }` — the explicit spelling of `daterange` containment; a plain\n date supplied for a `daterange` condition means the same thing.\n- `{ \"exists\": true }` — pinned to any value. `{ \"exists\": false }` says what leaving the key\n out says.\n\nExact values are typed by their condition: a `string` or `select` matches exactly and\ncase-sensitively, with no trimming; a `location` of format `zipcode` is the postal code\nitself, and one of format `zipcode + town` an object carrying both, whose town is compared\ncase- and whitespace-insensitively while its postal code is not.\n\n`default`, and any name beginning with `_`, are reserved for the server and cannot be\nsupplied here.\n", + "example": { + "postal_code": "46045", + "consumption": { + "lt": 5000 + } + } + }, + "ResolveOptions": { + "type": "object", + "additionalProperties": false, + "properties": { + "resolve_one": { + "type": "boolean", + "default": false, + "description": "Ask for an unambiguous answer. Several applicable variants become `AMBIGUOUS_RESOLUTION`\nrather than a set, and nothing applicable becomes `NOT_FOUND` rather than an empty one.\nThe response shape does not change: `results` simply carries exactly one entry.\n" } + } + }, + "ResolvedVariants": { + "type": "object", + "required": [ + "results" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BatchUpsertVariantsRequest" - }, - "examples": { - "A monthly refresh cycle": { - "summary": "Five items across two entities — a new postal code, a scheduled adjustment, a correction, an unchanged row and one bad source row", - "value": { - "correlation_id": "tariff-refresh-2027-01", - "items": [ - { - "entity_id": "price-sp26d1yo", - "conditions": { - "postal_code": "46045" - }, - "valid_from": "2027-01-01T00:00:00Z", - "values": { - "unit_amount": 3261, - "unit_amount_decimal": "32.61" - } - }, - { - "entity_id": "price-sp26d1yo", - "conditions": { - "postal_code": "50667" - }, - "valid_from": "2027-01-01T00:00:00Z", - "values": { - "unit_amount": 3412, - "unit_amount_decimal": "34.12" - } - }, - { - "entity_id": "price-base-fee", - "conditions": { - "postal_code": "50667" - }, - "valid_from": "2027-01-01T00:00:00Z", - "values": { - "unit_amount": 1290, - "unit_amount_decimal": "12.90" - } - }, - { - "entity_id": "price-sp26d1yo", - "conditions": { - "postal_code": "80331" - }, - "valid_from": "2027-01-01T00:00:00Z", - "values": { - "unit_amount": 3120, - "unit_amount_decimal": "31.20", - "description": "Grundpreis 2027" - } - }, - { - "entity_id": "price-sp26d1yo", - "conditions": { - "postal_code": "10115", - "segment": "industrial" - }, - "valid_from": "2027-01-01T00:00:00Z", - "values": { - "unit_amount": 2980, - "unit_amount_decimal": "29.80" - } - } - ] - } - } - } + "properties": { + "results": { + "type": "array", + "description": "One composed payload per applicable variant, capped at 100 — a context selecting more\nthan that is answered with `TOO_MANY_MATCHES` instead, since each result costs its own\nversion lookup. No dominance or specificity ordering is applied between them.\n", + "items": { + "$ref": "#/components/schemas/ResolvedVariant" } } - }, - "responses": { - "200": { - "description": "What every item did, in request order, and a count per outcome.\n\n`200` whatever the per-item outcomes: a batch that processed 100 items and failed 99 did\nits job, and `counts` says what happened.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BatchUpsertResult" - }, - "examples": { - "Every outcome once": { - "summary": "The five items above, in order — the created variant's id is the one an order pins, and item five failed on its own without touching the rest", - "value": { - "correlation_id": "tariff-refresh-2027-01", - "counts": { - "variant_created": 1, - "version_created": 1, - "updated": 1, - "skipped": 1, - "error": 1 - }, - "results": [ - { - "outcome": "variant_created", - "entity_id": "price-sp26d1yo", - "variant_id": "var-46045", - "valid_from": "2027-01-01T00:00:00.000Z", - "warnings": [ - { - "code": "VARIANT_COUNT_APPROACHING_CAP", - "message": "This entity holds 4998 of the 5000 variants it may hold", - "details": { - "variant_count": 4998, - "cap": 5000 - } - } - ] - }, - { - "outcome": "version_created", - "entity_id": "price-sp26d1yo", - "variant_id": "var-50667", - "valid_from": "2027-01-01T00:00:00.000Z", - "warnings": [] - }, - { - "outcome": "updated", - "entity_id": "price-base-fee", - "variant_id": "var-bf-50667", - "valid_from": "2027-01-01T00:00:00.000Z", - "warnings": [] - }, - { - "outcome": "skipped", - "entity_id": "price-sp26d1yo", - "variant_id": "var-80331", - "valid_from": "2027-01-01T00:00:00.000Z", - "warnings": [ - { - "code": "ATTRIBUTES_NOT_APPLIED", - "message": "The value sent for description was not applied", - "details": { - "attributes": [ - { - "attribute": "description", - "reason": "ATTRIBUTE_NOT_OVERRIDABLE" - } - ] - } - } - ] - }, - { - "outcome": "error", - "entity_id": "price-sp26d1yo", - "warnings": [], - "error": { - "message": "The value pinned for condition segment is not one of its declared options", - "code": "CONDITION_VALUE_INVALID", - "details": { - "condition_name": "segment", - "value": "industrial", - "options": [ - "private", - "commercial" - ] - } - } - } - ] - } - } - } - } - } + } + }, + "ResolvedVariant": { + "type": "object", + "additionalProperties": true, + "description": "The entity as this variant leaves it — every attribute of a plain entity read, with the\napplicable version's overrides applied — plus the discriminators saying where the numbers\ncame from.\n", + "required": [ + "_id", + "_variant_id", + "_version_valid_from", + "_conditions" + ], + "properties": { + "_id": { + "type": "string", + "description": "The logical entity's id — the same one a plain entity read returns. Resolution never\nmints a new identity; a variant is a set of values for *this* entity, not another one.\n", + "example": "price-sp26d1yo" }, - "400": { - "description": "The envelope cannot be processed at all: more than 100 items, an empty `items`, a slug\nthat names no conditional entity type, or a body this schema rejects outright.\n\nAll of those are request-validation failures, so they carry a message and neither `code`\nnor `details`. Every failure of an individual item is on that item's result entry\ninstead, `ENTITY_NOT_FOUND` included — the entity id is on the item and not in the path,\nso one wrong id in a source file cannot fail the other 99 rows. `ENTITY_TYPE_MISMATCH`\nand `ENTITY_NOT_CONDITIONAL` are per item for the same reason: each item names its own\nentity, and each entity is checked against the slug and for `is_conditional` on its own.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "_variant_id": { + "type": "string", + "description": "The variant these values came from. Durable: this is what an order or a contract pins to\nread the same numbers back later.\n", + "example": "var-46045" }, - "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`) — the one lookup the whole call depends on, since it\nis what the items are validated against.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "_version_valid_from": { + "type": "string", + "description": "The `valid_from` of the version applied for the requested `as_of`.", + "example": "2027-01-01T00:00:00.000Z" }, - "501": { - "description": "Published ahead of the behaviour. This operation is declared and not yet dispatched, so\nevery request to it is answered here until the batch write behaviour lands — which is how\na deployed stage says \"this exists and does not work yet\" rather than answering with\ncounts a client would read as a completed import.\n\nRead `message`. The body is the shared `Error` shape, as it is on every 501 this API\nanswers, so one \"not built yet\" branch covers all of them.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } + "_conditions": { + "allOf": [ + { + "$ref": "#/components/schemas/VariantConditions" } - } + ], + "description": "The conditions this variant pins, plus the boolean `default` discriminator.\n\nUnderscore-prefixed, like every other discriminator here, so that it cannot collide with\nan attribute an organization happens to have called `conditions`.\n" } } - } - }, - "/v1/conditional-pricing/{slug}/variants:batchDelete": { - "post": { - "description": "Removes up to 100 variants or versions in one call — the symmetric bulk withdrawal, so\nretiring a generation of variants, or a scheduled adjustment across many of them, is as\ncheap as creating it was.\n\nThe noun is `variants` on both batch endpoints, although an item carrying `valid_from`\nremoves one **version** rather than the variant: an item without it removes the whole variant\n— its condition tuple, its registration in the index, and every version it accumulated — and\nan item with it removes exactly that version, under the single-item rules. A future version\nand a superseded one are both deletable and both answered with the warnings that say what\nmoved; a variant's last remaining version is refused\n(`LAST_VERSION_UNDELETABLE`), because such a variant would still hold its tuple and still\nresolve to nothing. Delete the variant instead.\n\n**An item addresses its variant one of two ways, and never both**: by `variant_id`, or by the\ncondition tuple it pins. Use ids once the schema has drifted: a tuple naming a condition the\nschema no longer declares cannot be canonicalized, so it addresses nothing. An item naming\nboth fails validation and is an envelope `400`, not a per-item error: the request validator\nrejects the body before any item runs.\n\n**`entity_id` is required beside a `variant_id`, and is not redundant.** A variant id alone\naddresses nothing in this API.\n\n**Items addressing the same variant apply in array order; items addressing different variants\nare processed in parallel.** Because an item addresses its variant two ways, \"the same\nvariant\" is decided after addressing, in three steps: every condition tuple is resolved to a\nvariant id, items are grouped by that id, and each group is applied in array order. So one\ncall may hold an item naming `var-46045` and an item naming the tuple that variant pins, and\nthe guarantee holds across both. There is no cross-item rollback.\n\n**An item that addresses nothing is `skipped` — but only when the variant or the version is\nwhat is missing.** A missing *entity* is a per-item `ENTITY_NOT_FOUND`.\n\nAn interrupted call is safe to send again. A whole-variant delete frees the tuple in its\nfirst phase and removes the version rows afterwards, so a re-run picks up where it stopped\nand reports `skipped` for what has already gone. Nothing is archived: a variant an order or\ncontract pins stops resolving, and a pinned `:resolve` naming it answers `VARIANT_NOT_FOUND`.\n\n**Published ahead of the behaviour.** No handler serves this yet, so a deployed stage answers\n`501`.\n", - "operationId": "$batchDeleteConditionalVariants", - "summary": "$batchDeleteConditionalVariants", - "tags": [ - "Conditional Pricing API" + }, + "CreateVariantRequest": { + "type": "object", + "additionalProperties": false, + "required": [ + "values" ], - "parameters": [ - { - "in": "path", - "name": "slug", - "description": "The conditional entity type every item in this call removes from", - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "required": true, - "example": "price" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BatchDeleteVariantsRequest" - }, - "examples": { - "A cleanup pass, addressed both ways": { - "summary": "A version withdrawn by the tuple that pins it, a whole variant removed by id, and a version delete that would leave its variant with none", - "value": { - "correlation_id": "postal-code-cleanup-2026-09", - "items": [ - { - "entity_id": "price-sp26d1yo", - "conditions": { - "postal_code": "46045" - }, - "valid_from": "2026-01-01T00:00:00Z" - }, - { - "entity_id": "price-sp26d1yo", - "conditions": { - "postal_code": "99998" - } - }, - { - "entity_id": "price-sp26d1yo", - "variant_id": "var-80331", - "valid_from": "2026-01-01T00:00:00Z" - } - ] - } - } - } - } - } - }, - "responses": { - "200": { - "description": "What every item did, in request order, and a count per outcome.\n\n`200` whatever the per-item outcomes: the call did its job, and `counts` says what\nhappened.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BatchDeleteResult" - }, - "examples": { - "Every outcome once": { - "summary": "The three items above, in order — the second addressed a tuple no variant pins, so it names no variant to have skipped", - "value": { - "correlation_id": "postal-code-cleanup-2026-09", - "counts": { - "deleted": 1, - "skipped": 1, - "error": 1 - }, - "results": [ - { - "outcome": "deleted", - "entity_id": "price-sp26d1yo", - "variant_id": "var-46045", - "valid_from": "2026-01-01T00:00:00.000Z", - "warnings": [ - { - "code": "ACTIVE_VERSION_CHANGED", - "message": "The version in effect was removed, so what resolves now has changed", - "details": { - "valid_from": "2026-01-01T00:00:00.000Z", - "active_valid_from": "2026-01-01T00:00:00.000Z" - } - } - ] - }, - { - "outcome": "skipped", - "entity_id": "price-sp26d1yo", - "warnings": [] - }, - { - "outcome": "error", - "entity_id": "price-sp26d1yo", - "variant_id": "var-80331", - "valid_from": "2026-01-01T00:00:00.000Z", - "warnings": [], - "error": { - "message": "var-80331 has only this version, so removing it would leave the variant unresolvable", - "code": "LAST_VERSION_UNDELETABLE", - "details": { - "variant_id": "var-80331", - "valid_from": "2026-01-01T00:00:00.000Z" - } - } - } - ] - } - } - } - } - } + "properties": { + "conditions": { + "$ref": "#/components/schemas/PinnedConditions" }, - "400": { - "description": "The envelope cannot be processed at all: more than 100 items, an empty `items`, a slug\nthat names no conditional entity type, an item naming both a `variant_id` and a condition\ntuple, or a body this schema rejects outright.\n\nAll of those are request-validation failures, so they carry a message and neither `code`\nnor `details`. Every failure of an individual item is on that item's result entry\ninstead, `ENTITY_NOT_FOUND` included, along with the per-entity `ENTITY_TYPE_MISMATCH`\nand `ENTITY_NOT_CONDITIONAL` — each item names its own entity, so each is checked on its\nown.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "default": { + "type": "boolean", + "default": false, + "description": "Mark this variant as the entity's fallback: the one served when no other variant applies.\n\nA property of the variant, never an entry in `conditions` — a variant claiming a value for\nthe marker would hold a real condition tuple while being permanently unmatchable, since no\nresolve context ever supplies it. A default variant cannot pin anything else, and an\nentity can have at most one.\n\nAvailable to every conditional entity: nothing has to be declared in the schema first.\nThe variant is stored pinning one reserved condition, which is what makes the ordinary\ncondition-tuple guard enforce at-most-one-per-entity with no rule of its own.\n" }, - "404": { - "description": "No such schema (`SCHEMA_NOT_FOUND`) — the one lookup the whole call depends on.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConditionalPricingError" - } - } - } + "valid_from": { + "type": "string", + "description": "When the first version takes effect. Defaults to now.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Deliberately not declared as\n`format: date-time`, which would reject the plain-date form that this accepts.\n", + "example": "2027-01-01T00:00:00Z" }, - "501": { - "description": "Published ahead of the behaviour. This operation is declared and not yet dispatched, so\nevery request to it is answered here until the batch delete behaviour lands — which is\nhow a deployed stage says \"this exists and does not work yet\" rather than answering with\ncounts a client would read as a completed cleanup.\n\nRead `message`. The body is the shared `Error` shape, as it is on every 501 this API\nanswers, so one \"not built yet\" branch covers all of them.\n", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } + "values": { + "$ref": "#/components/schemas/VariantValues" } } - } - } - }, - "components": { - "securitySchemes": { - "EpilotAuth": { - "type": "http", - "scheme": "bearer", - "description": "Epilot Bearer Token" - }, - "EpilotPublicAuth": { - "type": "http", - "scheme": "bearer", - "description": "Epilot Public Access Bearer Token", - "bearerFormat": "JWT" - } - }, - "schemas": { - "IntegrationId": { - "type": "string", - "enum": [ - "getag", - "external-catalog" - ] - }, - "ConditionalEntitySlug": { - "type": "string", - "description": "Schema slug of an entity type that can be conditional — the `{slug}` of every\nconditional-pricing route.\n", - "enum": [ - "product", - "price", - "coupon" - ] }, - "ConditionType": { - "type": "string", - "description": "The kind of value a condition holds, which decides how a variant's pinned value is matched\nagainst a resolve context.\n\n- `string`: an arbitrary string, matched exactly and case-sensitively\n- `number`: a numeric value\n- `date`: a single date\n- `daterange`: a window with a from and an until timestamp; both ends may be left open\n- `boolean`: a true/false value\n- `select`: one of the values declared in `options`, which is always a closed vocabulary\n- `location`: a geographic value, shaped by `format`\n\nThere is no condition type for the fallback variant. Being the entity's fallback is a\nproperty of the variant, set by the `default` flag on a variant write, and needs nothing\ndeclared in the schema.\n", - "enum": [ - "string", - "number", - "date", - "daterange", - "boolean", - "select", - "location" - ] - }, - "ConditionDefinition": { + "VariantConditions": { "type": "object", - "description": "One condition dimension, in the shape a schema's `conditions` array holds it — copy it in\nverbatim.\n", + "additionalProperties": true, "required": [ - "id", - "name", - "label", - "type" + "default" ], + "description": "A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a\nboolean `default` saying whether this is the entity's fallback.\n\n`default` is always present and always a boolean, so a client can branch on \"did I get the\nfallback?\" without knowing how one is stored. The reserved condition a fallback is actually\npinned under never appears here.\n", "properties": { - "id": { - "type": "string", - "format": "uuid", - "description": "Stable identity of the condition, round-tripped unchanged for the lifetime of the\ncondition: it is what tells a rename apart from a remove plus an add. The Entity API\nmints none of its own, so whoever creates a condition supplies one — a catalog condition\narrives with the identity the catalog gives it, the same in every org, and is copied into\nthe schema along with the rest of the object.\n", - "example": "d5839b94-ba20-4225-a78e-76951d352bd6" - }, - "name": { - "type": "string", - "description": "How variants and resolve contexts refer to this condition. Independent of attribute\nnames: a value needed as an attribute too is duplicated onto the variant.\n\n`default`, and any name beginning with `_`, are reserved for the server: a condition\ndeclared under one is ignored, since nothing could pin it and no context could address it.\n", - "example": "postal_code" - }, - "label": { - "type": "string", - "description": "Human-readable name of the condition.", - "example": "Postal Code" - }, - "type": { - "$ref": "#/components/schemas/ConditionType" - }, - "options": { - "type": "array", - "description": "The declared vocabulary of a `select` condition. Absent for every other type.\n\nThe same shape a `select` condition's `options` has on the Entity API, item for item: an\nentry is either the value itself or an object carrying that value and an optional display\n`title`. A `title` is never pinned by a variant and never matched — two entries differing\nonly in their title are one vocabulary entry.\n\nThe vocabulary is always closed: a condition carries no flag widening it, so a pinned\nvalue outside a declared vocabulary is rejected with `CONDITION_VALUE_INVALID`. A\nvocabulary that declares nothing is closed too — while `options` is absent or empty, or\nholds nothing this deploy can read, the condition admits no pin at all and the same code\nis returned with an empty `options`. It is *not* enforced on resolve — a vocabulary says\nwhat may be stored, not what may be asked for, so a context value outside it is a query\nthat simply matches nothing.\n", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - }, - "title": { - "type": "string" - } - } - } - ] - }, - "example": [ - "private", - { - "value": "commercial", - "title": "Commercial customers" - } - ] - }, - "format": { - "type": "string", - "description": "The value shape of a `location` condition. Absent for every other type.", - "enum": [ - "zipcode", - "zipcode_town" - ] + "default": { + "type": "boolean" } + }, + "example": { + "postal_code": "46045", + "default": false } }, - "ConditionSet": { + "PinnedConditions": { + "type": "object", + "additionalProperties": true, + "description": "The situation this variant applies to: a flat map keyed by condition name, as the entity's\nschema declares them. A condition left out is a wildcard — the variant applies whatever the\ncontext says for it, which is what makes adding a condition to a schema non-breaking for the\nvariants that already exist.\n\nExact values only. Predicates are accepted in a resolve context and nowhere else, so that\nmatching is decided in exactly one place.\n\nValues are typed by their condition and stored canonicalized for that type: a `date` becomes\nmillisecond-precision UTC, a `daterange` an object carrying `from` and `until` where an empty\nstring is an open end, a `location` of format `zipcode` the postal code itself and one of\nformat `zipcode + town` an object carrying both. A `select` value must be a string, and must\nbe one the condition's `options` declare unless it sets `allow_any`.\n\n`default`, and any name beginning with `_`, are reserved for the server and cannot be pinned\nhere. Whether a variant is the entity's fallback is set through the request's `default` flag.\n", + "example": { + "postal_code": "46045" + } + }, + "VariantValues": { + "type": "object", + "additionalProperties": true, + "description": "The attribute values this version overrides on the base entity, keyed by attribute name.\n\nOnly attributes currently declaring `overridable_attribute` are applied. Metadata fields\n(anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable\nattributes present here are ignored rather than rejected, so a client working from a slightly\nstale schema snapshot still succeeds instead of failing on fields it could not have known to\ndrop. An attribute's `render_condition` says when to show it and has no bearing on whether a\nvariant may override it.\n\nIgnored means *not updated*, never *removed*: a value already stored for an attribute that is\nnot currently overridable is preserved, so removing and restoring the flag deactivates and\nthen reactivates the same override.\n\nA composite price's `price_components` is an ordinary overridable relation attribute: a\ncomposite variant pins its component variants here the same way any other relation value is\nset, with no special handling.\n", + "example": { + "unit_amount": 2499, + "unit_amount_decimal": "24.99" + } + }, + "CreatedVariant": { "type": "object", - "description": "A named bundle of condition definitions, built in for one entity type.", "required": [ - "id", - "label", - "description", - "conditions" + "variant_id", + "entity_id", + "schema", + "conditions", + "valid_from", + "values", + "_created_at", + "_updated_at", + "_revision", + "warnings" ], "properties": { - "id": { + "variant_id": { "type": "string", - "description": "Identifies the set within this entity type's catalog.", - "example": "delivery_area" + "description": "Server-generated, always. This is the durable key orders and contracts pin, so it is never\naccepted from a client — a client-suppliable id would risk collisions between independent\nimporters.\n", + "example": "var-46045" }, - "label": { + "entity_id": { "type": "string", - "description": "Human-readable name of the set.", - "example": "Delivery Area" + "example": "price-sp26d1yo" }, - "description": { - "type": "string", - "description": "What the set is for, and when to reach for it." + "schema": { + "$ref": "#/components/schemas/ConditionalEntitySlug" }, "conditions": { - "type": "array", - "description": "The condition definitions to copy into the schema's own `conditions` array.", + "allOf": [ + { + "$ref": "#/components/schemas/VariantConditions" + } + ], + "description": "The situation this variant applies to, plus the boolean `default` discriminator — the\nsame shape `_conditions` has on a resolved payload.\n" + }, + "valid_from": { + "type": "string", + "description": "When the first version takes effect, canonicalized to millisecond-precision UTC.", + "example": "2027-01-01T00:00:00.000Z" + }, + "values": { + "$ref": "#/components/schemas/VariantValues" + }, + "_created_at": { + "type": "string", + "description": "When the first version was created.", + "readOnly": true + }, + "_updated_at": { + "type": "string", + "description": "When the first version was last written.", + "readOnly": true + }, + "_revision": { + "type": "number", + "description": "The revision a later write to this version must carry to be accepted. Genuinely current,\nunlike one read back later from an eventually-consistent read.\n", + "readOnly": true + }, + "warnings": { + "type": "array", + "description": "Things worth knowing that did not stop the write. Empty in the ordinary case — a client\nreads its length rather than branching on its absence.\n", "items": { - "$ref": "#/components/schemas/ConditionDefinition" + "$ref": "#/components/schemas/VariantWriteWarning" } } } }, - "ConditionSetCatalog": { + "VariantWriteWarning": { "type": "object", "required": [ - "results" + "code", + "message", + "variant_count", + "cap" ], "properties": { - "results": { - "type": "array", - "description": "The condition sets built in for the requested entity type, in the order they are offered.\n", - "items": { - "$ref": "#/components/schemas/ConditionSet" - } - } - } - }, - "ConditionalPricingErrorCode": { - "type": "string", - "description": "Machine-readable failure mode of a conditional-pricing operation, allowing clients\nto branch on the kind of failure instead of parsing the error message.\n\n- `SCHEMA_NOT_FOUND` (404): no conditional entity type by that slug\n- `ENTITY_NOT_FOUND` (404): the schema holds no entity with that id\n- `ENTITY_TYPE_MISMATCH` (400): that id belongs to an entity of another type than the slug named\n- `ENTITY_NOT_CONDITIONAL` (400): the entity is of the right type but was not created as a conditional one\n- `VARIANT_NOT_FOUND` (404): the entity has no such variant\n- `VERSION_NOT_FOUND` (404): the variant has no version at that `valid_from`\n- `NO_MATCHES` (404): nothing applied to the context and the entity has no `default` variant\n- `NO_ACTIVE_VERSION` (404): the variant has no version in effect at the instant asked about\n- `AMBIGUOUS_RESOLUTION` (409): several variants match the given context while a single result was requested\n- `TUPLE_CONFLICT` (409): the condition tuple is already claimed by another variant\n- `VERSION_CONFLICT` (409): a version already exists at the given `valid_from` on that variant\n- `CONDITION_UNDEFINED` (400): a resolve context, a listing filter or a variant's pins name a condition the entity's schema does not define\n- `OPERATOR_UNSUPPORTED` (400): the requested operator is not applicable to the condition's type\n- `CONTEXT_FORMAT_INVALID` (400): a resolve context or listing filter value is malformed for its condition type\n- `CONDITION_VALUE_INVALID` (400): a variant write pins a `select` value the condition's `options` do not admit, including every pin on a condition whose `options` are absent, empty or unreadable\n- `TOO_MANY_MATCHES` (400): a multi-match resolve exceeded its result cap\n- `WRITE_CONFLICT` (409): transient write contention, retryable unlike `TUPLE_CONFLICT`\n- `OFFSET_WINDOW_EXCEEDED` (400): a listing's `from` plus `size` reaches past the offset window the search index allows\n- `CURSOR_INVALID` (400): a paging cursor cannot be read, or does not belong to the read it was sent with\n- `VARIANT_LIMIT_REACHED` (400): the entity already holds every variant it may hold\n- `PIN_FORMAT_INVALID` (400): a variant pins a value malformed for its condition's type\n- `VARIANT_UNPINNED` (400): a variant write pins no condition and is not marked `default`, or a batch delete item addresses no variant\n- `LAST_VERSION_UNDELETABLE` (400): the delete would leave the variant with no version at all\n\nIn a batch, the last four are the refusals an importer branches on: `VARIANT_LIMIT_REACHED`\nmeans stop the import, `PIN_FORMAT_INVALID` means one bad row, `LAST_VERSION_UNDELETABLE`\nmeans delete the variant instead.\n\nNot every refusal has a code. These carry a message and neither `code` nor `details`, and\neach operation's `400` names its own: a write pinning the reserved marker (`default` or\n`_default`), a variant marked `default` that also pins a real condition, a pin on a condition\nwhose declared type this deploy cannot read, an id this store cannot key by, a `valid_from`\nthis store cannot sort by, and a version write or delete with no `_revision`. Testing `code`\nfor absence is how a client tells them from the coded failures.\n\nFour of the 404s say that something the request addressed does not exist, and are fixed by\ncorrecting an id or accepting the thing is gone. The other two say the opposite: everything\naddressed exists and there is still nothing to serve — no variant applies to this situation,\nor none of a variant's versions is in effect yet. Those are ordinary business outcomes, told\napart from a wrong id by their code.\n\n`ENTITY_TYPE_MISMATCH` and `ENTITY_NOT_CONDITIONAL` are `400`s, not 404s: the entity the\nrequest addressed **was** found, and the fix is the slug beside it. A slug that names no\nconditional entity type at all is a `400` too.\n\nEach code is emitted with the HTTP status shown above, and only with that status, and each\none is pinned by a member of `ConditionalPricingError` — which is where the structured data\nthat code carries is declared.\n", - "enum": [ - "SCHEMA_NOT_FOUND", - "ENTITY_NOT_FOUND", - "ENTITY_TYPE_MISMATCH", - "ENTITY_NOT_CONDITIONAL", - "VARIANT_NOT_FOUND", - "VERSION_NOT_FOUND", - "NO_MATCHES", - "NO_ACTIVE_VERSION", - "AMBIGUOUS_RESOLUTION", - "TUPLE_CONFLICT", - "VERSION_CONFLICT", - "CONDITION_UNDEFINED", - "OPERATOR_UNSUPPORTED", - "CONTEXT_FORMAT_INVALID", - "CONDITION_VALUE_INVALID", - "TOO_MANY_MATCHES", - "WRITE_CONFLICT", - "OFFSET_WINDOW_EXCEEDED", - "CURSOR_INVALID", - "VARIANT_LIMIT_REACHED", - "PIN_FORMAT_INVALID", - "VARIANT_UNPINNED", - "LAST_VERSION_UNDELETABLE" - ] - }, - "ResolveConditionalEntityRequest": { - "description": "A resolve names one conditional entity, then says which of its variants it means — one of two\nways, and never both. `context` describes a situation and asks which variants apply to it;\n`variant_id` names one variant and skips matching entirely.\n\nA body carrying both, or neither, is a validation `400`. Asking for the default variant\nwithout knowing its id is `context: {}`, which matches nothing and therefore falls back to it.\n\nEverything below the variant selection is the same on both branches, `as_of` included.\n", - "oneOf": [ - { - "$ref": "#/components/schemas/ResolveByContextRequest" + "code": { + "type": "string", + "description": "- `VARIANT_COUNT_APPROACHING_CAP`: this entity is nearing the number of variants it may\n hold. Surfaced rather than rejected, so an importer finds out with a whole run's notice\n instead of discovering the limit halfway through a refresh.\n", + "enum": [ + "VARIANT_COUNT_APPROACHING_CAP" + ] }, - { - "$ref": "#/components/schemas/ResolveByPinRequest" + "message": { + "type": "string" + }, + "variant_count": { + "type": "number", + "description": "Variants this entity holds, including the one just created." + }, + "cap": { + "type": "number", + "description": "Variants this entity may hold. Configurable per organization." } - ] + } }, - "ResolveByContextRequest": { + "DeletedVariant": { "type": "object", - "additionalProperties": false, - "description": "Resolve by matching a situation: which of this entity's variants apply to `context`, each\ncomposed with the version in effect at `as_of`.\n", "required": [ - "schema", + "variant_id", "entity_id", - "context" + "schema", + "tuple_released", + "versions_deleted" ], "properties": { - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" + "variant_id": { + "type": "string", + "example": "var-46045" }, "entity_id": { "type": "string", - "description": "The conditional entity to resolve. Resolution is always scoped to exactly one.", "example": "price-sp26d1yo" }, - "context": { - "$ref": "#/components/schemas/ResolveContext" + "schema": { + "$ref": "#/components/schemas/ConditionalEntitySlug" }, - "as_of": { - "type": "string", - "description": "The instant the version is selected at — the version with the latest `valid_from` at or\nbefore it. Defaults to now. A variant whose first version is later than this is\nscheduled rather than applicable, and is excluded from resolution entirely.\n\nThat exclusion belongs to context matching only: a set of results may quietly drop a\nmember, where a pin naming one variant cannot answer with silence and is told\n`NO_ACTIVE_VERSION` instead.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision.\n", - "example": "2027-03-15T00:00:00Z" + "tuple_released": { + "type": "boolean", + "description": "Whether this call is the one that freed the variant's combination of condition values.\n`false` where an earlier, interrupted attempt had already freed it — the delete still\nsucceeded, and the combination was already reusable.\n" }, - "options": { - "$ref": "#/components/schemas/ResolveOptions" + "versions_deleted": { + "type": "number", + "description": "Version rows this call removed." } } }, - "ResolveByPinRequest": { + "VariantVersion": { "type": "object", - "additionalProperties": false, - "description": "Resolve by naming a variant: compose this one, whatever a context would have matched. What an\norder needs to show the numbers a customer agreed to, and what a contract needs to show what\nis billable now — the two differ only in whether `as_of` is supplied.\n", + "description": "One version of one variant: the attribute overrides it carries, the instant it takes effect,\nand the variant it belongs to.\n\nThese are the version's **own** overrides, not the base entity overlaid with them — this is\nwhat an editing screen loads and saves, and what it edits is the overrides. Composing them onto\nthe entity is what `:resolve` answers.\n", "required": [ - "schema", + "variant_id", "entity_id", - "variant_id" + "schema", + "conditions", + "valid_from", + "values", + "_created_at", + "_updated_at", + "_revision" ], "properties": { - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" + "variant_id": { + "type": "string", + "example": "var-46045" }, "entity_id": { "type": "string", - "description": "The conditional entity to resolve. Resolution is always scoped to exactly one.", "example": "price-sp26d1yo" }, - "variant_id": { + "schema": { + "$ref": "#/components/schemas/ConditionalEntitySlug" + }, + "conditions": { + "allOf": [ + { + "$ref": "#/components/schemas/VariantConditions" + } + ], + "description": "The situation the variant applies to, plus the boolean `default` discriminator. A property\nof the variant rather than of this version: every version of a variant carries the same\none, and no version write can change it.\n" + }, + "valid_from": { "type": "string", - "description": "The variant to compose. Condition matching is skipped entirely: no `context` is read, the\n`default` fallback does not apply, and `results` carries exactly one entry — a pin asks\nfor one variant by name.\n\nA `variant_id` this entity has no variant under is `VARIANT_NOT_FOUND`, and so is one\nnaming a variant of a different entity: a variant id alone addresses nothing.\n`SCHEMA_NOT_FOUND` and `ENTITY_NOT_FOUND` are still answered ahead of both.\n\n**Published ahead of the behaviour.** Until the pinned path is built, a body carrying\nthis field is answered `501`, ahead of every check above — the field exists so consumers\ncan build against it, and declining it is how a deployed stage says so rather than\nquietly returning the `default` variant.\n", - "example": "var-46045" + "description": "When this version takes effect, canonicalized to millisecond-precision UTC. A version's\nidentity within its variant — it never moves.\n", + "example": "2027-01-01T00:00:00.000Z" }, - "as_of": { + "values": { + "$ref": "#/components/schemas/VariantValues" + }, + "_created_at": { "type": "string", - "description": "The instant the version is selected at — the version with the latest `valid_from` at or\nbefore it. Defaults to now. The same selector, by the same rule, as on a context resolve:\nhow the variant was chosen is orthogonal to which of its versions applies, so a caller\nreplaying a recorded resolution instant supplies it here.\n\nA pinned variant whose first version is later than this is `NO_ACTIVE_VERSION`, carrying\nthe instant in `details.as_of`, rather than being dropped the way context matching drops\na scheduled variant.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision.\n", - "example": "2027-03-15T00:00:00Z" + "description": "When this version was created.", + "readOnly": true }, - "options": { - "$ref": "#/components/schemas/PinnedResolveOptions" - } - } - }, - "ResolveContext": { - "type": "object", - "additionalProperties": true, - "description": "The situation to resolve for: a flat map keyed by condition name, as the entity's schema\ndeclares them. A condition left out of the map is not a wildcard — it matches only variants\nthat leave that condition unpinned.\n\nEach value is either an exact value, typed by its condition, or a single-operator predicate\nobject:\n\n- `{ \"lt\": v }`, `{ \"lte\": v }`, `{ \"gt\": v }`, `{ \"gte\": v }` — order against a `number` or\n `date` condition.\n- `{ \"in\": [...] }` — membership, against a `string`, `select` or `number` condition.\n- `{ \"between\": \"2026-03-01\" }` — the explicit spelling of `daterange` containment; a plain\n date supplied for a `daterange` condition means the same thing.\n- `{ \"exists\": true }` — pinned to any value. `{ \"exists\": false }` says what leaving the key\n out says.\n\nAn `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To match\na condition whatever its value, send `{ \"exists\": true }` rather than enumerating its\nvocabulary.\n\nExact values are typed by their condition: a `string` or `select` matches exactly and\ncase-sensitively, with no trimming; a `location` of format `zipcode` is the postal code\nitself, and one of format `zipcode_town` an object carrying both, whose town is compared\ncase- and whitespace-insensitively while its postal code is not.\n\n`default`, and any name beginning with `_`, are reserved for the server and cannot be\nsupplied here.\n\nAn empty map is valid and means what it says: it supplies no value, so it matches no variant\nthat pins a condition, and the entity's `default` variant is what comes back. It is the only way to\nask for the default variant without knowing its id.\n", - "example": { - "postal_code": "46045", - "consumption": { - "lt": 5000 - } - } - }, - "ResolveOptions": { - "type": "object", - "additionalProperties": false, - "description": "The options a context resolve accepts. A pin takes `PinnedResolveOptions` instead.", - "properties": { - "resolve_one": { - "type": "boolean", - "default": false, - "description": "Ask for an unambiguous answer. Several applicable variants become `AMBIGUOUS_RESOLUTION`\nrather than a set, and nothing applicable becomes `NO_MATCHES` rather than an empty one.\nThe response shape does not change: `results` simply carries exactly one entry.\n" + "_updated_at": { + "type": "string", + "description": "When this version was last written.", + "readOnly": true }, - "hydrate": { - "type": "boolean", - "default": false, - "description": "Return the entities a relation attribute references in place of the references\nthemselves, one level deep, exactly as an entity read with hydration does.\n\nA fetch, not a second resolution: a referenced entity comes back as it is read, and one\nthat is itself conditional carries its own flag — acting on that is the consumer's\nchoice, and this API does not resolve it on their behalf.\n\nApplied after composition, so a relation attribute whose value this variant's version\nreplaced is hydrated too. That is what makes a composite price work: the override\nreferences different component *entities*, which exist only in the composed payload.\n\nA reference that cannot be fetched comes back exactly as entity hydration returns it —\nno drop, no failure, and no field reporting it. A resolved payload behaves as an entity\nof the same shape would, and the discriminators are the only difference.\n\nCosts one fetch per referenced entity per result, and carries no cap of its own: the\nper-attribute limits are entity hydration's, and the 100-result cap on the resolve itself\nis unchanged.\n\n**Published ahead of the behaviour.** Until hydration is built, `true` is answered `501`\nrather than served as unhydrated references; `false`, which asks for what this path\nalready does, resolves normally.\n" - } - } - }, - "PinnedResolveOptions": { - "type": "object", - "additionalProperties": false, - "description": "The options a pinned resolve accepts — `hydrate` and nothing else. `resolve_one` has nothing\nto change on this branch, where the answer is exactly one result or a 404, so a body sending\nit is a validation `400`. `hydrate` means what `ResolveOptions.hydrate` means.\n", - "properties": { - "hydrate": { - "type": "boolean", - "default": false, - "description": "Return the entities a relation attribute references in place of the references\nthemselves, one level deep, exactly as an entity read with hydration does.\n\nA fetch, not a second resolution: a referenced entity comes back as it is read, and one\nthat is itself conditional carries its own flag — acting on that is the consumer's\nchoice, and this API does not resolve it on their behalf.\n\nApplied after composition, so a relation attribute whose value this variant's version\nreplaced is hydrated too. That is what makes a composite price work: the override\nreferences different component *entities*, which exist only in the composed payload.\n\nA reference that cannot be fetched comes back exactly as entity hydration returns it —\nno drop, no failure, and no field reporting it. A resolved payload behaves as an entity\nof the same shape would, and the discriminators are the only difference.\n\nCosts one fetch per referenced entity per result, and carries no cap of its own: the\nper-attribute limits are entity hydration's, and the 100-result cap on the resolve itself\nis unchanged.\n\n**Published ahead of the behaviour.** Until hydration is built, `true` is answered `501`\nrather than served as unhydrated references; `false`, which asks for what this path\nalready does, resolves normally.\n" + "_revision": { + "type": "integer", + "description": "The revision a write to this version must carry to be accepted. Always current: every read\nthat returns one is strongly consistent, so it is never a marker a write would be refused\nfor having read too early.\n", + "readOnly": true, + "example": 3 } } }, - "ResolvedVariants": { - "type": "object", - "required": [ - "results" - ], - "properties": { - "results": { - "type": "array", - "description": "One composed payload per applicable variant, capped at 100 — a context selecting more\nthan that is answered with `TOO_MANY_MATCHES` instead. No dominance or specificity\nordering is applied between them.\n", - "items": { - "$ref": "#/components/schemas/ResolvedVariant" + "WrittenVariantVersion": { + "description": "A version as a write left it, together with anything the write moved.\n", + "allOf": [ + { + "$ref": "#/components/schemas/VariantVersion" + }, + { + "type": "object", + "required": [ + "warnings" + ], + "properties": { + "warnings": { + "type": "array", + "description": "What this write moved, if anything. Empty in the ordinary case — a client reads its\nlength rather than branching on its absence.\n", + "items": { + "$ref": "#/components/schemas/VersionWriteWarning" + } + } } } - } + ] }, - "ResolvedVariant": { + "DeletedVariantVersion": { "type": "object", - "additionalProperties": true, - "description": "The entity as this variant leaves it — every attribute of a plain entity read, with the\napplicable version's overrides applied — plus the discriminators saying where the numbers\ncame from.\n\nWith `options.hydrate`, a relation attribute holds the entities it references rather than the\nreferences themselves. That changes what an attribute holds, not the payload's shape, so\nnothing is declared here for it.\n", "required": [ - "_id", - "_variant_id", - "_version_valid_from", - "_conditions", - "_inert_overrides" + "variant_id", + "entity_id", + "schema", + "valid_from", + "warnings" ], "properties": { - "_id": { + "variant_id": { "type": "string", - "description": "The logical entity's id — the same one a plain entity read returns. Resolution never\nmints a new identity; a variant is a set of values for *this* entity, not another one.\n", - "example": "price-sp26d1yo" + "example": "var-46045" }, - "_variant_id": { + "entity_id": { "type": "string", - "description": "The variant these values came from. Durable: this is what an order or a contract pins to\nread the same numbers back later.\n", - "example": "var-46045" + "example": "price-sp26d1yo" }, - "_version_valid_from": { + "schema": { + "$ref": "#/components/schemas/ConditionalEntitySlug" + }, + "valid_from": { "type": "string", - "description": "The `valid_from` of the version applied for the requested `as_of`.", + "description": "The version removed, canonicalized to millisecond-precision UTC.", "example": "2027-01-01T00:00:00.000Z" }, - "_conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantConditions" - } - ], - "description": "The conditions this variant pins, plus the boolean `default` discriminator.\n" - }, - "_inert_overrides": { + "warnings": { "type": "array", - "description": "The variant's stored overrides this payload did not apply, and why. Always present, and\nempty in the ordinary case — a client reads its length rather than branching on its\nabsence, the same way it reads a write's `warnings`.\n\nComputed per read from the schema as it stands, never stored, so granting or withdrawing\n`overridable_attribute` changes what resolves — and this list — without any data being\nrewritten. A version read reports what is stored and carries no such list; this is the\nonly surface that honours the schema.\n", + "description": "What the delete moved, if anything. Empty when a scheduled version was withdrawn.", "items": { - "$ref": "#/components/schemas/InertOverride" + "$ref": "#/components/schemas/VersionWriteWarning" } } } }, - "CreateVariantRequest": { + "VersionWriteWarning": { "type": "object", - "additionalProperties": false, + "description": "Something a version write moved. A version write is never refused for being late — backdating a\nversion, and editing or deleting one that has already been superseded, are both accepted — so\nwhat a caller gets instead is a warning naming exactly what changed. One write can carry both\ncodes.\n", "required": [ - "values" - ], - "properties": { - "conditions": { - "$ref": "#/components/schemas/PinnedConditions" - }, - "default": { - "type": "boolean", - "default": false, - "description": "Mark this variant as the entity's fallback: the one served when no other variant applies.\n\nA property of the variant, never an entry in `conditions`. A default variant cannot pin\nanything else, and an entity can have at most one; a second is refused as\n`TUPLE_CONFLICT`.\n\nAvailable to every conditional entity: nothing has to be declared in the schema first.\n" - }, - "valid_from": { - "type": "string", - "description": "When the first version takes effect. Defaults to now.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision.\n", - "example": "2027-01-01T00:00:00Z" - }, - "values": { - "$ref": "#/components/schemas/VariantValues" - } - } - }, - "VariantConditions": { - "type": "object", - "additionalProperties": true, - "required": [ - "default" - ], - "description": "A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a\nboolean `default` saying whether this is the entity's fallback.\n\n`default` is always present and always a boolean, so a client can branch on \"did I get the\nfallback?\" without knowing how one is stored. The reserved condition a fallback is actually\npinned under never appears here.\n", - "properties": { - "default": { - "type": "boolean" - } - }, - "example": { - "postal_code": "46045", - "default": false - } - }, - "PinnedConditions": { - "type": "object", - "additionalProperties": true, - "description": "The situation this variant applies to: a flat map keyed by condition name, as the entity's\nschema declares them. A condition left out is a wildcard — the variant applies whatever the\ncontext says for it, which is what makes adding a condition to a schema non-breaking for the\nvariants that already exist.\n\nExact values only. A predicate is a read-side thing — a resolve context or a listing's\ncondition filter — and is never stored: what a variant applies to is one situation, not a\nrange of them.\n\nValues are typed by their condition and stored canonicalized for that type: a `date` becomes\nmillisecond-precision UTC, a `daterange` an object carrying `from` and `until` where an empty\nstring is an open end, a `location` of format `zipcode` the postal code itself and one of\nformat `zipcode_town` an object carrying both. A `select` value must be a string, and must\nbe one the condition's `options` declare, which is always a closed vocabulary.\n\n`default`, and any name beginning with `_`, are reserved for the server and cannot be pinned\nhere. Whether a variant is the entity's fallback is set through the request's `default` flag.\n", - "example": { - "postal_code": "46045" - } - }, - "VariantValues": { - "type": "object", - "additionalProperties": true, - "description": "The attribute values this version overrides on the base entity, keyed by attribute name.\n\nOnly attributes currently declaring `overridable_attribute` are applied. Metadata fields\n(anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes,\nattributes of a type no variant may override and non-overridable attributes present here are\nnot applied rather than rejected, and every one but the metadata is named in the write's\n`warnings`, so a client working from a slightly stale schema snapshot still succeeds instead\nof failing on fields it could not have known to drop, and still learns which of them did not\nland. Metadata is never named, since a client echoing back a payload it read carries it in\nevery body. An attribute's `render_condition` says when to show it and has no\nbearing on whether a variant may override it.\n\nNot applied means *not updated*, never *removed*: a value already stored for an attribute that\nis not currently overridable is preserved, so removing and restoring the flag deactivates and\nthen reactivates the same override. An append seeds the attributes the variant may not\noverride from the version in effect at its own `valid_from`, so its stored values are not a\npure function of the body that wrote it; a variant's first version, and an append dated before\nthe variant's earliest version, inherit nothing.\n\nA composite price's `price_components` is an ordinary overridable relation attribute. A\ncomposite variant's override references different component *entities*, never a variant or a\nversion of one, and holds whatever a relation attribute ordinarily holds — this API defines no\nreference shape of its own.\n", - "example": { - "unit_amount": 2499, - "unit_amount_decimal": "24.99" - } - }, - "CreatedVariant": { - "type": "object", - "required": [ - "variant_id", - "entity_id", - "schema", - "conditions", - "valid_from", - "values", - "_created_at", - "_updated_at", - "_revision", - "warnings" + "code", + "message", + "valid_from" ], "properties": { - "variant_id": { - "type": "string", - "description": "Server-generated, always, and never accepted from a client. This is the durable key orders\nand contracts pin.\n", - "example": "var-46045" - }, - "entity_id": { - "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantConditions" - } - ], - "description": "The situation this variant applies to, plus the boolean `default` discriminator — the\nsame shape `_conditions` has on a resolved payload.\n" - }, - "valid_from": { - "type": "string", - "description": "When the first version takes effect, canonicalized to millisecond-precision UTC.", - "example": "2027-01-01T00:00:00.000Z" - }, - "values": { - "$ref": "#/components/schemas/VariantValues" - }, - "_created_at": { - "type": "string", - "description": "When the first version was created.", - "readOnly": true - }, - "_updated_at": { + "code": { "type": "string", - "description": "When the first version was last written.", - "readOnly": true - }, - "_revision": { - "type": "number", - "description": "The revision a later write to this version must carry to be accepted.\n", - "readOnly": true - }, - "warnings": { - "type": "array", - "description": "Things worth knowing that did not stop the write. Empty in the ordinary case — a client\nreads its length rather than branching on its absence.\n", - "items": { - "$ref": "#/components/schemas/WriteWarning" - } - } - } - }, - "WriteWarning": { - "description": "Something worth knowing that did not stop a write.\n\nOne vocabulary for every write, so a client branches on what happened rather than on which\nendpoint it called. `code` and `message` are the only two fields every code shares; everything\nelse lives in a `details` object typed per code, so narrowing on `code` yields a payload the\nclient can read rather than an untyped bag. A write raises each code at most once, and in the\nordinary case raises none of them.\n", - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "description": "This entity is nearing the number of variants it may hold. Surfaced rather than rejected,\nso an importer finds out with a whole run's notice instead of discovering the limit\nhalfway through a refresh.\n", - "required": [ - "code", - "message", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "VARIANT_COUNT_APPROACHING_CAP" - ] - }, - "message": { - "type": "string" - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_count", - "cap" - ], - "properties": { - "variant_count": { - "type": "number", - "description": "Variants this entity holds, including the one just written." - }, - "cap": { - "type": "number", - "description": "Variants this entity may hold. Configurable per deploy, the same value for every\norganization on it.\n" - } - } - } - } - }, - { - "type": "object", - "additionalProperties": false, - "description": "What resolves **now** changed, other than by a newer version taking effect: the version in\neffect was written behind, or removed.\n", - "required": [ - "code", - "message", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "ACTIVE_VERSION_CHANGED" - ] - }, - "message": { - "type": "string" - }, - "details": { - "$ref": "#/components/schemas/VersionMoved" - } - } + "description": "- `ACTIVE_VERSION_REPLACED`: what resolves **now** changed, other than by a newer version\n taking effect. The version in effect was written behind, or removed.\n- `SUPERSEDED_VERSION_WRITTEN`: what a past-dated (`as_of`) read returns changed. The write\n landed on, or created, a version that is not the one currently in effect.\n", + "enum": [ + "ACTIVE_VERSION_REPLACED", + "SUPERSEDED_VERSION_WRITTEN" + ] }, - { - "type": "object", - "additionalProperties": false, - "description": "What a past-dated (`as_of`) read returns changed: the write landed on, or created, a\nversion dated in the past. The version in effect is one of those whenever its own date has\npassed, which is the ordinary case — it covers every instant from that date until now. A\nversion dated now or later covers no past instant and is not reported here.\n", - "required": [ - "code", - "message", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "SUPERSEDED_VERSION_WRITTEN" - ] - }, - "message": { - "type": "string" - }, - "details": { - "$ref": "#/components/schemas/VersionMoved" - } - } + "message": { + "type": "string" }, - { - "type": "object", - "additionalProperties": false, - "description": "Attributes named in the request body that the write did not store, whatever the reason.\nThe write itself succeeded: an attribute a variant may not override is left alone rather\nthan making the whole call fail, so a client working from a slightly stale schema snapshot\nstill succeeds instead of failing on fields it could not have known to drop.\n\nOne entry per attribute, each with its own reason, so a client that only cares about typos\nfilters the entries by `reason` rather than branching on a second code.\n", - "required": [ - "code", - "message", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "ATTRIBUTES_NOT_APPLIED" - ] - }, - "message": { - "type": "string" - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "attributes" - ], - "properties": { - "attributes": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/InertOverride" - } - } - } - } - } - } - ] - }, - "VersionMoved": { - "type": "object", - "additionalProperties": false, - "description": "Which version a write moved, and which one was in effect while it did.\n", - "required": [ - "valid_from" - ], - "properties": { "valid_from": { "type": "string", "description": "The version this write created, changed or removed.", @@ -6080,1889 +5044,149 @@ }, "active_valid_from": { "type": "string", - "description": "The version in effect when the write landed, before it did. Absent when the variant had\nnone — every version of it still scheduled.\n\nMay lag the variant's timeline by milliseconds, so a version written moments earlier may\nnot be named here. Advisory, like the warning carrying it: nothing branches on it except a\nhuman reading the message.\n", + "description": "The version in effect when the write landed, before it did. Absent when the variant had\nnone — every version of it still scheduled.\n", "example": "2026-01-01T00:00:00.000Z" } } }, - "InertOverride": { + "AppendVersionRequest": { "type": "object", "additionalProperties": false, - "description": "One override that did not apply, and why.\n\nThe same entry on both sides of the feature: a write reports the attributes in its body it did\nnot store, and a resolved payload reports the stored overrides composition did not apply. Those\nare the same fact observed at two moments, so a client learns one shape and reads it in both\nplaces.\n", - "required": [ - "attribute", - "reason" - ], - "properties": { - "attribute": { - "type": "string", - "description": "The attribute's name, as the request body or the stored version spells it.", - "example": "unit_amount" - }, - "reason": { - "$ref": "#/components/schemas/InertOverrideReason" - } - } - }, - "InertOverrideReason": { - "type": "string", - "description": "Why one override did not apply.\n\n- `ATTRIBUTE_NOT_OVERRIDABLE`: the entity's schema declares the attribute but has not granted\n it `overridable_attribute`. Granting the flag is an ordinary schema edit, which makes this\n the reason most often worth acting on.\n- `ATTRIBUTE_READONLY`: the attribute is declared readonly, and a readonly attribute cannot\n be granted the flag.\n- `ATTRIBUTE_HIDDEN`: the attribute is declared hidden, and a hidden attribute cannot be\n granted the flag.\n- `ATTRIBUTE_COMPUTED`: the attribute's value is derived (`type: computed` or\n `computed: true`) rather than stored, so an override would be recomputed away.\n- `ATTRIBUTE_UNDECLARED`: the entity's schema declares no attribute of that name. On a write\n that is usually a typo; on a resolved payload it is a stored override whose attribute has\n since left the schema — a stored value outlives the flag being withdrawn, so it can outlive\n its own attribute too. This API keeps no record of what a schema once declared, so it states\n only the observable fact and does not distinguish the two.\n- `TYPE_NOT_OVERRIDABLE`: the attribute's type is not one a variant may override, whatever\n the schema says about that particular attribute.\n- `CAPABILITY_NOT_OVERRIDABLE`: the attribute is contributed by a capability rather than\n declared on the entity's schema. Published for completeness and not emitted in this version,\n in which no capability attribute can be overridden at all.\n", - "enum": [ - "ATTRIBUTE_NOT_OVERRIDABLE", - "ATTRIBUTE_READONLY", - "ATTRIBUTE_HIDDEN", - "ATTRIBUTE_COMPUTED", - "ATTRIBUTE_UNDECLARED", - "TYPE_NOT_OVERRIDABLE", - "CAPABILITY_NOT_OVERRIDABLE" - ] - }, - "DeletedVariant": { - "type": "object", "required": [ - "variant_id", - "entity_id", - "schema", - "tuple_released", - "versions_deleted" + "values" ], "properties": { - "variant_id": { - "type": "string", - "example": "var-46045" - }, - "entity_id": { + "valid_from": { "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" + "description": "When this version takes effect. Defaults to now.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision. Deliberately not declared as\n`format: date-time`, which would reject the plain-date form that this accepts.\n\nA date in the past is accepted and answered with warnings, never refused. A date the\nvariant already has a version at is refused as `VERSION_CONFLICT`.\n\n**Omit this to mean \"now\"** — that is the only spelling of now that is reliably silent. A\ntimestamp taken from the caller's own clock is already some milliseconds old when the\nserver judges it, which makes it a backdate, however small, and it is answered with the\nwarnings a backdate earns.\n", + "example": "2027-01-01T00:00:00Z" }, - "tuple_released": { - "type": "boolean", - "description": "Whether this call is the one that freed the variant's combination of condition values.\n`false` where an earlier, interrupted attempt had already freed it — the delete still\nsucceeded, and the combination was already reusable.\n" + "values": { + "$ref": "#/components/schemas/VariantValues" }, - "versions_deleted": { - "type": "number", - "description": "Version rows this call removed." - } - } - }, - "VariantVersion": { - "type": "object", - "description": "One version of one variant: the attribute overrides it carries, the instant it takes effect,\nand the variant it belongs to.\n\nThese are the version's **own** overrides, not the base entity overlaid with them — this is\nwhat an editing screen loads and saves, and what it edits is the overrides. Composing them onto\nthe entity is what `:resolve` answers.\n", - "required": [ - "variant_id", - "entity_id", - "schema", - "conditions", - "valid_from", - "values", - "_created_at", - "_updated_at", - "_revision" - ], - "properties": { - "variant_id": { - "type": "string", - "example": "var-46045" - }, - "entity_id": { - "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantConditions" - } - ], - "description": "The situation the variant applies to, plus the boolean `default` discriminator. A property\nof the variant rather than of this version: every version of a variant carries the same\none, and no version write can change it.\n" - }, - "valid_from": { - "type": "string", - "description": "When this version takes effect, canonicalized to millisecond-precision UTC. A version's\nidentity within its variant — it never moves.\n", - "example": "2027-01-01T00:00:00.000Z" - }, - "values": { - "$ref": "#/components/schemas/VariantValues" - }, - "_created_at": { - "type": "string", - "description": "When this version was created.", - "readOnly": true - }, - "_updated_at": { - "type": "string", - "description": "When this version was last written.", - "readOnly": true - }, - "_revision": { - "type": "integer", - "description": "The revision a write to this version must carry to be accepted. Always current: every read\nthat returns one is strongly consistent, so it is never a marker a write would be refused\nfor having read too early.\n", - "readOnly": true, - "example": 3 - } - } - }, - "WrittenVariantVersion": { - "description": "A version as a write left it, together with anything the write moved.\n", - "allOf": [ - { - "$ref": "#/components/schemas/VariantVersion" - }, - { - "type": "object", - "required": [ - "warnings" - ], - "properties": { - "warnings": { - "type": "array", - "description": "What this write moved, and anything in the body it did not store. Empty in the\nordinary case — a client reads its length rather than branching on its absence.\n", - "items": { - "$ref": "#/components/schemas/WriteWarning" - } - } - } - } - ] - }, - "DeletedVariantVersion": { - "type": "object", - "required": [ - "variant_id", - "entity_id", - "schema", - "valid_from", - "warnings" - ], - "properties": { - "variant_id": { - "type": "string", - "example": "var-46045" - }, - "entity_id": { - "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "valid_from": { - "type": "string", - "description": "The version removed, canonicalized to millisecond-precision UTC.", - "example": "2027-01-01T00:00:00.000Z" - }, - "warnings": { - "type": "array", - "description": "What the delete moved, if anything. Empty when a scheduled version was withdrawn — a\nclient reads its length rather than branching on its absence.\n", - "items": { - "$ref": "#/components/schemas/WriteWarning" - } - } - } - }, - "AppendVersionRequest": { - "type": "object", - "additionalProperties": false, - "required": [ - "values" - ], - "properties": { - "valid_from": { - "type": "string", - "description": "When this version takes effect. Defaults to now.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision.\n\nA date in the past is accepted and answered with warnings, never refused. A date the\nvariant already has a version at is refused as `VERSION_CONFLICT`.\n\n**Omit this to mean \"now\"** — that is the only spelling of now that is reliably silent. A\ntimestamp taken from the caller's own clock is already some milliseconds old when the\nserver judges it, which makes it a backdate, however small, and it is answered with the\nwarnings a backdate earns.\n", - "example": "2027-01-01T00:00:00Z" - }, - "values": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantValues" - } - ], - "description": "The attribute overrides this version carries. An append seeds the attributes the variant\nmay not override from the version in effect at this version's own `valid_from` and then\napplies these values over them, so the stored values are not a pure function of this\nbody. An append dated before the variant's earliest version inherits nothing.\n" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/PinnedConditions" - } - ], - "description": "Optional, and never applied: a variant's conditions are fixed when it is created. Accepted\nonly so that a client building its body from the version it loaded is not forced to strip\nthem out, and refused when they describe a different situation from the stored one.\n" - } - } - }, - "ReplaceVersionRequest": { - "type": "object", - "additionalProperties": false, - "required": [ - "values", - "_revision" - ], - "properties": { - "values": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantValues" - } - ], - "description": "The complete set of attribute overrides this version carries. An overridable attribute\nabsent from here stops being overridden.\n\nAttributes the variant may not override are not applied where this carries them, and\ntheir **stored value is kept rather than dropped**.\n" - }, - "_revision": { - "type": "integer", - "minimum": 1, - "description": "The revision marker read from the version being written. The write is refused with\n`WRITE_CONFLICT` if the version has been written since.\n", - "example": 3 - }, - "valid_from": { - "type": "string", - "description": "Optional, and never applied. Accepted when it names the version being addressed — so a\nclient building its body from what it loaded need not strip it out — and refused when it\nnames another: a version's `valid_from` is its identity, and moving it is an append and a\ndelete rather than an edit.\n" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/PinnedConditions" - } - ], - "description": "Optional, and never applied: a variant's conditions are fixed when it is created. Refused\nwhen they describe a different situation from the stored one.\n" - } - } - }, - "PatchVersionRequest": { - "type": "object", - "additionalProperties": false, - "required": [ - "values", - "_revision" - ], - "properties": { - "values": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantValues" - } - ], - "description": "Only the attribute overrides to change. Everything not mentioned is left as stored.\n\n`null` is a value like any other here rather than a deletion; to stop overriding an\nattribute, send the complete snapshot without it through the replace operation.\n" - }, - "_revision": { - "type": "integer", - "minimum": 1, - "description": "The revision marker read from the version being written. The write is refused with\n`WRITE_CONFLICT` if the version has been written since.\n", - "example": 3 - }, - "valid_from": { - "type": "string", - "description": "Optional, never applied, and refused when it names a version other than the one addressed." - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/PinnedConditions" - } - ], - "description": "Optional, and never applied. A partial update that tries to change a pinned condition value\nis refused.\n" - } - } - }, - "ListVariantsRequest": { - "type": "object", - "additionalProperties": false, - "description": "How to narrow and page a variant listing. Every property is optional, so `{}` is a valid body\nand asks for the first ten variants of the entity in `variant_id` order — the body itself is\nrequired, and an omitted one is a request-validation `400` rather than an unnarrowed page.\n\n`conditions` and `search` narrow independently and a variant has to satisfy both.\n", - "properties": { - "conditions": { - "$ref": "#/components/schemas/VariantConditionFilter" - }, - "search": { - "type": "string", - "description": "Free text matched against the variant's pinned values — how someone finds one postal code\namong 800,000.\n\nMatches `string`, `select` and `number` pins only. A `location` pin is stored as an array\nof its format's parts and a `daterange` pin as an object carrying `from` and `until`, so\nneither is text a user could have typed.\n", - "example": "460" - }, - "sort": { - "type": "string", - "description": "`conditions.:asc` or `conditions.:desc`, for a `string`, `select`, `number` or\n`date` pin. Anything else — another field, or a pin of another type — is a `400`.\n\n**`variant_id:asc` is appended by the server**, always, so the order is total: many\nvariants can pin one postal code, and without a tiebreaker a cursor would repeat or skip\nrows between pages. Asking for no sort is `variant_id:asc` alone.\n", - "example": "conditions.postal_code:asc" - }, - "from": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "The offset to read from. Not read when a `cursor` is sent, which carries its own position.\n\nBounded by the search index's offset window, together with `size`: the window bounds the\nlast row a page may contain, so the final servable offset is the window minus the page\nsize. A page reaching past it is `OFFSET_WINDOW_EXCEEDED`, naming all three numbers,\nrather than a page clamped back inside it as entity listing does. The window is the\ndeploy's: read its size from the error, not from here.\n" - }, - "size": { - "type": "integer", - "minimum": 1, - "default": 10, - "description": "Rows per page. Clamped silently at 1000, as entity listing's is.\n" - }, - "cursor": { - "type": "string", - "description": "Continue from a previous response's `next`, which is where a caller goes when the offset\nwindow runs out. Opaque: it encodes the position and the listing it was issued for, and\nnothing a client should read or construct.\n\n`conditions`, `search` and `sort` must be the ones the cursor was issued with — a cursor\nresumes one listing, and cannot mean anything against a different one. A cursor that is\nmalformed, or does not match the listing it is sent with, is a `400`.\n", - "example": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0" - } - } - }, - "VariantTreeRequest": { - "type": "object", - "additionalProperties": false, - "description": "The variants list's request plus `as_of`, the instant each row's version is selected at.\n`size` is clamped at 100 here; every other shared property means what it means on the list.\n", - "properties": { - "conditions": { - "$ref": "#/components/schemas/VariantConditionFilter" - }, - "search": { - "type": "string", - "description": "Free text matched against the variant's pinned values — how someone finds one postal code\namong 800,000.\n\nMatches `string`, `select` and `number` pins only. A `location` pin is stored as an array\nof its format's parts and a `daterange` pin as an object carrying `from` and `until`, so\nneither is text a user could have typed.\n", - "example": "460" - }, - "sort": { - "type": "string", - "description": "`conditions.:asc` or `conditions.:desc`, for a `string`, `select`, `number` or\n`date` pin. Anything else — another field, or a pin of another type — is a `400`.\n\n**`variant_id:asc` is appended by the server**, always, so the order is total: many\nvariants can pin one postal code, and without a tiebreaker a cursor would repeat or skip\nrows between pages. Asking for no sort is `variant_id:asc` alone.\n", - "example": "conditions.postal_code:asc" - }, - "from": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "The offset to read from. Not read when a `cursor` is sent, which carries its own position.\n\nBounded by the search index's offset window, together with `size`: the window bounds the\nlast row a page may contain, so the final servable offset is the window minus the page\nsize. A page reaching past it is `OFFSET_WINDOW_EXCEEDED`, naming all three numbers,\nrather than a page clamped back inside it as entity listing does. The window is the\ndeploy's: read its size from the error, not from here.\n" - }, - "size": { - "type": "integer", - "minimum": 1, - "default": 10, - "description": "Rows per page. Clamped silently at 100, a tenth of the variants list's cap: every row here\ncosts its own version lookup.\n" - }, - "cursor": { - "type": "string", - "description": "Continue from a previous response's `next`, which is where a caller goes when the offset\nwindow runs out. Opaque: it encodes the position and the listing it was issued for, and\nnothing a client should read or construct.\n\n`conditions`, `search` and `sort` must be the ones the cursor was issued with — a cursor\nresumes one listing, and cannot mean anything against a different one. A cursor that is\nmalformed, or does not match the listing it is sent with, is a `400`.\n", - "example": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0" - }, - "as_of": { - "type": "string", - "description": "The instant each row's version is selected at — the version with the latest `valid_from`\nat or before it. Defaults to now. The same selector, by the same rule, as `:resolve`'s.\n\nA variant whose first version is later than this is not dropped the way context matching\ndrops it: it is a row with `status: scheduled` carrying that upcoming first version, which\nis what makes a staged price visible on the editing screen.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision.\n", - "example": "2027-03-15T00:00:00Z" - } - } - }, - "VariantConditionFilter": { - "type": "object", - "additionalProperties": true, - "description": "Which pins a variant must carry to be listed: a flat map keyed by condition name, as the\nentity's schema declares them. A condition left out of the map is not filtered on at all.\n\nEach value is either an exact value, typed by its condition, or a single-operator predicate\nobject — the same seven a resolve context accepts, because in both cases a predicate is\napplied to the variant's *pinned* value, so nothing about matching moves:\n\n- `{ \"lt\": v }`, `{ \"lte\": v }`, `{ \"gt\": v }`, `{ \"gte\": v }` — order against a `number` or\n `date` condition.\n- `{ \"in\": [...] }` — membership, against a `string`, `select` or `number` condition.\n- `{ \"between\": \"2026-03-01\" }` — the explicit spelling of `daterange` containment; a plain\n date supplied for a `daterange` condition means the same thing.\n- `{ \"exists\": true }` — pinned to any value. `{ \"exists\": false }` — the condition left\n unpinned.\n\nAn `in` list carries at most 50,000 values; a longer one is `CONTEXT_FORMAT_INVALID`. To\nfilter on a condition whatever its pinned value, send `{ \"exists\": true }` rather than\nenumerating its vocabulary.\n\n**A variant matches only where it pins the condition** — the one place a filter and a resolve\ncontext differ. On `:resolve` a condition a variant does not pin matches any value; here,\nasking for postal code 46045 does not return the variants that pin no postal code at all.\n`{ \"exists\": false }` is how those are asked for.\n\nValues are typed and canonicalized exactly as a resolve context's are, by the same code, so\none instant written two ways filters the same way either way. A condition the schema does not\ndeclare is `CONDITION_UNDEFINED`, a predicate its type does not support is\n`OPERATOR_UNSUPPORTED`, and a value malformed for its type is `CONTEXT_FORMAT_INVALID`.\n\n**`default` is accepted here**, as the exact boolean every row reports it as: `true` selects\nthe entity's fallback variant, `false` every variant that is not it.\n\nIt takes no predicate. `default` is not a condition and has no type, so ordering and\nmembership have nothing to apply to. It is also the one key the pinned-only rule above does\nnot describe literally: a variant that is not the fallback does not pin the marker to `false`,\nit does not pin it at all, so `false` selects the variants that leave it unpinned.\n\nNames beginning with `_` stay reserved for the server and cannot be filtered on — `_default`,\nthe marker a fallback is actually stored under, included. `default` is the spelling every read\nreports and the only one this accepts.\n", - "example": { - "postal_code": "46045", - "consumption": { - "lt": 5000 - } - } - }, - "VariantList": { - "type": "object", - "required": [ - "hits", - "results" - ], - "properties": { - "hits": { - "type": "integer", - "description": "How many variants match, exactly, at any depth — not how many this page carries. Exact,\nas entity listing's is.\n", - "example": 8128 - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VariantListRow" - } - }, - "next": { - "type": "string", - "description": "The cursor that continues this listing, absent on the last page. Send it back as `cursor`,\nwith the same filter, search and sort.\n", - "example": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0" - } - } - }, - "VariantListRow": { - "type": "object", - "description": "One variant as a listing reports it: which variant it is and what it pins.\n\nNo `_revision` — a write re-reads its version through that version's own `GET` — and no\n`_inert_overrides`, since a listing reports what is stored and only `:resolve` honours the\nschema.\n", - "required": [ - "variant_id", - "entity_id", - "schema", - "conditions" - ], - "properties": { - "variant_id": { - "type": "string", - "example": "var-46045" - }, - "entity_id": { - "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantConditions" - } - ], - "description": "The situation this variant applies to, plus the boolean `default` discriminator — the same\nshape a variant write returns.\n\nMay lag: a variant just created can be missing from a page, and one just deleted can still\nbe on it. The pins shown for a variant are never stale, since a variant's conditions are\nimmutable after creation.\n" - } - } - }, - "VariantTree": { - "type": "object", - "required": [ - "hits", - "results" - ], - "properties": { - "hits": { - "type": "integer", - "description": "How many variants match, exactly, at any depth — not how many this page carries. Exact,\nas entity listing's is.\n", - "example": 8128 - }, - "results": { - "type": "array", - "description": "One row per matching variant, in the requested order.\n\nA variant the index still holds but whose versions are already gone — a variant\nmid-delete — is **omitted** rather than returned without a `version`. So `results` can be\nshorter than `hits` implies, for the width of that lag and no longer. Paging still ends\nwhere `next` does.\n", - "items": { - "$ref": "#/components/schemas/VariantTreeRow" - } - }, - "next": { - "type": "string", - "description": "The cursor that continues this listing, absent on the last page. Send it back as `cursor`,\nwith the same filter, search and sort.\n\n`as_of` is free to change between pages. It selects which version each row shows and has\nno bearing on which variants match or on the order they come back in, so a screen whose\ndate picker moves mid-listing keeps paging rather than starting over.\n", - "example": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0" - } - } - }, - "VariantTreeRow": { - "type": "object", - "description": "A listing row plus the one version the tree view shows for it, and the status saying which\nversion that is.\n", - "required": [ - "variant_id", - "entity_id", - "schema", - "conditions", - "status", - "version" - ], - "properties": { - "variant_id": { - "type": "string", - "example": "var-46045" - }, - "entity_id": { - "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantConditions" - } - ], - "description": "The situation this variant applies to, plus the boolean `default` discriminator — the same\nshape a variant write returns.\n\nMay lag: a variant just created can be missing from a page, and one just deleted can still\nbe on it. The pins shown for a variant are never stale, since a variant's conditions are\nimmutable after creation.\n" - }, - "status": { - "$ref": "#/components/schemas/VariantTreeRowStatus" - }, - "version": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantVersionSnapshot" - } - ], - "description": "The version this row shows: the one in effect at `as_of`, or — where every version of the\nvariant is still ahead of it — that upcoming first one. `status` says which of the two it\nis.\n\nAlways present. A variant always has at least one version, and the one case where a row\ncould have none — a variant whose delete has removed its versions but not yet its index\ndocument — is omitted from `results` instead, so a consumer never reads this field\ndefensively.\n" - } - } - }, - "VariantTreeRowStatus": { - "type": "string", - "description": "Whether a tree row's version is the one in effect at `as_of`, or one still ahead of it.\n\nExactly two values, and every row has one: a variant always has at least one version, so\neither a version is in effect at `as_of` or every version of that variant is still to come.\n\n- `active`: `version` is the version with the latest `valid_from` at or before `as_of` —\n the same version `active_valid_from` and `NO_ACTIVE_VERSION` speak of.\n- `scheduled`: the variant's first version is later than `as_of`, and `version` is that\n upcoming first version.\n", - "enum": [ - "active", - "scheduled" - ] - }, - "VariantVersionSnapshot": { - "type": "object", - "description": "One version of one variant as a listing reports it: `VariantVersion` without `_revision`.\n\nThe revision is missing on purpose. An editing screen re-reads the one version it is about to\nwrite through that version's own `GET`, which is strongly consistent, and writes with the\nrevision it gets back.\n\nEverything else is `VariantVersion` field for field, including the variant's `conditions`,\nwhich every version of a variant repeats.\n", - "required": [ - "variant_id", - "entity_id", - "schema", - "conditions", - "valid_from", - "values", - "_created_at", - "_updated_at" - ], - "properties": { - "variant_id": { - "type": "string", - "example": "var-46045" - }, - "entity_id": { - "type": "string", - "example": "price-sp26d1yo" - }, - "schema": { - "$ref": "#/components/schemas/ConditionalEntitySlug" - }, - "conditions": { - "allOf": [ - { - "$ref": "#/components/schemas/VariantConditions" - } - ], - "description": "The situation the variant applies to, plus the boolean `default` discriminator. A property\nof the variant rather than of this version: every version of a variant carries the same\none, and no version write can change it.\n" - }, - "valid_from": { - "type": "string", - "description": "When this version takes effect, canonicalized to millisecond-precision UTC. A version's\nidentity within its variant — it never moves.\n", - "example": "2027-01-01T00:00:00.000Z" - }, - "values": { - "$ref": "#/components/schemas/VariantValues" - }, - "_created_at": { - "type": "string", - "description": "When this version was created.", - "readOnly": true - }, - "_updated_at": { - "type": "string", - "description": "When this version was last written.", - "readOnly": true - } - } - }, - "VariantVersionList": { - "type": "object", - "required": [ - "results" - ], - "properties": { - "results": { - "type": "array", - "description": "A page of the variant's timeline, in the requested `order`.\n", - "items": { - "$ref": "#/components/schemas/VariantVersionSnapshot" - } - }, - "next": { - "type": "string", - "description": "The cursor that continues this timeline, absent only on the last page.\n\nThe only end-of-data signal: a page shorter than `limit`, or an empty one, can still carry\na cursor, so a client pages until this field is absent rather than until a page looks\nshort. Send it back as `cursor`, against the same variant and the same `order`.\n", - "example": "eyJzayI6IlYjcHJpY2Utc3AyNmQxeW8jdmFyLTQ2MDQ1IzIwMjYtMDEtMDFUMDA6MDA6MDAuMDAwWiIsIm9yZGVyIjoiYXNjIn0" - } - } - }, - "BatchUpsertVariantsRequest": { - "type": "object", - "additionalProperties": false, - "description": "A batch of variant writes under one schema, each item naming the entity it writes to.\n", - "required": [ - "items" - ], - "properties": { - "correlation_id": { - "type": "string", - "description": "An opaque string the caller uses to tie this response to the file and cycle that produced\nit. Echoed back verbatim, only when it was sent, and never interpreted.\n", - "example": "tariff-refresh-2027-01" - }, - "items": { - "type": "array", - "minItems": 1, - "maxItems": 100, - "description": "The writes to apply, in the order they should apply where two of them address the same\nvariant. At most 100 per call — a limit on one request, distinct from the per-entity\nvariant cap, which limits stored state.\n", - "items": { - "$ref": "#/components/schemas/BatchUpsertItem" - } - } - } - }, - "BatchUpsertItem": { - "type": "object", - "additionalProperties": false, - "description": "One variant write: the entity it belongs to, the situation it applies to, and the values it\ncarries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on\na create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the\nvariant already holding it.\n\nThere is no `variant_id`. An upsert creates variants that have no id yet.\n", - "required": [ - "entity_id", - "values" - ], - "properties": { - "entity_id": { - "type": "string", - "description": "The conditional entity this item writes to. On the item rather than in the path, so one\ncall can refresh a whole tariff hierarchy — a composite price and its components\ntogether.\n", - "example": "price-sp26d1yo" - }, - "conditions": { - "$ref": "#/components/schemas/PinnedConditions" - }, - "default": { - "type": "boolean", - "default": false, - "description": "Mark this variant as the entity's fallback, exactly as a create does: a property of the\nvariant, never an entry in `conditions`. An item that pins nothing and is not the default\nis `VARIANT_UNPINNED` — the empty postal-code column in a source file.\n" - }, - "valid_from": { - "type": "string", - "description": "When the version this item writes takes effect. Omitted, it is a current-state,\nlast-write-wins write with no `skipped` detection.\n\nAn RFC 3339 date (`2026-01-01`, read as midnight UTC) or date-time\n(`2026-01-01T00:00:00Z`), to at most millisecond precision.\n\nA past instant is written like any other and answered with the timeline warnings on this\nitem, so an importer stamping one `valid_from` across a batch sees them on every item.\n", - "example": "2027-01-01T00:00:00Z" - }, - "values": { - "$ref": "#/components/schemas/VariantValues" - } - } - }, - "BatchDeleteVariantsRequest": { - "type": "object", - "additionalProperties": false, - "description": "A batch of variant and version deletes under one schema, each item naming the entity it\nremoves from.\n", - "required": [ - "items" - ], - "properties": { - "correlation_id": { - "type": "string", - "description": "An opaque string the caller uses to tie this response to the file and cycle that produced\nit. Echoed back verbatim, only when it was sent, and never interpreted.\n", - "example": "postal-code-cleanup-2026-09" - }, - "items": { - "type": "array", - "minItems": 1, - "maxItems": 100, - "description": "The deletes to apply, in the order they should apply where two of them address the same\nvariant — which is decided after every condition tuple has been resolved to a variant id,\nso the order holds across the two addressing forms. At most 100 per call.\n", - "items": { - "$ref": "#/components/schemas/BatchDeleteItem" - } - } - } - }, - "BatchDeleteItem": { - "description": "One delete: the variant, addressed by id or by the condition tuple it pins, and optionally\nthe one version of it to remove.\n\nExactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches\nneither branch and is an envelope `400`, since the request validator rejects the body before\nany item runs.\n", - "oneOf": [ - { - "$ref": "#/components/schemas/BatchDeleteByVariantId" - }, - { - "$ref": "#/components/schemas/BatchDeleteByConditions" - } - ] - }, - "BatchDeleteByVariantId": { - "type": "object", - "additionalProperties": false, - "description": "A delete addressing its variant by id — the form a cleanup pass uses after the schema has\ndrifted, since a tuple naming a condition the schema no longer declares addresses nothing.\n", - "required": [ - "entity_id", - "variant_id" - ], - "properties": { - "entity_id": { - "type": "string", - "description": "The conditional entity the variant belongs to. **Required beside `variant_id`, and not\nredundant**: a variant id alone addresses nothing in this API.\n", - "example": "price-sp26d1yo" - }, - "variant_id": { - "type": "string", - "description": "The variant to remove, or whose version to remove.", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The one version to remove, by the instant it takes effect. Omitted, the whole variant\ngoes — its tuple, its index registration and every version it accumulated.\n\nAn RFC 3339 date or date-time, to at most millisecond precision, canonicalized before it\nis matched.\n", - "example": "2027-01-01T00:00:00Z" - } - } - }, - "BatchDeleteByConditions": { - "type": "object", - "additionalProperties": false, - "description": "A delete addressing its variant by the situation it applies to — the form an importer uses\nwhen it knows the source rows rather than the ids they produced.\n\n`conditions` is optional because the entity's fallback variant pins nothing: an item\naddressing it sends `default: true` and no `conditions`, exactly as a create marks one.\n\n**An item that addresses no variant is a per-item `VARIANT_UNPINNED`, not an envelope\n`400` and not a `skipped`.** Three shapes reach it: no `conditions` and no `default`,\n`conditions: {}`, and `default: false` alone — an empty postal-code column in a source row,\nserialized one way or another.\n\nTwo more shapes validate here and are refused per item rather than described by the schema:\nan item marking `default` while also pinning `conditions` — a fallback variant applies only\nwhen nothing else does, so it cannot also pin — and an item carrying `valid_from` with no\nvariant addressed at all. Both carry a message and no code, as the create path refuses the\nfirst today.\n", - "required": [ - "entity_id" - ], - "properties": { - "entity_id": { - "type": "string", - "description": "The conditional entity the variant belongs to. Required, as it is beside a `variant_id`.\n", - "example": "price-sp26d1yo" - }, - "conditions": { - "$ref": "#/components/schemas/PinnedConditions" - }, - "default": { - "type": "boolean", - "default": false, - "description": "Address the entity's fallback variant, the one it serves when nothing else applies. A\nproperty of the variant, as it is on a write, never an entry in `conditions`.\n" - }, - "valid_from": { - "type": "string", - "description": "The one version to remove, by the instant it takes effect. Omitted, the whole variant\ngoes.\n\nAn RFC 3339 date or date-time, to at most millisecond precision, canonicalized before it\nis matched.\n", - "example": "2027-01-01T00:00:00Z" - } - } - }, - "BatchUpsertResult": { - "type": "object", - "description": "What a batch upsert did: one entry per item, in request order, and a count per outcome.\n", - "required": [ - "counts", - "results" - ], - "properties": { - "correlation_id": { - "type": "string", - "description": "The `correlation_id` the request carried, echoed only when it was sent.", - "example": "tariff-refresh-2027-01" - }, - "counts": { - "$ref": "#/components/schemas/BatchUpsertCounts" - }, - "results": { - "type": "array", - "description": "One entry per item, **in request order** — position is what maps an outcome back to its\nsource row, and no entry carries an index of its own.\n", - "items": { - "$ref": "#/components/schemas/BatchUpsertResultEntry" - } - } - } - }, - "BatchDeleteResult": { - "type": "object", - "description": "What a batch delete did: one entry per item, in request order, and a count per outcome.\n", - "required": [ - "counts", - "results" - ], - "properties": { - "correlation_id": { - "type": "string", - "description": "The `correlation_id` the request carried, echoed only when it was sent.", - "example": "postal-code-cleanup-2026-09" - }, - "counts": { - "$ref": "#/components/schemas/BatchDeleteCounts" - }, - "results": { - "type": "array", - "description": "One entry per item, **in request order** — position is what maps an outcome back to its\nsource row.\n", - "items": { - "$ref": "#/components/schemas/BatchDeleteResultEntry" - } - } - } - }, - "BatchUpsertOutcome": { - "type": "string", - "description": "What one upsert item did, derived from what was stored rather than from a mode the caller\ndeclared.\n\n- `variant_created`: the condition tuple was unknown, so a variant and its first version were\n created. The entry's `variant_id` is the id an order or contract pins.\n- `version_created`: the tuple was known and had no version at the item's `valid_from`, so\n one was appended. The ordinary monthly-refresh case, and a separate value from\n `variant_created` so an importer's counts can tell \"new postal codes appeared\" from\n \"existing variants got their scheduled adjustment\".\n- `updated`: a version existed at that exact instant and was written in place.\n- `skipped`: reserved for a write whose values are identical to what is stored, so re-running\n an unchanged import reads as a no-op. An item without `valid_from` has no `skipped`\n detection at all.\n- `error`: this item alone failed, and the entry's `error` says why.\n", - "enum": [ - "variant_created", - "version_created", - "updated", - "skipped", - "error" - ] - }, - "BatchDeleteOutcome": { - "type": "string", - "description": "What one delete item did.\n\n- `deleted`: the variant, or the one version the item named, is gone.\n- `skipped`: the item addressed nothing — **the variant or the version**, never the entity. An\n entity that cannot answer the item is an `error` carrying `ENTITY_NOT_FOUND`,\n `ENTITY_TYPE_MISMATCH` or `ENTITY_NOT_CONDITIONAL`.\n- `error`: this item alone failed, and the entry's `error` says why.\n", - "enum": [ - "deleted", - "skipped", - "error" - ] - }, - "BatchUpsertCounts": { - "type": "object", - "additionalProperties": false, - "description": "How many items reached each outcome. Keyed by exactly the values of `BatchUpsertOutcome`, all\nof them present, so a logger reads a count without `?? 0`.\n\n**They sum to the length of `results`.** There is no `total`.\n", - "required": [ - "variant_created", - "version_created", - "updated", - "skipped", - "error" - ], - "properties": { - "variant_created": { - "type": "integer", - "example": 1 - }, - "version_created": { - "type": "integer", - "example": 1 - }, - "updated": { - "type": "integer", - "example": 1 - }, - "skipped": { - "type": "integer", - "example": 1 - }, - "error": { - "type": "integer", - "example": 1 - } - } - }, - "BatchDeleteCounts": { - "type": "object", - "additionalProperties": false, - "description": "How many items reached each outcome. Keyed by exactly the values of `BatchDeleteOutcome`, all\nof them present, and summing to the length of `results`. No `total`.\n", - "required": [ - "deleted", - "skipped", - "error" - ], - "properties": { - "deleted": { - "type": "integer", - "example": 1 - }, - "skipped": { - "type": "integer", - "example": 1 - }, - "error": { - "type": "integer", - "example": 1 - } - } - }, - "BatchUpsertResultEntry": { - "type": "object", - "additionalProperties": false, - "description": "What one upsert item did, and anything worth knowing about it.\n\n**It carries nothing else.** Position in `results` is the contract, so no entry carries an\nindex; nothing the caller sent is echoed back beyond `entity_id`; and there is no `_revision`\n— an editing screen re-reads the version it is about to write through its own `GET`.\n", - "required": [ - "outcome", - "entity_id", - "warnings" - ], - "properties": { - "outcome": { - "$ref": "#/components/schemas/BatchUpsertOutcome" - }, - "entity_id": { - "type": "string", - "description": "The entity this item wrote to, echoed from the item — present whatever happened.", - "example": "price-sp26d1yo" - }, - "variant_id": { - "type": "string", - "description": "The variant this item created or wrote to. Present on every outcome but `error`: for a\n`variant_created` item it is the id an importer needs to pin, and for the rest it is the\nvariant the item's condition tuple resolved to.\n", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The version this item wrote, canonicalized to millisecond-precision UTC. Present on every\noutcome but `error`, including for an item that sent none — the server stamps the instant\na current-state write takes effect, and this is where the caller reads it back.\n", - "example": "2027-01-01T00:00:00.000Z" - }, - "warnings": { - "type": "array", - "description": "Things worth knowing that did not stop this item's write. **Always present, and possibly\nempty** — on a `skipped` and an `error` entry too — so a client reads its length rather\nthan branching on its absence, as every other write in this document already asks.\n`skipped` describes what storage did; a warning describes what the request asked for, and\nthe two are not the same fact.\n\nEvery warning fires per item, with no batch-level suppression:\n`VARIANT_COUNT_APPROACHING_CAP` included, even where an entity past its threshold\nproduces it on all 100 entries. A logger dedupes by code.\n", - "items": { - "$ref": "#/components/schemas/WriteWarning" - } - }, - "error": { - "allOf": [ - { - "$ref": "#/components/schemas/ConditionalPricingError" - } - ], - "description": "Why this item failed, present only with `outcome: error`. The same typed shape a\nsingle-item write is refused with, so a per-item failure and a single-item failure are\nread by one client type.\n\nAn item carries the codes variant create raises — `VARIANT_UNPINNED`,\n`CONDITION_UNDEFINED`, `CONDITION_VALUE_INVALID`, `PIN_FORMAT_INVALID`,\n`VARIANT_LIMIT_REACHED`, `WRITE_CONFLICT` for transient contention, and the three the\naddressed entity answers with: `ENTITY_NOT_FOUND`, `ENTITY_TYPE_MISMATCH` and\n`ENTITY_NOT_CONDITIONAL` — less two. Those three are per item because each item names its\nown entity, while `SCHEMA_NOT_FOUND` is the envelope's, since the slug is in the path. `TUPLE_CONFLICT` never appears on an item, and neither does `VERSION_CONFLICT`: a\nguard failure on a brand-new tuple is re-read and re-derived, and an existing\n`valid_from` is a replacement.\n" - } - } - }, - "BatchDeleteResultEntry": { - "type": "object", - "additionalProperties": false, - "description": "What one delete item did, and anything worth knowing about it.\n\nThe same six properties as a batch upsert entry, and it carries nothing else.\n", - "required": [ - "outcome", - "entity_id", - "warnings" - ], - "properties": { - "outcome": { - "$ref": "#/components/schemas/BatchDeleteOutcome" - }, - "entity_id": { - "type": "string", - "description": "The entity this item removed from, echoed from the item — present whatever happened.", - "example": "price-sp26d1yo" - }, - "variant_id": { - "type": "string", - "description": "The variant this item removed, or whose version it removed. Present wherever it is known:\nalways for an item that named one, and for an item addressing a condition tuple only once\nthat tuple resolved. **A `skipped` entry for a tuple no variant pins therefore names no\nvariant.**\n", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The version this item removed, canonicalized to millisecond-precision UTC. Absent where\nthe item removed the whole variant, which is what distinguishes the two deletes this one\nendpoint performs.\n", - "example": "2027-01-01T00:00:00.000Z" - }, - "warnings": { - "type": "array", - "description": "Things worth knowing that did not stop this item's delete — chiefly which reads the\nremoval moved: `ACTIVE_VERSION_CHANGED` where what resolves now changed, and\n`SUPERSEDED_VERSION_WRITTEN` where a past-dated read did. Always present and possibly\nempty, on every outcome, as batch upsert's is.\n", - "items": { - "$ref": "#/components/schemas/WriteWarning" - } - }, - "error": { - "allOf": [ - { - "$ref": "#/components/schemas/ConditionalPricingError" - } - ], - "description": "Why this item failed, present only with `outcome: error`. The same typed shape a\nsingle-item delete is refused with.\n\n`LAST_VERSION_UNDELETABLE` is the refusal specific to this endpoint's dated form;\n`VARIANT_UNPINNED` is an item that addresses no variant — no `variant_id`, no\n`default`, and no or empty `conditions`; `ENTITY_NOT_FOUND`, `ENTITY_TYPE_MISMATCH` and\n`ENTITY_NOT_CONDITIONAL` are per item, since each item names its own entity;\n`WRITE_CONFLICT` is transient contention.\nA missing variant or version is not here at all — that is `skipped`.\n" - } - } - }, - "Error": { - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Error message" - }, - "status": { - "type": "number", - "description": "The HTTP status code" - }, - "cause": { - "type": "string", - "description": "The cause of the error (visible for bad requests - http 400)" - } - } - }, - "ReportedError": { - "description": "The `error` field of an error response: the message, or — where the request itself failed\nvalidation before any handler ran — the validation errors themselves, which those 400s put\nhere in place of a string.\n\nA conditional-pricing operation answers a body its schema rejects with the list, and\neverything else it refuses with the message.\n", - "oneOf": [ - { - "type": "string", - "description": "The message, the same string as `message`.", - "example": "The conditions requested for variant var-46045 are already pinned" - }, - { - "type": "array", - "description": "One entry per validation failure, as the request validator reported it.", - "items": { - "type": "object", - "additionalProperties": true - } - } - ] - }, - "ConditionalPricingError": { - "description": "An error from a conditional-pricing operation, carrying a machine-readable `code` from the\nconditional-pricing vocabulary plus the structured data that code explains, so a client can\nbranch on the kind of failure rather than parse the message.\nReferenced only by the operations that emit these codes; every other operation\nkeeps the plain `Error` shape.\n\n`details` is typed per code. Narrow on `code` and the object under it declares exactly the\nfields that code sends — never a field it does not send, and nothing beyond the declaration —\nso the conflicting variant id, or the value and vocabulary behind a rejected pin, is read\ndirectly.\n\nNot every failure these operations raise is in the vocabulary. A request body that is simply\nmalformed earns a message and nothing to branch on, and is answered with neither `code` nor\n`details` — the last member of the union, so testing `code` for absence is how a client tells\none of those from the twenty-three coded failures.\n", - "allOf": [ - { - "$ref": "#/components/schemas/Error" - }, - { - "type": "object", - "properties": { - "error": { - "allOf": [ - { - "$ref": "#/components/schemas/ReportedError" - } - ], - "description": "What went wrong, in the field responses have always used and every caller to date\nreads. Carries the same string as `message` — which the shared `Error` schema\nrequires — except on a request-validation failure, which puts the list of validation\nerrors here instead.\n" - } - } - }, - { - "oneOf": [ - { - "type": "object", - "description": "No conditional entity type by that slug — the organization has no schema under it, or\nthe schema it has is not a conditional-pricing one.\n\nAddressed to the caller's own path parameter, and the same answer for every operation:\nnothing below a schema can be looked up until the schema itself is known.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "SCHEMA_NOT_FOUND" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "schema" - ], - "properties": { - "schema": { - "type": "string", - "description": "The entity type the request addressed.", - "example": "price" - } - } - } - } - }, - { - "type": "object", - "description": "The schema exists and holds no entity with that id.\n\nA wrong entity id is answered here, never as a variant that was never there. An id\nthat *does* exist, under another type, is not this code — the entity was found, and\n`ENTITY_TYPE_MISMATCH` is what says so.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "ENTITY_NOT_FOUND" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "schema", - "entity_id" - ], - "properties": { - "schema": { - "type": "string", - "description": "The entity type the request addressed.", - "example": "price" - }, - "entity_id": { - "type": "string", - "description": "The conditional entity the request addressed.", - "example": "price-sp26d1yo" - } - } - } - } - }, - { - "type": "object", - "description": "That entity id belongs to an entity of a different type than the `{slug}` segment\nnamed.\n\nA `400`, not a `404`: the entity **was** found. The fix is to correct the slug and\nsend the request again; the entity id and the variant id were right. `actual_schema`\nnames the type the id belongs to, and where that is a conditional entity type it is\nthe slug to send.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "ENTITY_TYPE_MISMATCH" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "schema", - "entity_id", - "actual_schema" - ], - "properties": { - "schema": { - "type": "string", - "description": "The entity type the request addressed.", - "example": "price" - }, - "entity_id": { - "type": "string", - "description": "The conditional entity the request addressed.", - "example": "price-sp26d1yo" - }, - "actual_schema": { - "type": "string", - "description": "The entity type that id belongs to. Where it is a conditional entity type, it\nis the slug to send instead.\n", - "example": "product" - } - } - } - } - }, - { - "type": "object", - "description": "The entity is of the type the slug named, and is not a conditional one.\n\nA Product, Price or Coupon carries variants only if it was created with\n`is_conditional` set, and that flag is fixed at creation. So this is not a refusal\nanother request can get past: the entity has no conditional capability to address,\nand one that needs it has to be created as such.\n\nA `400`, as `ENTITY_TYPE_MISMATCH` is: the entity was found. Reading and writing the\nentity itself are unaffected; it is these endpoints that do not apply to it.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "ENTITY_NOT_CONDITIONAL" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "schema", - "entity_id" - ], - "properties": { - "schema": { - "type": "string", - "description": "The entity type the request addressed.", - "example": "price" - }, - "entity_id": { - "type": "string", - "description": "The conditional entity the request addressed.", - "example": "price-sp26d1yo" - } - } - } - } - }, - { - "type": "object", - "description": "This entity has no such variant — nothing to read, write or delete, and nothing that\nwas ever there to have deleted.\n\nRaised only once the entity itself has been established, so it never stands in for a\nwrong entity id or a wrong slug.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "VARIANT_NOT_FOUND" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "entity_id", - "variant_id" - ], - "properties": { - "entity_id": { - "type": "string", - "description": "The conditional entity the request addressed.", - "example": "price-sp26d1yo" - }, - "variant_id": { - "type": "string", - "description": "The variant the request addressed.", - "example": "var-46045" - } - } - } - } - }, - { - "type": "object", - "description": "No version at that `valid_from` — never written, or deleted since.\n\nA version is addressed by the exact instant it takes effect from, not by the instant\na read happens to fall in, so this is not \"no version applies then\"; that case is\n`NO_ACTIVE_VERSION`.\n\nResolving a dated address tells an absent version from an absent variant, so a\nvariant that does not exist at all answers `VARIANT_NOT_FOUND` — the same answer the\npaths that name no date give.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "VERSION_NOT_FOUND" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id", - "valid_from" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The variant the request addressed.", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The version the request addressed, by the instant it takes effect from.", - "example": "2027-01-01T00:00:00.000Z" - } - } - } - } - }, - { - "type": "object", - "description": "Nothing applied to the given context, and the entity has no `default` variant to fall\nback to.\n\nEverything the request addressed exists: this is an answer about the organization's\nown data, not a defect to fix — \"we do not serve this situation\".\n\nOnly reachable with `resolve_one`. Without it the same situation is a `200` carrying\nan empty `results`, since a set of applicable variants can legitimately be empty; it\nis asking for exactly one answer that turns having none into a failure.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "NO_MATCHES" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "schema", - "entity_id" - ], - "properties": { - "schema": { - "type": "string", - "description": "The entity type the request addressed.", - "example": "price" - }, - "entity_id": { - "type": "string", - "description": "The conditional entity the resolve was scoped to.", - "example": "price-sp26d1yo" - } - } - } - } - }, - { - "type": "object", - "description": "The variant has no version in effect at the instant asked about — raised by the\nshorthand reads and writes that address \"the version in effect\" without naming a\ndate, and by a pinned `:resolve` whose variant has no version in effect at `as_of`.\n\nRelative to `as_of`, and not a claim that every version is scheduled: a variant that\nis live today has none in effect at an instant before its first `valid_from` either.\nThe ordinary case is a variant staged ahead of its launch, which is a variant waiting\nrather than a variant broken — address one of its versions by `valid_from` to read or\nedit it before it takes effect.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "NO_ACTIVE_VERSION" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id", - "as_of" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The variant the request addressed.", - "example": "var-46045" - }, - "as_of": { - "type": "string", - "description": "The instant a version in effect was asked for at.", - "example": "2026-06-01T00:00:00.000Z" - } - } - } - } - }, - { - "type": "object", - "description": "Several variants apply to the given context while a single result was requested.\n\nThe candidates are named, and none of them is served over the others: which is right\nis a question about the organization's own data.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "AMBIGUOUS_RESOLUTION" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "candidates" - ], - "properties": { - "candidates": { - "type": "array", - "minItems": 2, - "description": "Every variant that applied, each with the conditions it pins — which is what\nmakes the overlap actionable: two variants both apply because their pins do\nnot distinguish the context they were both asked about.\n\nBounded by the same cap `TOO_MANY_MATCHES` reports, which is checked first,\nso this list is never longer than one response may carry.\n", - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id", - "conditions" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The candidate variant.", - "example": "var-46045" - }, - "conditions": { - "$ref": "#/components/schemas/VariantConditions" - } - } - } - } - } - } - } - }, - { - "type": "object", - "description": "The condition tuple this write claims is already held.\n\nPersistent, unlike `WRITE_CONFLICT`: the same request fails the same way until the\nholder changes, so a bulk importer can tell \"send this again\" from \"this combination\nis taken and always will be\".\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "TUPLE_CONFLICT" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The variant the write addressed.", - "example": "var-46045" - }, - "conflicting_variant_id": { - "type": "string", - "description": "The variant already holding the tuple, where the write read it back.\n", - "example": "var-50667" - } - } - } - } - }, - { - "type": "object", - "description": "A version already exists at the given `valid_from` on that variant.", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "VERSION_CONFLICT" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id", - "valid_from" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The variant the write addressed.", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The instant already claimed by a version of that variant.", - "example": "2027-01-01T00:00:00.000Z" - } - } - } - } - }, - { - "type": "object", - "description": "A condition the entity's schema does not define, named by a resolve context, by a\nlisting's condition filter, or by a variant's pins.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "CONDITION_UNDEFINED" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "condition_name" - ], - "properties": { - "condition_name": { - "type": "string", - "description": "The condition named by the request and absent from the schema.", - "example": "postal_code" - } - } - } - } - }, - { - "type": "object", - "description": "The requested operator is not applicable to the condition's type.", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "OPERATOR_UNSUPPORTED" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "condition_name", - "condition_type", - "operator" - ], - "properties": { - "condition_name": { - "type": "string", - "example": "postal_code" - }, - "condition_type": { - "type": "string", - "description": "The type the schema declares that condition with, which is what decides the\noperators it accepts.\n", - "example": "location" - }, - "operator": { - "type": "string", - "description": "The operator the context or filter asked for.", - "example": "between" - } - } - } - } - }, - { - "type": "object", - "description": "A resolve context or listing filter value that is malformed for its condition's type.\n\n`details` says what the type requires, never what arrived: a resolve context value is\nnot quoted back.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "CONTEXT_FORMAT_INVALID" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "condition_name", - "expected" - ], - "properties": { - "condition_name": { - "type": "string", - "example": "postal_code" - }, - "expected": { - "type": "string", - "description": "What a value for that condition has to be, in prose.", - "example": "a postal code" - } - } - } - } - }, - { - "type": "object", - "description": "A variant write pins a `select` value the condition's `options` do not admit — either\na value a declared vocabulary does not contain, or any value at all where the\ncondition declares no vocabulary for it to be in.\n\nOne of the two codes that report the submitted value back — `PIN_FORMAT_INVALID` is\nthe other. A resolve context value is never quoted back.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "CONDITION_VALUE_INVALID" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "condition_name", - "value", - "options" - ], - "properties": { - "condition_name": { - "type": "string", - "example": "segment" - }, - "value": { - "description": "The value the write pinned, as it arrived. Declared without a type: the\nvocabulary holds strings, so anything else is out of it by definition and is\nreported as sent.\n", - "example": "industrial" - }, - "options": { - "type": "array", - "description": "The vocabulary *as enforced* — after the entries this deploy cannot read have\nbeen dropped, so a tenant whose `options` holds a title-only entry is told\nwhat the API actually checked against rather than what they believe they\nwrote. Empty when the condition declares no vocabulary at all, which is\nitself the reason the pin was refused; the message says which of the two\n(unconfigured, or unreadable) applies.\n", - "items": { - "type": "string" - }, - "example": [ - "private", - "commercial" - ] - } - } - } - } - }, - { - "type": "object", - "description": "A multi-match resolve found more variants than one response may carry. Narrowing the\ncontext is the only fix; the matches are not reported.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "TOO_MANY_MATCHES" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "limit" - ], - "properties": { - "limit": { - "type": "number", - "description": "The most variants one resolve may compose.", - "example": 100 - } - } - } - } - }, - { - "type": "object", - "description": "Transient write contention — concurrent writers, or throughput pressure on the\nentity's own rows. Retryable, unlike `TUPLE_CONFLICT`.\n\nThe revisions are present where the contention was detected on a specific version: a\nwrite carrying `_revision` lost to another that landed first, and a client that read\nthe version again would see `current_revision`. A variant-level refusal carries the\nvariant alone.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "WRITE_CONFLICT" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The variant the write addressed.", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The version the write addressed, where one was addressed.", - "example": "2027-01-01T00:00:00.000Z" - }, - "expected_revision": { - "type": "number", - "description": "The revision the write required the stored version to still be at.", - "example": 3 - }, - "current_revision": { - "type": "number", - "description": "The revision the version is actually at, where the failed write read it back.\nAbsent when it could not be.\n", - "example": 4 - } - } - } - } - }, + "conditions": { + "allOf": [ { - "type": "object", - "description": "A listing asked for a page reaching past the window the search index allows.\n\n**`from` plus `size`**, not `from` alone: the window bounds the last row a page may\ncontain, so the final servable offset is `window` minus the page size. All three\nnumbers are in `details`, because a refusal quoting only an offset below the window\nreads like a mistake.\n\nNot a page clamped back inside the window, as entity listing does. The fix is a\ndifferent request: page on with the last response's `next`.\n\nThe window belongs to the deploy's search index, so it is reported and never\npublished.\n\nRaised by the paginated variant reads, which answer `501` until their behaviour\nlands.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "OFFSET_WINDOW_EXCEEDED" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "from", - "size", - "window" - ], - "properties": { - "from": { - "type": "integer", - "description": "The offset the request asked for.", - "example": 24990 - }, - "size": { - "type": "integer", - "description": "The page size the request asked for, after clamping. Present because the two\ntogether are what exceeded the window — an offset inside it can still be\nrefused for the page it would have to read.\n", - "example": 25 - }, - "window": { - "type": "integer", - "description": "The last row this deploy's index will serve from an offset. Read it to size a\npage control, never to decide when to switch to the cursor — a caller can page\non with `next` from any page.\n", - "example": 25000 - } - } - } - } - }, + "$ref": "#/components/schemas/PinnedConditions" + } + ], + "description": "Optional, and never applied: a variant's conditions are fixed when it is created. Accepted\nonly so that a client building its body from the version it loaded is not forced to strip\nthem out, and refused when they describe a different situation from the stored one.\n" + } + } + }, + "ReplaceVersionRequest": { + "type": "object", + "additionalProperties": false, + "required": [ + "values", + "_revision" + ], + "properties": { + "values": { + "allOf": [ { - "type": "object", - "description": "A paging cursor could not be used for the read it arrived on.\n\nOne code for every way that happens, because the caller's fix is the same for all of\nthem: start the read again without a cursor. `details.reason` says which check failed,\nfor a human reading a log rather than for a client to branch on — a cursor this API\nminted and a caller stored can go stale, be truncated in transit, be replayed against\na different filter or sort, or be replayed against another variant or the opposite\norder on a versions read.\n\nRaised by the paginated variant and version reads, which answer `501` until their\nbehaviour lands.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "CURSOR_INVALID" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "description": "Which check the cursor failed, in prose.", - "example": "The cursor was issued for a different sort order" - } - } - } - } - }, + "$ref": "#/components/schemas/VariantValues" + } + ], + "description": "The complete set of attribute overrides this version carries. An overridable attribute\nabsent from here stops being overridden.\n\nAttributes the variant may not override are ignored where this carries them, and their\n**stored value is kept rather than dropped** — otherwise a routine full-snapshot write\nwould erase an override the moment its attribute's `overridable_attribute`, `readonly` or\n`hidden` flag happened to be off.\n" + }, + "_revision": { + "type": "integer", + "minimum": 1, + "description": "The revision marker read from the version being written. The write is refused with\n`WRITE_CONFLICT` if the version has been written since.\n\nRequired rather than optional: an optional one is a guarantee every client can opt out of\nby forgetting a field, and the write it protects is the one that overwrites somebody\nelse's edit.\n", + "example": 3 + }, + "valid_from": { + "type": "string", + "description": "Optional, and never applied. Accepted when it names the version being addressed — so a\nclient building its body from what it loaded need not strip it out — and refused when it\nnames another: a version's `valid_from` is its identity, and moving it is an append and a\ndelete rather than an edit.\n" + }, + "conditions": { + "allOf": [ { - "type": "object", - "description": "The entity already holds every variant it may hold.\n\nA hard refusal, unlike the `VARIANT_COUNT_APPROACHING_CAP` warning that precedes it,\ncarrying the warning's two keys. In a batch it means stop the import rather than fix\na row: every remaining item for that entity will be refused the same way.\n\nEmitted by `$createConditionalVariant`. The batch writes that will also raise it\nanswer `501` until their handlers land.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "VARIANT_LIMIT_REACHED" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_count", - "cap" - ], - "properties": { - "variant_count": { - "type": "number", - "description": "Variants this entity already holds.", - "example": 5000 - }, - "cap": { - "type": "number", - "description": "Variants this entity may hold. Configurable per deploy, the same value for\nevery organization on it.\n", - "example": 5000 - } - } - } - } - }, + "$ref": "#/components/schemas/PinnedConditions" + } + ], + "description": "Optional, and never applied: a variant's conditions are fixed when it is created. Refused\nwhen they describe a different situation from the stored one.\n" + } + } + }, + "PatchVersionRequest": { + "type": "object", + "additionalProperties": false, + "required": [ + "values", + "_revision" + ], + "properties": { + "values": { + "allOf": [ { - "type": "object", - "description": "A variant pins a value that is malformed for its condition's type.\n\nThe write-side mirror of `CONTEXT_FORMAT_INVALID`: a context value is *matched*, a\nvariant's value is *pinned*. Unlike that one it reports the value back, as\n`CONDITION_VALUE_INVALID` does.\n\nDistinct from a condition whose *declared type* this deploy cannot read at all: that\nis a schema problem rather than a bad row, every item naming the condition fails\nidentically, and it stays uncoded.\n\nIt carries `expected` as well as `condition_type`, and the two are not the same fact:\na `location` condition is `condition_type: location` whichever format it declares,\nand the two formats want different values — a postal code, or an object carrying a\npostal code and a town. The type is what a client branches on; `expected` is what\nsays what the value had to be.\n\nEmitted by `$createConditionalVariant`. The batch writes that will also raise it\nanswer `501` until their handlers land.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "PIN_FORMAT_INVALID" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "condition_name", - "condition_type", - "expected", - "value" - ], - "properties": { - "condition_name": { - "type": "string", - "example": "valid_period" - }, - "condition_type": { - "type": "string", - "description": "The type the schema declares that condition with, which is what decides the\nvalues it accepts.\n", - "example": "daterange" - }, - "expected": { - "type": "string", - "description": "What a pin for that condition has to be, in prose — the same field\n`CONTEXT_FORMAT_INVALID` carries, worded for the write side. It says what\n`condition_type` cannot: a `location` of format `zipcode` wants a postal code\nand one of format `zipcode_town` wants an object carrying both, and the type\nis `location` either way.\n", - "example": "an object carrying a from and an until date, either may be open" - }, - "value": { - "description": "The value the write pinned, as it arrived. Declared without a type, since\nwhat makes it invalid is that it is not of the condition's type.\n", - "example": "2027-01-01/2027-12-31" - } - } - } - } - }, + "$ref": "#/components/schemas/VariantValues" + } + ], + "description": "Only the attribute overrides to change. Everything not mentioned is left as stored.\n\n`null` is a value like any other here rather than a deletion; to stop overriding an\nattribute, send the complete snapshot without it through the replace operation.\n" + }, + "_revision": { + "type": "integer", + "minimum": 1, + "description": "The revision marker read from the version being written. The write is refused with\n`WRITE_CONFLICT` if the version has been written since.\n", + "example": 3 + }, + "valid_from": { + "type": "string", + "description": "Optional, never applied, and refused when it names a version other than the one addressed." + }, + "conditions": { + "allOf": [ { - "type": "object", - "description": "The write pins no condition and is not marked `default`.\n\nSuch a variant would be a universal wildcard matching every resolve, which is a far\nmore dangerous thing than a fallback and far easier to create by accident — an empty\npostal-code column in a source file produces exactly this.\n\nRaised on a delete too, where an item addresses no variant at all — no `variant_id`,\nno `default`, and either no `conditions` or an empty one: the item names no target.\nIt is an `error`, not a `skipped`.\n\nEmitted by `$createConditionalVariant`. Batch upsert and batch delete, which raise\nit too, answer `501` until their handlers land.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "VARIANT_UNPINNED" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "entity_id" - ], - "properties": { - "entity_id": { - "type": "string", - "description": "The conditional entity the item addressed.", - "example": "price-sp26d1yo" - } - } - } - } + "$ref": "#/components/schemas/PinnedConditions" + } + ], + "description": "Optional, and never applied. A partial update that tries to change a pinned condition value\nis refused — this is the path that rule is most likely to be broken on by accident.\n" + } + } + }, + "Error": { + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string", + "description": "Error message" + }, + "status": { + "type": "number", + "description": "The HTTP status code" + }, + "cause": { + "type": "string", + "description": "The cause of the error (visible for bad requests - http 400)" + } + } + }, + "ConditionalPricingError": { + "description": "An error from a conditional-pricing operation, carrying a machine-readable `code`\nfrom the conditional-pricing vocabulary plus any structured data about the failure,\nso a client can branch on the kind of failure rather than parse the message.\nReferenced only by the operations that emit these codes; every other operation\nkeeps the plain `Error` shape.\n", + "allOf": [ + { + "$ref": "#/components/schemas/Error" + }, + { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "The error message. Carries the same string as `message`, which the shared `Error`\nschema requires — `error` is the field responses have always used, and every caller\nto date reads. Declared here rather than on the shared `Error` because a request\nvalidation failure puts a list of validation errors in this field instead of a\nstring, and those responses reference `Error` directly.\n" }, - { - "type": "object", - "description": "The delete would leave the variant with no version at all.\n\nSuch a variant would still hold its condition tuple and still be selectable, and\nwould then resolve to nothing — a variant delete wearing a version delete's clothes.\nDelete the variant instead; that frees the tuple too.\n\nEmitted by `$deleteConditionalVariantVersion`. Batch delete, which raises it too,\nanswers `501` until its handler lands.\n", - "required": [ - "code", - "details" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "LAST_VERSION_UNDELETABLE" - ] - }, - "details": { - "type": "object", - "additionalProperties": false, - "required": [ - "variant_id", - "valid_from" - ], - "properties": { - "variant_id": { - "type": "string", - "description": "The variant whose last version the delete addressed.", - "example": "var-46045" - }, - "valid_from": { - "type": "string", - "description": "The version the delete addressed, by the instant it takes effect from.", - "example": "2027-01-01T00:00:00.000Z" - } - } - } - } + "code": { + "$ref": "#/components/schemas/ConditionalPricingErrorCode" }, - { + "details": { "type": "object", - "description": "A failure the vocabulary has no entry for: a malformed request body, a value that is\nnot readable as its condition's type, a rule refusing a write for a reason a client\ncannot branch on. The message says what to fix, and no code is sent.\n\nCarries what every response carries and nothing else — reading `code` on this member\nis how a client tells it from the coded members above.\n", - "additionalProperties": false, - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "status": { - "type": "number" - }, - "cause": { - "type": "string" - }, - "error": { - "$ref": "#/components/schemas/ReportedError" - } - } + "additionalProperties": true, + "description": "Structured data about the failure, shaped by the accompanying `code`\n(e.g. the candidate variants of an `ambiguous-resolution`). Only present\nwhen the failure has structured data to report, and never without a `code`.\n" } - ] + } } ] }, @@ -8158,10 +5382,6 @@ } } }, - "is_conditional": { - "description": "The flag for entities whose values vary by context. Resolve the values that apply with\n`POST /v1/conditional-pricing:resolve`.\n", - "type": "boolean" - }, "_availability_files": { "type": "array", "description": "Stores references to the availability files that define where this product is available.\nThese files are used when interacting with products via epilot Journeys, thought the AvailabilityCheck block.\n", @@ -9320,10 +6540,6 @@ false ] }, - "is_conditional": { - "description": "The flag for entities whose values vary by context. Resolve the values that apply with\n`POST /v1/conditional-pricing:resolve`.\n", - "type": "boolean" - }, "pricing_model": { "type": "string", "description": "Describes how to compute the price per period. Either `per_unit`, `tiered_graduated` or `tiered_volume`.\n- `per_unit` indicates that the fixed amount (specified in unit_amount or unit_amount_decimal) will be charged per unit in quantity\n- `tiered_graduated` indicates that the unit pricing will be computed using tiers attribute. The customer pays the price per unit in every range their purchase rises through.\n- `tiered_volume` indicates that the unit pricing will be computed using tiers attribute. The customer pays the same unit price for all purchased units.\n- `tiered_flatfee` While similar to tiered_volume, tiered flat fee charges for the same price (flat) for the entire range instead using the unit price to multiply the quantity.\n - `dynamic_tariff` indicates that the price is dynamically dependend on the (quarter)-hourly spot market price.\n- `external_getag` indicates that the price is influenced by aquisition fees provided by GetAG.\n", @@ -9644,10 +6860,6 @@ true ] }, - "is_conditional": { - "description": "The flag for entities whose values vary by context. Resolve the values that apply with\n`POST /v1/conditional-pricing:resolve`.\n", - "type": "boolean" - }, "_created_at": { "description": "The price creation date", "type": "string" @@ -10373,6 +7585,10 @@ "description": "The optional reference date for the price computation (ISO 8601 format)", "type": "string", "format": "date" + }, + "city": { + "description": "The city the postal code belongs to. Not used for price computation,\nonly echoed back in `inputs` for display purposes.\n", + "type": "string" } }, "required": [ @@ -10612,6 +7828,14 @@ "breakdown": { "$ref": "#/components/schemas/ComputedPriceBreakdown" }, + "inputs": { + "description": "A snapshot of the parameters this price was computed from, for display purposes\n(e.g. showing \"computed for 3,500 kWh/year\"). Included in the `_meta` signature.\n", + "allOf": [ + { + "$ref": "#/components/schemas/ComputePriceInputs" + } + ] + }, "_meta": { "$ref": "#/components/schemas/SignatureMeta" } @@ -10624,6 +7848,49 @@ "breakdown" ] }, + "ComputePriceInputs": { + "type": "object", + "description": "Echo of the request parameters used to compute the price, in the caller-facing shape.", + "properties": { + "type": { + "$ref": "#/components/schemas/ProductCategory" + }, + "consumptionHT": { + "type": "number" + }, + "consumptionNT": { + "type": "number" + }, + "consumptionType": { + "$ref": "#/components/schemas/ConsumptionTypeGetAg" + }, + "zipCode": { + "type": "string" + }, + "city": { + "type": "string" + }, + "providerId": { + "type": "string" + }, + "billingPeriod": { + "type": "string", + "enum": [ + "weekly", + "monthly", + "every_quarter", + "every_6_months", + "yearly", + "one_time" + ] + }, + "referenceDate": { + "type": "string", + "format": "date" + } + }, + "additionalProperties": true + }, "SpotMarketBiddingZone": { "description": "The bidding zone for a spot market price.", "type": "string", @@ -13137,10 +10404,6 @@ "active": { "type": "boolean" }, - "is_conditional": { - "description": "The flag for entities whose values vary by context. Resolve the values that apply with\n`POST /v1/conditional-pricing:resolve`.\n", - "type": "boolean" - }, "requires_promo_code": { "type": "boolean", "description": "Whether the coupon requires a promo code to be applied" @@ -14057,6 +11320,23 @@ "items": { "$ref": "#/components/schemas/ProductRecommendation" } + }, + "source": { + "type": "object", + "description": "Context about what the recommendations were searched against.", + "properties": { + "item": { + "description": "The first line item of the contract used as source for the recommendation.\nCarries the amounts the customer currently pays; only present when searching by contract_id.\n", + "anyOf": [ + { + "$ref": "#/components/schemas/PriceItem" + }, + { + "$ref": "#/components/schemas/CompositePriceItem" + } + ] + } + } } }, "required": [