@epilot/sdk 2.20.30 → 2.20.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/definitions/pricing.json +4181 -848
  2. package/dist/apis/access-token.cjs +6 -6
  3. package/dist/apis/access-token.js +1 -1
  4. package/dist/apis/address-suggestions.cjs +6 -6
  5. package/dist/apis/address-suggestions.js +1 -1
  6. package/dist/apis/address.cjs +6 -6
  7. package/dist/apis/address.js +1 -1
  8. package/dist/apis/ai-agents.cjs +6 -6
  9. package/dist/apis/ai-agents.js +1 -1
  10. package/dist/apis/app.cjs +6 -6
  11. package/dist/apis/app.js +1 -1
  12. package/dist/apis/audit-logs.cjs +6 -6
  13. package/dist/apis/audit-logs.js +1 -1
  14. package/dist/apis/automation.cjs +6 -6
  15. package/dist/apis/automation.js +1 -1
  16. package/dist/apis/billing.cjs +6 -6
  17. package/dist/apis/billing.js +1 -1
  18. package/dist/apis/blueprint-manifest.cjs +6 -6
  19. package/dist/apis/blueprint-manifest.js +1 -1
  20. package/dist/apis/calendar.cjs +6 -6
  21. package/dist/apis/calendar.js +1 -1
  22. package/dist/apis/chat.cjs +6 -6
  23. package/dist/apis/chat.js +1 -1
  24. package/dist/apis/configuration-hub.cjs +6 -6
  25. package/dist/apis/configuration-hub.js +1 -1
  26. package/dist/apis/consent.cjs +6 -6
  27. package/dist/apis/consent.js +1 -1
  28. package/dist/apis/customer-portal.cjs +6 -6
  29. package/dist/apis/customer-portal.js +1 -1
  30. package/dist/apis/dashboard.cjs +6 -6
  31. package/dist/apis/dashboard.js +1 -1
  32. package/dist/apis/data-governance.cjs +6 -6
  33. package/dist/apis/data-governance.js +1 -1
  34. package/dist/apis/deduplication.cjs +6 -6
  35. package/dist/apis/deduplication.js +1 -1
  36. package/dist/apis/design.cjs +6 -6
  37. package/dist/apis/design.js +1 -1
  38. package/dist/apis/document.cjs +6 -6
  39. package/dist/apis/document.js +1 -1
  40. package/dist/apis/email-settings.cjs +6 -6
  41. package/dist/apis/email-settings.js +1 -1
  42. package/dist/apis/email-template.cjs +6 -6
  43. package/dist/apis/email-template.js +1 -1
  44. package/dist/apis/entity-mapping.cjs +6 -6
  45. package/dist/apis/entity-mapping.js +1 -1
  46. package/dist/apis/entity.cjs +6 -6
  47. package/dist/apis/entity.js +1 -1
  48. package/dist/apis/environments.cjs +6 -6
  49. package/dist/apis/environments.js +1 -1
  50. package/dist/apis/event-catalog.cjs +6 -6
  51. package/dist/apis/event-catalog.js +1 -1
  52. package/dist/apis/file.cjs +6 -6
  53. package/dist/apis/file.js +1 -1
  54. package/dist/apis/iban.cjs +6 -6
  55. package/dist/apis/iban.js +1 -1
  56. package/dist/apis/integration-toolkit.cjs +6 -6
  57. package/dist/apis/integration-toolkit.js +1 -1
  58. package/dist/apis/journey.cjs +6 -6
  59. package/dist/apis/journey.js +1 -1
  60. package/dist/apis/kanban.cjs +6 -6
  61. package/dist/apis/kanban.js +1 -1
  62. package/dist/apis/message.cjs +6 -6
  63. package/dist/apis/message.js +1 -1
  64. package/dist/apis/metering.cjs +6 -6
  65. package/dist/apis/metering.js +1 -1
  66. package/dist/apis/notes.cjs +6 -6
  67. package/dist/apis/notes.js +1 -1
  68. package/dist/apis/notification.cjs +6 -6
  69. package/dist/apis/notification.js +1 -1
  70. package/dist/apis/organization.cjs +6 -6
  71. package/dist/apis/organization.js +1 -1
  72. package/dist/apis/partner-directory.cjs +6 -6
  73. package/dist/apis/partner-directory.js +1 -1
  74. package/dist/apis/permissions.cjs +6 -6
  75. package/dist/apis/permissions.js +1 -1
  76. package/dist/apis/pricing-tier.cjs +6 -6
  77. package/dist/apis/pricing-tier.js +1 -1
  78. package/dist/apis/pricing.cjs +6 -6
  79. package/dist/apis/pricing.d.cts +2 -2
  80. package/dist/apis/pricing.d.ts +2 -2
  81. package/dist/apis/pricing.js +1 -1
  82. package/dist/apis/purpose.cjs +6 -6
  83. package/dist/apis/purpose.js +1 -1
  84. package/dist/apis/query.cjs +6 -6
  85. package/dist/apis/query.js +1 -1
  86. package/dist/apis/sandbox.cjs +6 -6
  87. package/dist/apis/sandbox.js +1 -1
  88. package/dist/apis/sharing.cjs +6 -6
  89. package/dist/apis/sharing.js +1 -1
  90. package/dist/apis/snapshot.cjs +6 -6
  91. package/dist/apis/snapshot.js +1 -1
  92. package/dist/apis/submission.cjs +6 -6
  93. package/dist/apis/submission.js +1 -1
  94. package/dist/apis/target.cjs +6 -6
  95. package/dist/apis/target.js +1 -1
  96. package/dist/apis/targeting.cjs +6 -6
  97. package/dist/apis/targeting.js +1 -1
  98. package/dist/apis/template-variables.cjs +6 -6
  99. package/dist/apis/template-variables.js +1 -1
  100. package/dist/apis/user.cjs +6 -6
  101. package/dist/apis/user.js +1 -1
  102. package/dist/apis/validation-rules.cjs +6 -6
  103. package/dist/apis/validation-rules.js +1 -1
  104. package/dist/apis/webhooks.cjs +6 -6
  105. package/dist/apis/webhooks.js +1 -1
  106. package/dist/apis/workflow-definition.cjs +6 -6
  107. package/dist/apis/workflow-definition.js +1 -1
  108. package/dist/apis/workflow.cjs +6 -6
  109. package/dist/apis/workflow.js +1 -1
  110. package/dist/{chunk-FZAVCO4Z.cjs → chunk-BY67WVUK.cjs} +1 -1
  111. package/dist/{chunk-L7M2HFK3.js → chunk-MCAD6CIA.js} +1 -1
  112. package/dist/index.cjs +8 -8
  113. package/dist/index.d.cts +1 -1
  114. package/dist/index.d.ts +1 -1
  115. package/dist/index.js +1 -1
  116. package/dist/pricing-2ZISBC2M.cjs +7 -0
  117. package/dist/pricing-CCNUYYYL.js +7 -0
  118. package/dist/{pricing.d-BKrHrQxy.d.cts → pricing.d-BCziNLXL.d.cts} +9791 -2746
  119. package/dist/{pricing.d-BKrHrQxy.d.ts → pricing.d-BCziNLXL.d.ts} +9791 -2746
  120. package/docs/pricing.md +1364 -244
  121. package/package.json +1 -1
  122. package/dist/pricing-QERD2QHS.cjs +0 -7
  123. package/dist/pricing-XJ7PKOWG.js +0 -7
package/docs/pricing.md CHANGED
@@ -68,15 +68,20 @@ const { data } = await pricingClient.$calculatePricingDetails(...)
68
68
  - [`$getConditionSets`](#$getconditionsets)
69
69
  - [`$resolveConditionalEntity`](#$resolveconditionalentity)
70
70
  - [`$createConditionalVariant`](#$createconditionalvariant)
71
+ - [`$listConditionalVariants`](#$listconditionalvariants)
72
+ - [`$getConditionalVariantTree`](#$getconditionalvarianttree)
71
73
  - [`$getActiveConditionalVariantVersion`](#$getactiveconditionalvariantversion)
72
74
  - [`$replaceActiveConditionalVariantVersion`](#$replaceactiveconditionalvariantversion)
73
75
  - [`$patchActiveConditionalVariantVersion`](#$patchactiveconditionalvariantversion)
74
76
  - [`$deleteConditionalVariant`](#$deleteconditionalvariant)
77
+ - [`$listConditionalVariantVersions`](#$listconditionalvariantversions)
75
78
  - [`$appendConditionalVariantVersion`](#$appendconditionalvariantversion)
76
79
  - [`$getConditionalVariantVersion`](#$getconditionalvariantversion)
77
80
  - [`$replaceConditionalVariantVersion`](#$replaceconditionalvariantversion)
78
81
  - [`$patchConditionalVariantVersion`](#$patchconditionalvariantversion)
79
82
  - [`$deleteConditionalVariantVersion`](#$deleteconditionalvariantversion)
83
+ - [`$batchUpsertConditionalVariants`](#$batchupsertconditionalvariants)
84
+ - [`$batchDeleteConditionalVariants`](#$batchdeleteconditionalvariants)
80
85
 
81
86
  **Schemas**
82
87
  - [`IntegrationId`](#integrationid)
@@ -87,8 +92,11 @@ const { data } = await pricingClient.$calculatePricingDetails(...)
87
92
  - [`ConditionSetCatalog`](#conditionsetcatalog)
88
93
  - [`ConditionalPricingErrorCode`](#conditionalpricingerrorcode)
89
94
  - [`ResolveConditionalEntityRequest`](#resolveconditionalentityrequest)
95
+ - [`ResolveByContextRequest`](#resolvebycontextrequest)
96
+ - [`ResolveByPinRequest`](#resolvebypinrequest)
90
97
  - [`ResolveContext`](#resolvecontext)
91
98
  - [`ResolveOptions`](#resolveoptions)
99
+ - [`PinnedResolveOptions`](#pinnedresolveoptions)
92
100
  - [`ResolvedVariants`](#resolvedvariants)
93
101
  - [`ResolvedVariant`](#resolvedvariant)
94
102
  - [`CreateVariantRequest`](#createvariantrequest)
@@ -96,16 +104,43 @@ const { data } = await pricingClient.$calculatePricingDetails(...)
96
104
  - [`PinnedConditions`](#pinnedconditions)
97
105
  - [`VariantValues`](#variantvalues)
98
106
  - [`CreatedVariant`](#createdvariant)
99
- - [`VariantWriteWarning`](#variantwritewarning)
107
+ - [`WriteWarning`](#writewarning)
108
+ - [`VersionMoved`](#versionmoved)
109
+ - [`InertOverride`](#inertoverride)
110
+ - [`InertOverrideReason`](#inertoverridereason)
100
111
  - [`DeletedVariant`](#deletedvariant)
101
112
  - [`VariantVersion`](#variantversion)
102
113
  - [`WrittenVariantVersion`](#writtenvariantversion)
103
114
  - [`DeletedVariantVersion`](#deletedvariantversion)
104
- - [`VersionWriteWarning`](#versionwritewarning)
105
115
  - [`AppendVersionRequest`](#appendversionrequest)
106
116
  - [`ReplaceVersionRequest`](#replaceversionrequest)
107
117
  - [`PatchVersionRequest`](#patchversionrequest)
118
+ - [`ListVariantsRequest`](#listvariantsrequest)
119
+ - [`VariantTreeRequest`](#varianttreerequest)
120
+ - [`VariantConditionFilter`](#variantconditionfilter)
121
+ - [`VariantList`](#variantlist)
122
+ - [`VariantListRow`](#variantlistrow)
123
+ - [`VariantTree`](#varianttree)
124
+ - [`VariantTreeRow`](#varianttreerow)
125
+ - [`VariantTreeRowStatus`](#varianttreerowstatus)
126
+ - [`VariantVersionSnapshot`](#variantversionsnapshot)
127
+ - [`VariantVersionList`](#variantversionlist)
128
+ - [`BatchUpsertVariantsRequest`](#batchupsertvariantsrequest)
129
+ - [`BatchUpsertItem`](#batchupsertitem)
130
+ - [`BatchDeleteVariantsRequest`](#batchdeletevariantsrequest)
131
+ - [`BatchDeleteItem`](#batchdeleteitem)
132
+ - [`BatchDeleteByVariantId`](#batchdeletebyvariantid)
133
+ - [`BatchDeleteByConditions`](#batchdeletebyconditions)
134
+ - [`BatchUpsertResult`](#batchupsertresult)
135
+ - [`BatchDeleteResult`](#batchdeleteresult)
136
+ - [`BatchUpsertOutcome`](#batchupsertoutcome)
137
+ - [`BatchDeleteOutcome`](#batchdeleteoutcome)
138
+ - [`BatchUpsertCounts`](#batchupsertcounts)
139
+ - [`BatchDeleteCounts`](#batchdeletecounts)
140
+ - [`BatchUpsertResultEntry`](#batchupsertresultentry)
141
+ - [`BatchDeleteResultEntry`](#batchdeleteresultentry)
108
142
  - [`Error`](#error)
143
+ - [`ReportedError`](#reportederror)
109
144
  - [`ConditionalPricingError`](#conditionalpricingerror)
110
145
  - [`Product`](#product)
111
146
  - [`Opportunity`](#opportunity)
@@ -1795,9 +1830,7 @@ const { data } = await client.$productRecommendations(
1795
1830
 
1796
1831
  ### `$getConditionSets`
1797
1832
 
1798
- Returns the condition sets built in for one conditional entity type: the situations a
1799
- conditional Product, Price or Coupon is commonly varied by, ready to be copied into that
1800
- schema's `conditions` arr
1833
+ Returns the condition sets built in for one conditional entity type, ready to copy into that schema's `conditions` array. Read-only, and the same for every organization.
1801
1834
 
1802
1835
  `GET /v1/conditional-pricing/{slug}/condition-sets`
1803
1836
 
@@ -1819,11 +1852,17 @@ const { data } = await client.$getConditionSets({
1819
1852
  "description": "string",
1820
1853
  "conditions": [
1821
1854
  {
1855
+ "id": "d5839b94-ba20-4225-a78e-76951d352bd6",
1822
1856
  "name": "postal_code",
1823
1857
  "label": "Postal Code",
1824
1858
  "type": "string",
1825
- "options": ["private", "commercial"],
1826
- "allow_any": false,
1859
+ "options": [
1860
+ "private",
1861
+ {
1862
+ "value": "commercial",
1863
+ "title": "Commercial customers"
1864
+ }
1865
+ ],
1827
1866
  "format": "zipcode"
1828
1867
  }
1829
1868
  ]
@@ -1838,8 +1877,8 @@ const { data } = await client.$getConditionSets({
1838
1877
 
1839
1878
  ### `$resolveConditionalEntity`
1840
1879
 
1841
- Resolves which of a conditional entity's variants apply to a situation, and returns each one
1842
- composed: the base entity overlaid with the values of the version in effect at `as_of`.
1880
+ Returns the variants of one conditional entity that apply, each composed: the base entity
1881
+ overlaid with the version in effect at `as_of`.
1843
1882
 
1844
1883
  `POST /v1/conditional-pricing:resolve`
1845
1884
 
@@ -1857,7 +1896,8 @@ const { data } = await client.$resolveConditionalEntity(
1857
1896
  },
1858
1897
  as_of: '2027-03-15T00:00:00Z',
1859
1898
  options: {
1860
- resolve_one: false
1899
+ resolve_one: false,
1900
+ hydrate: false
1861
1901
  }
1862
1902
  },
1863
1903
  )
@@ -1876,7 +1916,13 @@ const { data } = await client.$resolveConditionalEntity(
1876
1916
  "_conditions": {
1877
1917
  "postal_code": "46045",
1878
1918
  "default": false
1879
- }
1919
+ },
1920
+ "_inert_overrides": [
1921
+ {
1922
+ "attribute": "unit_amount",
1923
+ "reason": "ATTRIBUTE_NOT_OVERRIDABLE"
1924
+ }
1925
+ ]
1880
1926
  }
1881
1927
  ]
1882
1928
  }
@@ -1888,9 +1934,7 @@ const { data } = await client.$resolveConditionalEntity(
1888
1934
 
1889
1935
  ### `$createConditionalVariant`
1890
1936
 
1891
- Creates one variant of a conditional entity, together with the first version carrying its
1892
- values. Never two calls: a variant that existed without a version would be an entity holding
1893
- a condition tuple
1937
+ Creates one variant together with its first version.
1894
1938
 
1895
1939
  `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants`
1896
1940
 
@@ -1938,8 +1982,10 @@ const { data } = await client.$createConditionalVariant(
1938
1982
  {
1939
1983
  "code": "VARIANT_COUNT_APPROACHING_CAP",
1940
1984
  "message": "string",
1941
- "variant_count": 0,
1942
- "cap": 0
1985
+ "details": {
1986
+ "variant_count": 0,
1987
+ "cap": 0
1988
+ }
1943
1989
  }
1944
1990
  ]
1945
1991
  }
@@ -1949,10 +1995,137 @@ const { data } = await client.$createConditionalVariant(
1949
1995
 
1950
1996
  ---
1951
1997
 
1998
+ ### `$listConditionalVariants`
1999
+
2000
+ Lists a conditional entity's variants and the conditions each one pins. A `POST` because the
2001
+ condition filter is a structured object; nothing is written. The body is required, so send
2002
+ `{}` for the fir
2003
+
2004
+ `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants:list`
2005
+
2006
+ ```ts
2007
+ const { data } = await client.$listConditionalVariants(
2008
+ {
2009
+ slug: 'example',
2010
+ entity_id: 'example',
2011
+ },
2012
+ {
2013
+ conditions: {
2014
+ postal_code: '46045',
2015
+ consumption: {
2016
+ lt: 5000
2017
+ }
2018
+ },
2019
+ search: '460',
2020
+ sort: 'conditions.postal_code:asc',
2021
+ from: 0,
2022
+ size: 10,
2023
+ cursor: 'eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0'
2024
+ },
2025
+ )
2026
+ ```
2027
+
2028
+ <details>
2029
+ <summary>Response</summary>
2030
+
2031
+ ```json
2032
+ {
2033
+ "hits": 8128,
2034
+ "results": [
2035
+ {
2036
+ "variant_id": "var-46045",
2037
+ "entity_id": "price-sp26d1yo",
2038
+ "schema": "product",
2039
+ "conditions": {
2040
+ "postal_code": "46045",
2041
+ "default": false
2042
+ }
2043
+ }
2044
+ ],
2045
+ "next": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0"
2046
+ }
2047
+ ```
2048
+
2049
+ </details>
2050
+
2051
+ ---
2052
+
2053
+ ### `$getConditionalVariantTree`
2054
+
2055
+ The variants list, each row carrying the version in effect at `as_of` and a `status` saying
2056
+ whether that version is `active` or still `scheduled`.
2057
+
2058
+ `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants:tree`
2059
+
2060
+ ```ts
2061
+ const { data } = await client.$getConditionalVariantTree(
2062
+ {
2063
+ slug: 'example',
2064
+ entity_id: 'example',
2065
+ },
2066
+ {
2067
+ conditions: {
2068
+ postal_code: '46045',
2069
+ consumption: {
2070
+ lt: 5000
2071
+ }
2072
+ },
2073
+ search: '460',
2074
+ sort: 'conditions.postal_code:asc',
2075
+ from: 0,
2076
+ size: 10,
2077
+ cursor: 'eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0',
2078
+ as_of: '2027-03-15T00:00:00Z'
2079
+ },
2080
+ )
2081
+ ```
2082
+
2083
+ <details>
2084
+ <summary>Response</summary>
2085
+
2086
+ ```json
2087
+ {
2088
+ "hits": 8128,
2089
+ "results": [
2090
+ {
2091
+ "variant_id": "var-46045",
2092
+ "entity_id": "price-sp26d1yo",
2093
+ "schema": "product",
2094
+ "conditions": {
2095
+ "postal_code": "46045",
2096
+ "default": false
2097
+ },
2098
+ "status": "active",
2099
+ "version": {
2100
+ "variant_id": "var-46045",
2101
+ "entity_id": "price-sp26d1yo",
2102
+ "schema": "product",
2103
+ "conditions": {
2104
+ "postal_code": "46045",
2105
+ "default": false
2106
+ },
2107
+ "valid_from": "2027-01-01T00:00:00.000Z",
2108
+ "values": {
2109
+ "unit_amount": 2499,
2110
+ "unit_amount_decimal": "24.99"
2111
+ },
2112
+ "_created_at": "string",
2113
+ "_updated_at": "string"
2114
+ }
2115
+ }
2116
+ ],
2117
+ "next": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0"
2118
+ }
2119
+ ```
2120
+
2121
+ </details>
2122
+
2123
+ ---
2124
+
1952
2125
  ### `$getActiveConditionalVariantVersion`
1953
2126
 
1954
- Returns the version of this variant that is currently in effect — the one with the latest
1955
- `valid_from` at or before now.
2127
+ Returns the version of this variant in effect now — the latest `valid_from` at or before now
2128
+ — with the `_revision` a write to it must carry.
1956
2129
 
1957
2130
  `GET /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}`
1958
2131
 
@@ -1993,7 +2166,9 @@ const { data } = await client.$getActiveConditionalVariantVersion({
1993
2166
 
1994
2167
  ### `$replaceActiveConditionalVariantVersion`
1995
2168
 
1996
- Replaces the values of the version currently in effect, wholesale.
2169
+ Replaces the values of the version in effect. The body is the complete set of overrides: an
2170
+ overridable attribute absent from it stops being overridden, and one the variant may not
2171
+ override keeps its
1997
2172
 
1998
2173
  `PUT /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}`
1999
2174
 
@@ -2040,10 +2215,12 @@ const { data } = await client.$replaceActiveConditionalVariantVersion(
2040
2215
  "_revision": 3,
2041
2216
  "warnings": [
2042
2217
  {
2043
- "code": "ACTIVE_VERSION_REPLACED",
2218
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2044
2219
  "message": "string",
2045
- "valid_from": "2026-08-01T00:00:00.000Z",
2046
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2220
+ "details": {
2221
+ "variant_count": 0,
2222
+ "cap": 0
2223
+ }
2047
2224
  }
2048
2225
  ]
2049
2226
  }
@@ -2055,7 +2232,8 @@ const { data } = await client.$replaceActiveConditionalVariantVersion(
2055
2232
 
2056
2233
  ### `$patchActiveConditionalVariantVersion`
2057
2234
 
2058
- Changes only the fields it names on the version currently in effect.
2235
+ Changes only the fields it names on the version in effect. `null` sets a value rather than
2236
+ removing an override; use the replace operation to remove one.
2059
2237
 
2060
2238
  `PATCH /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}`
2061
2239
 
@@ -2102,10 +2280,12 @@ const { data } = await client.$patchActiveConditionalVariantVersion(
2102
2280
  "_revision": 3,
2103
2281
  "warnings": [
2104
2282
  {
2105
- "code": "ACTIVE_VERSION_REPLACED",
2283
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2106
2284
  "message": "string",
2107
- "valid_from": "2026-08-01T00:00:00.000Z",
2108
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2285
+ "details": {
2286
+ "variant_count": 0,
2287
+ "cap": 0
2288
+ }
2109
2289
  }
2110
2290
  ]
2111
2291
  }
@@ -2117,8 +2297,8 @@ const { data } = await client.$patchActiveConditionalVariantVersion(
2117
2297
 
2118
2298
  ### `$deleteConditionalVariant`
2119
2299
 
2120
- Removes one variant of a conditional entity: the condition tuple it holds, its registration
2121
- in the search index, and every version it accumulated.
2300
+ Removes one variant: its condition tuple, its index entry and all its versions. The tuple
2301
+ becomes reusable, and an interrupted delete is safe to send again.
2122
2302
 
2123
2303
  `DELETE /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}`
2124
2304
 
@@ -2147,9 +2327,60 @@ const { data } = await client.$deleteConditionalVariant({
2147
2327
 
2148
2328
  ---
2149
2329
 
2330
+ ### `$listConditionalVariantVersions`
2331
+
2332
+ Lists one variant's versions. Cursor paging only: a page may be short or empty and still
2333
+ carry a `next`, so page until `next` is absent. A cursor is bound to one variant and one
2334
+ `order`.
2335
+
2336
+ `GET /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions`
2337
+
2338
+ ```ts
2339
+ const { data } = await client.$listConditionalVariantVersions({
2340
+ slug: 'example',
2341
+ entity_id: 'example',
2342
+ variant_id: 'example',
2343
+ limit: 1,
2344
+ order: 'example',
2345
+ cursor: 'example',
2346
+ })
2347
+ ```
2348
+
2349
+ <details>
2350
+ <summary>Response</summary>
2351
+
2352
+ ```json
2353
+ {
2354
+ "results": [
2355
+ {
2356
+ "variant_id": "var-46045",
2357
+ "entity_id": "price-sp26d1yo",
2358
+ "schema": "product",
2359
+ "conditions": {
2360
+ "postal_code": "46045",
2361
+ "default": false
2362
+ },
2363
+ "valid_from": "2027-01-01T00:00:00.000Z",
2364
+ "values": {
2365
+ "unit_amount": 2499,
2366
+ "unit_amount_decimal": "24.99"
2367
+ },
2368
+ "_created_at": "string",
2369
+ "_updated_at": "string"
2370
+ }
2371
+ ],
2372
+ "next": "eyJzayI6IlYjcHJpY2Utc3AyNmQxeW8jdmFyLTQ2MDQ1IzIwMjYtMDEtMDFUMDA6MDA6MDAuMDAwWiIsIm9yZGVyIjoiYXNjIn0"
2373
+ }
2374
+ ```
2375
+
2376
+ </details>
2377
+
2378
+ ---
2379
+
2150
2380
  ### `$appendConditionalVariantVersion`
2151
2381
 
2152
- Appends a version to a variant: a new set of values taking effect at its own instant.
2382
+ Appends a version taking effect at its own instant. The version in effect at any instant is
2383
+ the one with the latest `valid_from` at or before it; a future one is staged until its date.
2153
2384
 
2154
2385
  `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions`
2155
2386
 
@@ -2195,10 +2426,12 @@ const { data } = await client.$appendConditionalVariantVersion(
2195
2426
  "_revision": 3,
2196
2427
  "warnings": [
2197
2428
  {
2198
- "code": "ACTIVE_VERSION_REPLACED",
2429
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2199
2430
  "message": "string",
2200
- "valid_from": "2026-08-01T00:00:00.000Z",
2201
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2431
+ "details": {
2432
+ "variant_count": 0,
2433
+ "cap": 0
2434
+ }
2202
2435
  }
2203
2436
  ]
2204
2437
  }
@@ -2210,8 +2443,7 @@ const { data } = await client.$appendConditionalVariantVersion(
2210
2443
 
2211
2444
  ### `$getConditionalVariantVersion`
2212
2445
 
2213
- Returns one specific version of a variant, by the instant it takes effect — what a form editing
2214
- that version loads.
2446
+ Returns one version by the instant it takes effect. Exact, never nearest.
2215
2447
 
2216
2448
  `GET /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions/{valid_from}`
2217
2449
 
@@ -2253,7 +2485,8 @@ const { data } = await client.$getConditionalVariantVersion({
2253
2485
 
2254
2486
  ### `$replaceConditionalVariantVersion`
2255
2487
 
2256
- Replaces one version's values wholesale, addressed by its `valid_from`.
2488
+ Replaces one version's values, whatever its date. Attributes the variant may not override
2489
+ keep their stored value. Writing a superseded version is reported in `warnings`.
2257
2490
 
2258
2491
  `PUT /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions/{valid_from}`
2259
2492
 
@@ -2301,10 +2534,12 @@ const { data } = await client.$replaceConditionalVariantVersion(
2301
2534
  "_revision": 3,
2302
2535
  "warnings": [
2303
2536
  {
2304
- "code": "ACTIVE_VERSION_REPLACED",
2537
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2305
2538
  "message": "string",
2306
- "valid_from": "2026-08-01T00:00:00.000Z",
2307
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2539
+ "details": {
2540
+ "variant_count": 0,
2541
+ "cap": 0
2542
+ }
2308
2543
  }
2309
2544
  ]
2310
2545
  }
@@ -2316,7 +2551,7 @@ const { data } = await client.$replaceConditionalVariantVersion(
2316
2551
 
2317
2552
  ### `$patchConditionalVariantVersion`
2318
2553
 
2319
- Changes only the fields it names on one version, addressed by its `valid_from`.
2554
+ Changes only the fields it names on one version.
2320
2555
 
2321
2556
  `PATCH /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions/{valid_from}`
2322
2557
 
@@ -2364,10 +2599,12 @@ const { data } = await client.$patchConditionalVariantVersion(
2364
2599
  "_revision": 3,
2365
2600
  "warnings": [
2366
2601
  {
2367
- "code": "ACTIVE_VERSION_REPLACED",
2602
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2368
2603
  "message": "string",
2369
- "valid_from": "2026-08-01T00:00:00.000Z",
2370
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2604
+ "details": {
2605
+ "variant_count": 0,
2606
+ "cap": 0
2607
+ }
2371
2608
  }
2372
2609
  ]
2373
2610
  }
@@ -2379,7 +2616,8 @@ const { data } = await client.$patchConditionalVariantVersion(
2379
2616
 
2380
2617
  ### `$deleteConditionalVariantVersion`
2381
2618
 
2382
- Removes one version of a variant.
2619
+ Removes one version. What the removal moves is reported in `warnings`. A variant's last
2620
+ remaining version cannot be removed — delete the variant instead.
2383
2621
 
2384
2622
  `DELETE /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions/{valid_from}`
2385
2623
 
@@ -2404,10 +2642,156 @@ const { data } = await client.$deleteConditionalVariantVersion({
2404
2642
  "valid_from": "2027-01-01T00:00:00.000Z",
2405
2643
  "warnings": [
2406
2644
  {
2407
- "code": "ACTIVE_VERSION_REPLACED",
2645
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2408
2646
  "message": "string",
2409
- "valid_from": "2026-08-01T00:00:00.000Z",
2410
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2647
+ "details": {
2648
+ "variant_count": 0,
2649
+ "cap": 0
2650
+ }
2651
+ }
2652
+ ]
2653
+ }
2654
+ ```
2655
+
2656
+ </details>
2657
+
2658
+ ---
2659
+
2660
+ ### `$batchUpsertConditionalVariants`
2661
+
2662
+ Writes up to 100 variants or versions in one call. Each item names its own entity, so one
2663
+ call can span a tariff hierarchy, and addresses a variant by condition tuple rather than by
2664
+ id — the id it cre
2665
+
2666
+ `POST /v1/conditional-pricing/{slug}/variants:batchUpsert`
2667
+
2668
+ ```ts
2669
+ const { data } = await client.$batchUpsertConditionalVariants(
2670
+ {
2671
+ slug: 'example',
2672
+ },
2673
+ {
2674
+ correlation_id: 'tariff-refresh-2027-01',
2675
+ items: [
2676
+ {
2677
+ entity_id: 'price-sp26d1yo',
2678
+ conditions: {
2679
+ postal_code: '46045'
2680
+ },
2681
+ default: false,
2682
+ valid_from: '2027-01-01T00:00:00Z',
2683
+ values: {
2684
+ unit_amount: 2499,
2685
+ unit_amount_decimal: '24.99'
2686
+ }
2687
+ }
2688
+ ]
2689
+ },
2690
+ )
2691
+ ```
2692
+
2693
+ <details>
2694
+ <summary>Response</summary>
2695
+
2696
+ ```json
2697
+ {
2698
+ "correlation_id": "tariff-refresh-2027-01",
2699
+ "counts": {
2700
+ "variant_created": 1,
2701
+ "version_created": 1,
2702
+ "updated": 1,
2703
+ "skipped": 1,
2704
+ "error": 1
2705
+ },
2706
+ "results": [
2707
+ {
2708
+ "outcome": "variant_created",
2709
+ "entity_id": "price-sp26d1yo",
2710
+ "variant_id": "var-46045",
2711
+ "valid_from": "2027-01-01T00:00:00.000Z",
2712
+ "warnings": [
2713
+ {
2714
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2715
+ "message": "string",
2716
+ "details": {
2717
+ "variant_count": 0,
2718
+ "cap": 0
2719
+ }
2720
+ }
2721
+ ],
2722
+ "error": {
2723
+ "code": "SCHEMA_NOT_FOUND",
2724
+ "details": {
2725
+ "schema": "price"
2726
+ }
2727
+ }
2728
+ }
2729
+ ]
2730
+ }
2731
+ ```
2732
+
2733
+ </details>
2734
+
2735
+ ---
2736
+
2737
+ ### `$batchDeleteConditionalVariants`
2738
+
2739
+ Removes up to 100 variants or versions in one call. An item carrying `valid_from` removes
2740
+ that version; one without it removes the whole variant.
2741
+
2742
+ `POST /v1/conditional-pricing/{slug}/variants:batchDelete`
2743
+
2744
+ ```ts
2745
+ const { data } = await client.$batchDeleteConditionalVariants(
2746
+ {
2747
+ slug: 'example',
2748
+ },
2749
+ {
2750
+ correlation_id: 'postal-code-cleanup-2026-09',
2751
+ items: [
2752
+ {
2753
+ entity_id: 'price-sp26d1yo',
2754
+ variant_id: 'var-46045',
2755
+ valid_from: '2027-01-01T00:00:00Z'
2756
+ }
2757
+ ]
2758
+ },
2759
+ )
2760
+ ```
2761
+
2762
+ <details>
2763
+ <summary>Response</summary>
2764
+
2765
+ ```json
2766
+ {
2767
+ "correlation_id": "postal-code-cleanup-2026-09",
2768
+ "counts": {
2769
+ "deleted": 1,
2770
+ "skipped": 1,
2771
+ "error": 1
2772
+ },
2773
+ "results": [
2774
+ {
2775
+ "outcome": "deleted",
2776
+ "entity_id": "price-sp26d1yo",
2777
+ "variant_id": "var-46045",
2778
+ "valid_from": "2027-01-01T00:00:00.000Z",
2779
+ "warnings": [
2780
+ {
2781
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2782
+ "message": "string",
2783
+ "details": {
2784
+ "variant_count": 0,
2785
+ "cap": 0
2786
+ }
2787
+ }
2788
+ ],
2789
+ "error": {
2790
+ "code": "SCHEMA_NOT_FOUND",
2791
+ "details": {
2792
+ "schema": "price"
2793
+ }
2794
+ }
2411
2795
  }
2412
2796
  ]
2413
2797
  }
@@ -2427,9 +2811,7 @@ type IntegrationId = "getag" | "external-catalog"
2427
2811
 
2428
2812
  ### `ConditionalEntitySlug`
2429
2813
 
2430
- Schema slug of an entity type that can be conditional — the `{slug}` of every
2431
- conditional-pricing route.
2432
-
2814
+ Schema slug of an entity type that can be conditional — the `{slug}` of every conditional-pricing route.
2433
2815
 
2434
2816
  ```ts
2435
2817
  type ConditionalEntitySlug = "product" | "price" | "coupon"
@@ -2437,13 +2819,13 @@ type ConditionalEntitySlug = "product" | "price" | "coupon"
2437
2819
 
2438
2820
  ### `ConditionType`
2439
2821
 
2440
- The kind of value a condition holds, which decides how a variant's pinned value is matched
2441
- against a resolve context.
2822
+ The kind of value a condition holds, which decides how a pinned value is matched against a
2823
+ resolve context.
2442
2824
 
2443
2825
  - `string`: an arbitrary string, matched exactly and case-sensitively
2444
2826
  - `number`: a numeric value
2445
2827
  - `date`: a single date
2446
- - `daterange`: a window with a from and an until timestamp;
2828
+ - `daterange`: a window with a from and an until timestamp; either en
2447
2829
 
2448
2830
  ```ts
2449
2831
  type ConditionType = "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"
@@ -2451,12 +2833,11 @@ type ConditionType = "string" | "number" | "date" | "daterange" | "boolean" | "s
2451
2833
 
2452
2834
  ### `ConditionDefinition`
2453
2835
 
2454
- One condition dimension, in the shape a schema's `conditions` array holds it — copy it in
2455
- verbatim.
2456
-
2836
+ One condition dimension, in the shape a schema's `conditions` array holds it — copy it in verbatim.
2457
2837
 
2458
2838
  ```ts
2459
2839
  type ConditionDefinition = {
2840
+ id: string // uuid
2460
2841
  name: string
2461
2842
  label: string
2462
2843
  type: "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"
@@ -2464,8 +2845,7 @@ type ConditionDefinition = {
2464
2845
  value: string
2465
2846
  title?: string
2466
2847
  }>
2467
- allow_any?: boolean
2468
- format?: "zipcode" | "zipcode + town"
2848
+ format?: "zipcode" | "zipcode_town"
2469
2849
  }
2470
2850
  ```
2471
2851
 
@@ -2479,6 +2859,7 @@ type ConditionSet = {
2479
2859
  label: string
2480
2860
  description: string
2481
2861
  conditions: Array<{
2862
+ id: string // uuid
2482
2863
  name: string
2483
2864
  label: string
2484
2865
  type: "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"
@@ -2486,8 +2867,7 @@ type ConditionSet = {
2486
2867
  value: { ... }
2487
2868
  title?: { ... }
2488
2869
  }>
2489
- allow_any?: boolean
2490
- format?: "zipcode" | "zipcode + town"
2870
+ format?: "zipcode" | "zipcode_town"
2491
2871
  }>
2492
2872
  }
2493
2873
  ```
@@ -2501,11 +2881,11 @@ type ConditionSetCatalog = {
2501
2881
  label: string
2502
2882
  description: string
2503
2883
  conditions: Array<{
2884
+ id: { ... }
2504
2885
  name: { ... }
2505
2886
  label: { ... }
2506
2887
  type: { ... }
2507
2888
  options?: { ... }
2508
- allow_any?: { ... }
2509
2889
  format?: { ... }
2510
2890
  }>
2511
2891
  }>
@@ -2514,87 +2894,696 @@ type ConditionSetCatalog = {
2514
2894
 
2515
2895
  ### `ConditionalPricingErrorCode`
2516
2896
 
2517
- Machine-readable failure mode of a conditional-pricing operation, allowing clients
2518
- to branch on the kind of failure instead of parsing the error message.
2897
+ Machine-readable failure mode of a conditional-pricing operation, so a client can branch on
2898
+ the kind of failure instead of parsing the message. A `400` is about the request; a `409` is
2899
+ about what is already stored. Refusals raised by request validation carry no `code` at all.
2519
2900
 
2520
- - `NOT_FOUND` (404): the addressed entity, variant or version does not exist
2521
- - `AMBIGUOUS_RESOLUTION` (409): several variants match the given con
2901
+ - `SCHEMA_NOT_FOUND` (
2522
2902
 
2523
2903
  ```ts
2524
- 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"
2904
+ 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" | "VARIANT_PIN_UNDECLARED" | "OPERATOR_UNSUPPORTED" | "CONTEXT_FORMAT_INVALID" | "CONDITION_VALUE_INVALID" | "CONDITION_UNCONFIGURED" | "TOO_MANY_MATCHES" | "WRITE_CONFLICT" | "OFFSET_WINDOW_EXCEEDED" | "CURSOR_INVALID" | "VARIANT_LIMIT_REACHED" | "PIN_FORMAT_INVALID" | "VARIANT_UNPINNED" | "LAST_VERSION_UNDELETABLE" | "CONDITION_UNREADABLE" | "SORT_INVALID" | "DEFAULT_MARKER_RESERVED" | "DEFAULT_VARIANT_PINS_CONDITIONS" | "VALID_FROM_IMMUTABLE" | "VARIANT_CONDITIONS_IMMUTABLE" | "IDENTIFIER_INVALID" | "VALID_FROM_INVALID" | "VALUE_UNSTORABLE"
2525
2905
  ```
2526
2906
 
2527
2907
  ### `ResolveConditionalEntityRequest`
2528
2908
 
2909
+ A resolve names one conditional entity and selects its variants either by `context` or by
2910
+ `variant_id`, never both. `context: {}` matches nothing and so returns the `default`
2911
+ variant, which is how to ask for it without knowing its id.
2912
+
2913
+
2529
2914
  ```ts
2530
2915
  type ResolveConditionalEntityRequest = {
2531
2916
  schema: "product" | "price" | "coupon"
2532
2917
  entity_id: string
2533
- context?: Record<string, unknown>
2534
- as_of?: string
2535
- options?: {
2536
- resolve_one?: boolean
2918
+ context: Record<string, unknown>
2919
+ as_of?: string
2920
+ options?: {
2921
+ resolve_one?: boolean
2922
+ hydrate?: boolean
2923
+ }
2924
+ } | {
2925
+ schema: "product" | "price" | "coupon"
2926
+ entity_id: string
2927
+ variant_id: string
2928
+ as_of?: string
2929
+ options?: {
2930
+ hydrate?: boolean
2931
+ }
2932
+ }
2933
+ ```
2934
+
2935
+ ### `ResolveByContextRequest`
2936
+
2937
+ Resolve by matching a situation: which of this entity's variants apply to `context`, each
2938
+ composed with the version in effect at `as_of`.
2939
+
2940
+
2941
+ ```ts
2942
+ type ResolveByContextRequest = {
2943
+ schema: "product" | "price" | "coupon"
2944
+ entity_id: string
2945
+ context: Record<string, unknown>
2946
+ as_of?: string
2947
+ options?: {
2948
+ resolve_one?: boolean
2949
+ hydrate?: boolean
2950
+ }
2951
+ }
2952
+ ```
2953
+
2954
+ ### `ResolveByPinRequest`
2955
+
2956
+ Resolve by naming a variant: compose this one, whatever a context would have matched.
2957
+
2958
+ ```ts
2959
+ type ResolveByPinRequest = {
2960
+ schema: "product" | "price" | "coupon"
2961
+ entity_id: string
2962
+ variant_id: string
2963
+ as_of?: string
2964
+ options?: {
2965
+ hydrate?: boolean
2966
+ }
2967
+ }
2968
+ ```
2969
+
2970
+ ### `ResolveContext`
2971
+
2972
+ The situation to resolve for: a flat map keyed by condition name. A condition left out
2973
+ matches only variants that leave it unpinned; an empty map therefore returns the `default`
2974
+ variant.
2975
+
2976
+ Each value is an exact value, typed by its condition, or a single-operator predicate:
2977
+
2978
+ - `{ "lt": v }`, `{ "lte"
2979
+
2980
+ ```ts
2981
+ type ResolveContext = Record<string, unknown>
2982
+ ```
2983
+
2984
+ ### `ResolveOptions`
2985
+
2986
+ The options a context resolve accepts. A pin takes `PinnedResolveOptions` instead.
2987
+
2988
+ ```ts
2989
+ type ResolveOptions = {
2990
+ resolve_one?: boolean
2991
+ hydrate?: boolean
2992
+ }
2993
+ ```
2994
+
2995
+ ### `PinnedResolveOptions`
2996
+
2997
+ The options a pinned resolve accepts — `hydrate` and nothing else. `resolve_one` has nothing
2998
+ to change where the answer is one result or a 404, so a body sending it is a `400`.
2999
+
3000
+
3001
+ ```ts
3002
+ type PinnedResolveOptions = {
3003
+ hydrate?: boolean
3004
+ }
3005
+ ```
3006
+
3007
+ ### `ResolvedVariants`
3008
+
3009
+ ```ts
3010
+ type ResolvedVariants = {
3011
+ results: Array<{
3012
+ _id: string
3013
+ _variant_id: string
3014
+ _version_valid_from: string
3015
+ _conditions: {
3016
+ default: { ... }
3017
+ }
3018
+ _inert_overrides: Array<{
3019
+ attribute: { ... }
3020
+ reason: { ... }
3021
+ }>
3022
+ }>
3023
+ }
3024
+ ```
3025
+
3026
+ ### `ResolvedVariant`
3027
+
3028
+ The entity as this variant leaves it — every attribute of a plain entity read with the
3029
+ applicable version's overrides applied — plus the discriminators below.
3030
+
3031
+
3032
+ ```ts
3033
+ type ResolvedVariant = {
3034
+ _id: string
3035
+ _variant_id: string
3036
+ _version_valid_from: string
3037
+ _conditions: {
3038
+ default: boolean
3039
+ }
3040
+ _inert_overrides: Array<{
3041
+ attribute: string
3042
+ reason: "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"
3043
+ }>
3044
+ }
3045
+ ```
3046
+
3047
+ ### `CreateVariantRequest`
3048
+
3049
+ ```ts
3050
+ type CreateVariantRequest = {
3051
+ conditions?: Record<string, unknown>
3052
+ default?: boolean
3053
+ valid_from?: string
3054
+ values: Record<string, unknown>
3055
+ }
3056
+ ```
3057
+
3058
+ ### `VariantConditions`
3059
+
3060
+ A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a
3061
+ boolean `default` saying whether this is the entity's fallback.
3062
+
3063
+
3064
+ ```ts
3065
+ type VariantConditions = {
3066
+ default: boolean
3067
+ }
3068
+ ```
3069
+
3070
+ ### `PinnedConditions`
3071
+
3072
+ The situation this variant applies to: a flat map keyed by condition name. A condition left
3073
+ out is a wildcard, which is what makes adding a condition to a schema non-breaking for
3074
+ existing variants.
3075
+
3076
+ Exact values only; predicates belong to reads. Values are stored canonicalized for their
3077
+ type: a `dat
3078
+
3079
+ ```ts
3080
+ type PinnedConditions = Record<string, unknown>
3081
+ ```
3082
+
3083
+ ### `VariantValues`
3084
+
3085
+ The values this version overrides on the base entity, keyed by entity field name.
3086
+
3087
+ A field is overridable if its attribute declares `overridable_attribute` — which readonly,
3088
+ hidden, computed and metadata fields, and types no variant may override, cannot be given —
3089
+ or if a capability declaring `overr
3090
+
3091
+ ```ts
3092
+ type VariantValues = Record<string, unknown>
3093
+ ```
3094
+
3095
+ ### `CreatedVariant`
3096
+
3097
+ ```ts
3098
+ type CreatedVariant = {
3099
+ variant_id: string
3100
+ entity_id: string
3101
+ schema: "product" | "price" | "coupon"
3102
+ conditions: {
3103
+ default: boolean
3104
+ }
3105
+ valid_from: string
3106
+ values: Record<string, unknown>
3107
+ _created_at: string
3108
+ _updated_at: string
3109
+ _revision: number
3110
+ warnings: Array<{
3111
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3112
+ message: string
3113
+ details: {
3114
+ variant_count: { ... }
3115
+ cap: { ... }
3116
+ }
3117
+ } | {
3118
+ code: "ACTIVE_VERSION_CHANGED"
3119
+ message: string
3120
+ details: {
3121
+ valid_from: { ... }
3122
+ active_valid_from?: { ... }
3123
+ }
3124
+ } | {
3125
+ code: "SUPERSEDED_VERSION_WRITTEN"
3126
+ message: string
3127
+ details: {
3128
+ valid_from: { ... }
3129
+ active_valid_from?: { ... }
3130
+ }
3131
+ } | {
3132
+ code: "ATTRIBUTES_NOT_APPLIED"
3133
+ message: string
3134
+ details: {
3135
+ attributes: { ... }
3136
+ }
3137
+ }>
3138
+ }
3139
+ ```
3140
+
3141
+ ### `WriteWarning`
3142
+
3143
+ Something worth knowing that did not stop a write. One vocabulary for every write; `details`
3144
+ is typed per `code`, and a write raises each code at most once.
3145
+
3146
+
3147
+ ```ts
3148
+ type WriteWarning = {
3149
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3150
+ message: string
3151
+ details: {
3152
+ variant_count: number
3153
+ cap: number
3154
+ }
3155
+ } | {
3156
+ code: "ACTIVE_VERSION_CHANGED"
3157
+ message: string
3158
+ details: {
3159
+ valid_from: string
3160
+ active_valid_from?: string
3161
+ }
3162
+ } | {
3163
+ code: "SUPERSEDED_VERSION_WRITTEN"
3164
+ message: string
3165
+ details: {
3166
+ valid_from: string
3167
+ active_valid_from?: string
3168
+ }
3169
+ } | {
3170
+ code: "ATTRIBUTES_NOT_APPLIED"
3171
+ message: string
3172
+ details: {
3173
+ attributes: Array<{
3174
+ attribute: { ... }
3175
+ reason: { ... }
3176
+ }>
3177
+ }
3178
+ }
3179
+ ```
3180
+
3181
+ ### `VersionMoved`
3182
+
3183
+ Which version a write moved, and which one was in effect while it did.
3184
+
3185
+ ```ts
3186
+ type VersionMoved = {
3187
+ valid_from: string
3188
+ active_valid_from?: string
3189
+ }
3190
+ ```
3191
+
3192
+ ### `InertOverride`
3193
+
3194
+ One override that did not apply, and why — reported by a write for the attributes in its
3195
+ body, and by a resolved payload for the stored overrides composition passed over.
3196
+
3197
+
3198
+ ```ts
3199
+ type InertOverride = {
3200
+ attribute: string
3201
+ reason: "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"
3202
+ }
3203
+ ```
3204
+
3205
+ ### `InertOverrideReason`
3206
+
3207
+ Why one override did not apply.
3208
+
3209
+ - `ATTRIBUTE_NOT_OVERRIDABLE`: the schema declares the attribute without
3210
+ `overridable_attribute`, which is an ordinary schema edit away
3211
+ - `ATTRIBUTE_READONLY`: the attribute is readonly, and cannot be granted the flag
3212
+ - `ATTRIBUTE_HIDDEN`: the attribute is hidden,
3213
+
3214
+ ```ts
3215
+ type InertOverrideReason = "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"
3216
+ ```
3217
+
3218
+ ### `DeletedVariant`
3219
+
3220
+ ```ts
3221
+ type DeletedVariant = {
3222
+ variant_id: string
3223
+ entity_id: string
3224
+ schema: "product" | "price" | "coupon"
3225
+ tuple_released: boolean
3226
+ versions_deleted: number
3227
+ }
3228
+ ```
3229
+
3230
+ ### `VariantVersion`
3231
+
3232
+ One version of one variant: the overrides it carries, the instant it takes effect, and the
3233
+ variant it belongs to. These are the version's own overrides; `:resolve` composes them onto
3234
+ the entity.
3235
+
3236
+
3237
+ ```ts
3238
+ type VariantVersion = {
3239
+ variant_id: string
3240
+ entity_id: string
3241
+ schema: "product" | "price" | "coupon"
3242
+ conditions: {
3243
+ default: boolean
3244
+ }
3245
+ valid_from: string
3246
+ values: Record<string, unknown>
3247
+ _created_at: string
3248
+ _updated_at: string
3249
+ _revision: number
3250
+ }
3251
+ ```
3252
+
3253
+ ### `WrittenVariantVersion`
3254
+
3255
+ A version as a write left it, together with anything the write moved.
3256
+
3257
+ ```ts
3258
+ type WrittenVariantVersion = {
3259
+ variant_id: string
3260
+ entity_id: string
3261
+ schema: "product" | "price" | "coupon"
3262
+ conditions: {
3263
+ default: boolean
3264
+ }
3265
+ valid_from: string
3266
+ values: Record<string, unknown>
3267
+ _created_at: string
3268
+ _updated_at: string
3269
+ _revision: number
3270
+ warnings: Array<{
3271
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3272
+ message: string
3273
+ details: {
3274
+ variant_count: { ... }
3275
+ cap: { ... }
3276
+ }
3277
+ } | {
3278
+ code: "ACTIVE_VERSION_CHANGED"
3279
+ message: string
3280
+ details: {
3281
+ valid_from: { ... }
3282
+ active_valid_from?: { ... }
3283
+ }
3284
+ } | {
3285
+ code: "SUPERSEDED_VERSION_WRITTEN"
3286
+ message: string
3287
+ details: {
3288
+ valid_from: { ... }
3289
+ active_valid_from?: { ... }
3290
+ }
3291
+ } | {
3292
+ code: "ATTRIBUTES_NOT_APPLIED"
3293
+ message: string
3294
+ details: {
3295
+ attributes: { ... }
3296
+ }
3297
+ }>
3298
+ }
3299
+ ```
3300
+
3301
+ ### `DeletedVariantVersion`
3302
+
3303
+ ```ts
3304
+ type DeletedVariantVersion = {
3305
+ variant_id: string
3306
+ entity_id: string
3307
+ schema: "product" | "price" | "coupon"
3308
+ valid_from: string
3309
+ warnings: Array<{
3310
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3311
+ message: string
3312
+ details: {
3313
+ variant_count: { ... }
3314
+ cap: { ... }
3315
+ }
3316
+ } | {
3317
+ code: "ACTIVE_VERSION_CHANGED"
3318
+ message: string
3319
+ details: {
3320
+ valid_from: { ... }
3321
+ active_valid_from?: { ... }
3322
+ }
3323
+ } | {
3324
+ code: "SUPERSEDED_VERSION_WRITTEN"
3325
+ message: string
3326
+ details: {
3327
+ valid_from: { ... }
3328
+ active_valid_from?: { ... }
3329
+ }
3330
+ } | {
3331
+ code: "ATTRIBUTES_NOT_APPLIED"
3332
+ message: string
3333
+ details: {
3334
+ attributes: { ... }
3335
+ }
3336
+ }>
3337
+ }
3338
+ ```
3339
+
3340
+ ### `AppendVersionRequest`
3341
+
3342
+ ```ts
3343
+ type AppendVersionRequest = {
3344
+ valid_from?: string
3345
+ values: Record<string, unknown>
3346
+ conditions?: Record<string, unknown>
3347
+ }
3348
+ ```
3349
+
3350
+ ### `ReplaceVersionRequest`
3351
+
3352
+ ```ts
3353
+ type ReplaceVersionRequest = {
3354
+ values: Record<string, unknown>
3355
+ _revision: number
3356
+ valid_from?: string
3357
+ conditions?: Record<string, unknown>
3358
+ }
3359
+ ```
3360
+
3361
+ ### `PatchVersionRequest`
3362
+
3363
+ ```ts
3364
+ type PatchVersionRequest = {
3365
+ values: Record<string, unknown>
3366
+ _revision: number
3367
+ valid_from?: string
3368
+ conditions?: Record<string, unknown>
3369
+ }
3370
+ ```
3371
+
3372
+ ### `ListVariantsRequest`
3373
+
3374
+ How to narrow and page a variant listing. Every property is optional, so `{}` asks for the
3375
+ first ten variants in `variant_id` order, but the body itself is required. `conditions` and
3376
+ `search` narrow independently and a variant must satisfy both.
3377
+
3378
+
3379
+ ```ts
3380
+ type ListVariantsRequest = {
3381
+ conditions?: Record<string, unknown>
3382
+ search?: string
3383
+ sort?: string
3384
+ from?: number
3385
+ size?: number
3386
+ cursor?: string
3387
+ }
3388
+ ```
3389
+
3390
+ ### `VariantTreeRequest`
3391
+
3392
+ The variants list's request plus `as_of`, the instant each row's version is selected at.
3393
+ `size` is clamped at 100 here; every other property means what it means on the list.
3394
+
3395
+
3396
+ ```ts
3397
+ type VariantTreeRequest = {
3398
+ conditions?: Record<string, unknown>
3399
+ search?: string
3400
+ sort?: string
3401
+ from?: number
3402
+ size?: number
3403
+ cursor?: string
3404
+ as_of?: string
3405
+ }
3406
+ ```
3407
+
3408
+ ### `VariantConditionFilter`
3409
+
3410
+ Which pins a variant must carry to be listed: a flat map keyed by condition name, taking the
3411
+ same exact values and predicates a resolve context does. A condition left out is not
3412
+ filtered on. An `in` list carries at most 50,000 values.
3413
+
3414
+ A variant matches only where it pins the condition — unlike `:re
3415
+
3416
+ ```ts
3417
+ type VariantConditionFilter = Record<string, unknown>
3418
+ ```
3419
+
3420
+ ### `VariantList`
3421
+
3422
+ ```ts
3423
+ type VariantList = {
3424
+ hits: number
3425
+ results: Array<{
3426
+ variant_id: string
3427
+ entity_id: string
3428
+ schema: "product" | "price" | "coupon"
3429
+ conditions: {
3430
+ default: { ... }
3431
+ }
3432
+ }>
3433
+ next?: string
3434
+ }
3435
+ ```
3436
+
3437
+ ### `VariantListRow`
3438
+
3439
+ One variant as a listing reports it: which variant it is and what it pins.
3440
+
3441
+ ```ts
3442
+ type VariantListRow = {
3443
+ variant_id: string
3444
+ entity_id: string
3445
+ schema: "product" | "price" | "coupon"
3446
+ conditions: {
3447
+ default: boolean
3448
+ }
3449
+ }
3450
+ ```
3451
+
3452
+ ### `VariantTree`
3453
+
3454
+ ```ts
3455
+ type VariantTree = {
3456
+ hits: number
3457
+ results: Array<{
3458
+ variant_id: string
3459
+ entity_id: string
3460
+ schema: "product" | "price" | "coupon"
3461
+ conditions: {
3462
+ default: { ... }
3463
+ }
3464
+ status: "active" | "scheduled"
3465
+ version: {
3466
+ variant_id: { ... }
3467
+ entity_id: { ... }
3468
+ schema: { ... }
3469
+ conditions: { ... }
3470
+ valid_from: { ... }
3471
+ values: { ... }
3472
+ _created_at: { ... }
3473
+ _updated_at: { ... }
3474
+ }
3475
+ }>
3476
+ next?: string
3477
+ }
3478
+ ```
3479
+
3480
+ ### `VariantTreeRow`
3481
+
3482
+ A listing row plus the one version the tree shows for it, and the status saying which.
3483
+
3484
+ ```ts
3485
+ type VariantTreeRow = {
3486
+ variant_id: string
3487
+ entity_id: string
3488
+ schema: "product" | "price" | "coupon"
3489
+ conditions: {
3490
+ default: boolean
3491
+ }
3492
+ status: "active" | "scheduled"
3493
+ version: {
3494
+ variant_id: string
3495
+ entity_id: string
3496
+ schema: "product" | "price" | "coupon"
3497
+ conditions: {
3498
+ default: { ... }
3499
+ }
3500
+ valid_from: string
3501
+ values: Record<string, unknown>
3502
+ _created_at: string
3503
+ _updated_at: string
2537
3504
  }
2538
3505
  }
2539
3506
  ```
2540
3507
 
2541
- ### `ResolveContext`
3508
+ ### `VariantTreeRowStatus`
2542
3509
 
2543
- The situation to resolve for: a flat map keyed by condition name, as the entity's schema
2544
- declares them. A condition left out of the map is not a wildcard — it matches only variants
2545
- that leave that condition unpinned.
3510
+ Whether a tree row's version is the one in effect at `as_of`, or one still ahead of it.
3511
+
3512
+ - `active`: the version with the latest `valid_from` at or before `as_of`
3513
+ - `scheduled`: the variant's first version, which is later than `as_of`
2546
3514
 
2547
- Each value is either an exact value, typed by its condition, or a single-operator
2548
3515
 
2549
3516
  ```ts
2550
- type ResolveContext = Record<string, unknown>
3517
+ type VariantTreeRowStatus = "active" | "scheduled"
2551
3518
  ```
2552
3519
 
2553
- ### `ResolveOptions`
3520
+ ### `VariantVersionSnapshot`
3521
+
3522
+ One version of one variant as a listing reports it: `VariantVersion` without `_revision`.
3523
+ Read the version through its own `GET` to get the revision a write must carry.
3524
+
2554
3525
 
2555
3526
  ```ts
2556
- type ResolveOptions = {
2557
- resolve_one?: boolean
3527
+ type VariantVersionSnapshot = {
3528
+ variant_id: string
3529
+ entity_id: string
3530
+ schema: "product" | "price" | "coupon"
3531
+ conditions: {
3532
+ default: boolean
3533
+ }
3534
+ valid_from: string
3535
+ values: Record<string, unknown>
3536
+ _created_at: string
3537
+ _updated_at: string
2558
3538
  }
2559
3539
  ```
2560
3540
 
2561
- ### `ResolvedVariants`
3541
+ ### `VariantVersionList`
2562
3542
 
2563
3543
  ```ts
2564
- type ResolvedVariants = {
3544
+ type VariantVersionList = {
2565
3545
  results: Array<{
2566
- _id: string
2567
- _variant_id: string
2568
- _version_valid_from: string
2569
- _conditions: {
3546
+ variant_id: string
3547
+ entity_id: string
3548
+ schema: "product" | "price" | "coupon"
3549
+ conditions: {
2570
3550
  default: { ... }
2571
3551
  }
3552
+ valid_from: string
3553
+ values: Record<string, unknown>
3554
+ _created_at: string
3555
+ _updated_at: string
2572
3556
  }>
3557
+ next?: string
2573
3558
  }
2574
3559
  ```
2575
3560
 
2576
- ### `ResolvedVariant`
2577
-
2578
- The entity as this variant leaves it — every attribute of a plain entity read, with the
2579
- applicable version's overrides applied — plus the discriminators saying where the numbers
2580
- came from.
3561
+ ### `BatchUpsertVariantsRequest`
2581
3562
 
3563
+ A batch of variant writes under one schema, each item naming the entity it writes to.
2582
3564
 
2583
3565
  ```ts
2584
- type ResolvedVariant = {
2585
- _id: string
2586
- _variant_id: string
2587
- _version_valid_from: string
2588
- _conditions: {
2589
- default: boolean
2590
- }
3566
+ type BatchUpsertVariantsRequest = {
3567
+ correlation_id?: string
3568
+ items: Array<{
3569
+ entity_id: string
3570
+ conditions?: Record<string, unknown>
3571
+ default?: boolean
3572
+ valid_from?: string
3573
+ values: Record<string, unknown>
3574
+ }>
2591
3575
  }
2592
3576
  ```
2593
3577
 
2594
- ### `CreateVariantRequest`
3578
+ ### `BatchUpsertItem`
3579
+
3580
+ One variant write: the single-item create's body plus `entity_id`, and no `variant_id`. An
3581
+ existing condition tuple appends a version to the variant holding it rather than conflicting.
3582
+
2595
3583
 
2596
3584
  ```ts
2597
- type CreateVariantRequest = {
3585
+ type BatchUpsertItem = {
3586
+ entity_id: string
2598
3587
  conditions?: Record<string, unknown>
2599
3588
  default?: boolean
2600
3589
  valid_from?: string
@@ -2602,204 +3591,312 @@ type CreateVariantRequest = {
2602
3591
  }
2603
3592
  ```
2604
3593
 
2605
- ### `VariantConditions`
2606
-
2607
- A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a
2608
- boolean `default` saying whether this is the entity's fallback.
3594
+ ### `BatchDeleteVariantsRequest`
2609
3595
 
2610
- `default` is always present and always a boolean, so a client can branch on "did I get the
2611
- fallback?" without knowing how one is stored. The rese
3596
+ A batch of variant and version deletes under one schema, each item naming the entity it removes from.
2612
3597
 
2613
3598
  ```ts
2614
- type VariantConditions = {
2615
- default: boolean
3599
+ type BatchDeleteVariantsRequest = {
3600
+ correlation_id?: string
3601
+ items: Array<{
3602
+ entity_id: string
3603
+ variant_id: string
3604
+ valid_from?: string
3605
+ } | {
3606
+ entity_id: string
3607
+ conditions?: Record<string, unknown>
3608
+ default?: boolean
3609
+ valid_from?: string
3610
+ }>
2616
3611
  }
2617
3612
  ```
2618
3613
 
2619
- ### `PinnedConditions`
2620
-
2621
- The situation this variant applies to: a flat map keyed by condition name, as the entity's
2622
- schema declares them. A condition left out is a wildcard — the variant applies whatever the
2623
- context says for it, which is what makes adding a condition to a schema non-breaking for the
2624
- variants that already ex
2625
-
2626
- ```ts
2627
- type PinnedConditions = Record<string, unknown>
2628
- ```
2629
-
2630
- ### `VariantValues`
2631
-
2632
- The attribute values this version overrides on the base entity, keyed by attribute name.
2633
-
2634
- Only attributes currently declaring `overridable_attribute` are applied. Metadata fields
2635
- (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable
2636
- attributes present here are ig
3614
+ ### `BatchDeleteItem`
2637
3615
 
2638
- ```ts
2639
- type VariantValues = Record<string, unknown>
2640
- ```
3616
+ One delete: the variant, addressed by id or by the condition tuple it pins, and optionally
3617
+ the one version of it to remove. An item carrying both matches neither branch and is an
3618
+ envelope `400`.
2641
3619
 
2642
- ### `CreatedVariant`
2643
3620
 
2644
3621
  ```ts
2645
- type CreatedVariant = {
3622
+ type BatchDeleteItem = {
3623
+ entity_id: string
2646
3624
  variant_id: string
3625
+ valid_from?: string
3626
+ } | {
2647
3627
  entity_id: string
2648
- schema: "product" | "price" | "coupon"
2649
- conditions: {
2650
- default: boolean
2651
- }
2652
- valid_from: string
2653
- values: Record<string, unknown>
2654
- _created_at: string
2655
- _updated_at: string
2656
- _revision: number
2657
- warnings: Array<{
2658
- code: "VARIANT_COUNT_APPROACHING_CAP"
2659
- message: string
2660
- variant_count: number
2661
- cap: number
2662
- }>
3628
+ conditions?: Record<string, unknown>
3629
+ default?: boolean
3630
+ valid_from?: string
2663
3631
  }
2664
3632
  ```
2665
3633
 
2666
- ### `VariantWriteWarning`
3634
+ ### `BatchDeleteByVariantId`
3635
+
3636
+ A delete addressing its variant by id.
2667
3637
 
2668
3638
  ```ts
2669
- type VariantWriteWarning = {
2670
- code: "VARIANT_COUNT_APPROACHING_CAP"
2671
- message: string
2672
- variant_count: number
2673
- cap: number
3639
+ type BatchDeleteByVariantId = {
3640
+ entity_id: string
3641
+ variant_id: string
3642
+ valid_from?: string
2674
3643
  }
2675
3644
  ```
2676
3645
 
2677
- ### `DeletedVariant`
3646
+ ### `BatchDeleteByConditions`
3647
+
3648
+ A delete addressing its variant by the situation it applies to.
3649
+
3650
+ `conditions` is optional because the fallback variant pins nothing: address it with
3651
+ `default: true` and no `conditions`. An item that ends up addressing no variant at all is a
3652
+ per-item `VARIANT_UNPINNED`, and one marking `default` besi
2678
3653
 
2679
3654
  ```ts
2680
- type DeletedVariant = {
2681
- variant_id: string
3655
+ type BatchDeleteByConditions = {
2682
3656
  entity_id: string
2683
- schema: "product" | "price" | "coupon"
2684
- tuple_released: boolean
2685
- versions_deleted: number
3657
+ conditions?: Record<string, unknown>
3658
+ default?: boolean
3659
+ valid_from?: string
2686
3660
  }
2687
3661
  ```
2688
3662
 
2689
- ### `VariantVersion`
2690
-
2691
- One version of one variant: the attribute overrides it carries, the instant it takes effect,
2692
- and the variant it belongs to.
3663
+ ### `BatchUpsertResult`
2693
3664
 
2694
- These are the version's **own** overrides, not the base entity overlaid with them — this is
2695
- what an editing screen loads and saves, and what it edits is the overrides. Composi
3665
+ What a batch upsert did: one entry per item, in request order, and a count per outcome.
2696
3666
 
2697
3667
  ```ts
2698
- type VariantVersion = {
2699
- variant_id: string
2700
- entity_id: string
2701
- schema: "product" | "price" | "coupon"
2702
- conditions: {
2703
- default: boolean
3668
+ type BatchUpsertResult = {
3669
+ correlation_id?: string
3670
+ counts: {
3671
+ variant_created: number
3672
+ version_created: number
3673
+ updated: number
3674
+ skipped: number
3675
+ error: number
2704
3676
  }
2705
- valid_from: string
2706
- values: Record<string, unknown>
2707
- _created_at: string
2708
- _updated_at: string
2709
- _revision: number
3677
+ results: Array<{
3678
+ outcome: "variant_created" | "version_created" | "updated" | "skipped" | "error"
3679
+ entity_id: string
3680
+ variant_id?: string
3681
+ valid_from?: string
3682
+ warnings: Array<{
3683
+ code: { ... }
3684
+ message: { ... }
3685
+ details: { ... }
3686
+ } | {
3687
+ code: { ... }
3688
+ message: { ... }
3689
+ details: { ... }
3690
+ } | {
3691
+ code: { ... }
3692
+ message: { ... }
3693
+ details: { ... }
3694
+ } | {
3695
+ code: { ... }
3696
+ message: { ... }
3697
+ details: { ... }
3698
+ }>
3699
+ error?: {
3700
+ message: { ... }
3701
+ status?: { ... }
3702
+ cause?: { ... }
3703
+ error?: { ... }
3704
+ }
3705
+ }>
2710
3706
  }
2711
3707
  ```
2712
3708
 
2713
- ### `WrittenVariantVersion`
2714
-
2715
- A version as a write left it, together with anything the write moved.
3709
+ ### `BatchDeleteResult`
2716
3710
 
3711
+ What a batch delete did: one entry per item, in request order, and a count per outcome.
2717
3712
 
2718
3713
  ```ts
2719
- type WrittenVariantVersion = {
2720
- variant_id: string
2721
- entity_id: string
2722
- schema: "product" | "price" | "coupon"
2723
- conditions: {
2724
- default: boolean
3714
+ type BatchDeleteResult = {
3715
+ correlation_id?: string
3716
+ counts: {
3717
+ deleted: number
3718
+ skipped: number
3719
+ error: number
2725
3720
  }
2726
- valid_from: string
2727
- values: Record<string, unknown>
2728
- _created_at: string
2729
- _updated_at: string
2730
- _revision: number
2731
- warnings: Array<{
2732
- code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"
2733
- message: string
2734
- valid_from: string
2735
- active_valid_from?: string
3721
+ results: Array<{
3722
+ outcome: "deleted" | "skipped" | "error"
3723
+ entity_id: string
3724
+ variant_id?: string
3725
+ valid_from?: string
3726
+ warnings: Array<{
3727
+ code: { ... }
3728
+ message: { ... }
3729
+ details: { ... }
3730
+ } | {
3731
+ code: { ... }
3732
+ message: { ... }
3733
+ details: { ... }
3734
+ } | {
3735
+ code: { ... }
3736
+ message: { ... }
3737
+ details: { ... }
3738
+ } | {
3739
+ code: { ... }
3740
+ message: { ... }
3741
+ details: { ... }
3742
+ }>
3743
+ error?: {
3744
+ message: { ... }
3745
+ status?: { ... }
3746
+ cause?: { ... }
3747
+ error?: { ... }
3748
+ }
2736
3749
  }>
2737
3750
  }
2738
3751
  ```
2739
3752
 
2740
- ### `DeletedVariantVersion`
3753
+ ### `BatchUpsertOutcome`
3754
+
3755
+ What one upsert item did, derived from what was stored.
3756
+
3757
+ - `variant_created`: the condition tuple was unknown, so a variant and its first version
3758
+ were created
3759
+ - `version_created`: the tuple was known and had no version at the item's `valid_from`
3760
+ - `updated`: a version existed at that exact instant
2741
3761
 
2742
3762
  ```ts
2743
- type DeletedVariantVersion = {
2744
- variant_id: string
2745
- entity_id: string
2746
- schema: "product" | "price" | "coupon"
2747
- valid_from: string
2748
- warnings: Array<{
2749
- code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"
2750
- message: string
2751
- valid_from: string
2752
- active_valid_from?: string
2753
- }>
2754
- }
3763
+ type BatchUpsertOutcome = "variant_created" | "version_created" | "updated" | "skipped" | "error"
2755
3764
  ```
2756
3765
 
2757
- ### `VersionWriteWarning`
3766
+ ### `BatchDeleteOutcome`
3767
+
3768
+ What one delete item did.
2758
3769
 
2759
- Something a version write moved. A version write is never refused for being late — backdating a
2760
- version, and editing or deleting one that has already been superseded, are both accepted — so
2761
- what a caller gets instead is a warning naming exactly what changed. One write can carry both
2762
- codes.
3770
+ - `deleted`: the variant, or the one version the item named, is gone
3771
+ - `skipped`: the item addressed no such variant or version; a missing entity is an `error`
3772
+ - `error`: this item alone failed, and the entry's `error` says why
2763
3773
 
2764
3774
 
2765
3775
  ```ts
2766
- type VersionWriteWarning = {
2767
- code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"
2768
- message: string
2769
- valid_from: string
2770
- active_valid_from?: string
3776
+ type BatchDeleteOutcome = "deleted" | "skipped" | "error"
3777
+ ```
3778
+
3779
+ ### `BatchUpsertCounts`
3780
+
3781
+ How many items reached each outcome. Keyed by exactly the values of `BatchUpsertOutcome`,
3782
+ all present, and summing to the length of `results`.
3783
+
3784
+
3785
+ ```ts
3786
+ type BatchUpsertCounts = {
3787
+ variant_created: number
3788
+ version_created: number
3789
+ updated: number
3790
+ skipped: number
3791
+ error: number
2771
3792
  }
2772
3793
  ```
2773
3794
 
2774
- ### `AppendVersionRequest`
3795
+ ### `BatchDeleteCounts`
3796
+
3797
+ How many items reached each outcome. Keyed by exactly the values of `BatchDeleteOutcome`,
3798
+ all present, and summing to the length of `results`.
3799
+
2775
3800
 
2776
3801
  ```ts
2777
- type AppendVersionRequest = {
2778
- valid_from?: string
2779
- values: Record<string, unknown>
2780
- conditions?: Record<string, unknown>
3802
+ type BatchDeleteCounts = {
3803
+ deleted: number
3804
+ skipped: number
3805
+ error: number
2781
3806
  }
2782
3807
  ```
2783
3808
 
2784
- ### `ReplaceVersionRequest`
3809
+ ### `BatchUpsertResultEntry`
3810
+
3811
+ What one upsert item did. Position in `results` maps it back to its source row.
2785
3812
 
2786
3813
  ```ts
2787
- type ReplaceVersionRequest = {
2788
- values: Record<string, unknown>
2789
- _revision: number
3814
+ type BatchUpsertResultEntry = {
3815
+ outcome: "variant_created" | "version_created" | "updated" | "skipped" | "error"
3816
+ entity_id: string
3817
+ variant_id?: string
2790
3818
  valid_from?: string
2791
- conditions?: Record<string, unknown>
3819
+ warnings: Array<{
3820
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3821
+ message: string
3822
+ details: {
3823
+ variant_count: { ... }
3824
+ cap: { ... }
3825
+ }
3826
+ } | {
3827
+ code: "ACTIVE_VERSION_CHANGED"
3828
+ message: string
3829
+ details: {
3830
+ valid_from: { ... }
3831
+ active_valid_from?: { ... }
3832
+ }
3833
+ } | {
3834
+ code: "SUPERSEDED_VERSION_WRITTEN"
3835
+ message: string
3836
+ details: {
3837
+ valid_from: { ... }
3838
+ active_valid_from?: { ... }
3839
+ }
3840
+ } | {
3841
+ code: "ATTRIBUTES_NOT_APPLIED"
3842
+ message: string
3843
+ details: {
3844
+ attributes: { ... }
3845
+ }
3846
+ }>
3847
+ error?: {
3848
+ message: string
3849
+ status?: number
3850
+ cause?: string
3851
+ error?: string | Record<string, unknown>[]
3852
+ }
2792
3853
  }
2793
3854
  ```
2794
3855
 
2795
- ### `PatchVersionRequest`
3856
+ ### `BatchDeleteResultEntry`
3857
+
3858
+ What one delete item did. Position in `results` maps it back to its source row.
2796
3859
 
2797
3860
  ```ts
2798
- type PatchVersionRequest = {
2799
- values: Record<string, unknown>
2800
- _revision: number
3861
+ type BatchDeleteResultEntry = {
3862
+ outcome: "deleted" | "skipped" | "error"
3863
+ entity_id: string
3864
+ variant_id?: string
2801
3865
  valid_from?: string
2802
- conditions?: Record<string, unknown>
3866
+ warnings: Array<{
3867
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3868
+ message: string
3869
+ details: {
3870
+ variant_count: { ... }
3871
+ cap: { ... }
3872
+ }
3873
+ } | {
3874
+ code: "ACTIVE_VERSION_CHANGED"
3875
+ message: string
3876
+ details: {
3877
+ valid_from: { ... }
3878
+ active_valid_from?: { ... }
3879
+ }
3880
+ } | {
3881
+ code: "SUPERSEDED_VERSION_WRITTEN"
3882
+ message: string
3883
+ details: {
3884
+ valid_from: { ... }
3885
+ active_valid_from?: { ... }
3886
+ }
3887
+ } | {
3888
+ code: "ATTRIBUTES_NOT_APPLIED"
3889
+ message: string
3890
+ details: {
3891
+ attributes: { ... }
3892
+ }
3893
+ }>
3894
+ error?: {
3895
+ message: string
3896
+ status?: number
3897
+ cause?: string
3898
+ error?: string | Record<string, unknown>[]
3899
+ }
2803
3900
  }
2804
3901
  ```
2805
3902
 
@@ -2813,21 +3910,30 @@ type Error = {
2813
3910
  }
2814
3911
  ```
2815
3912
 
3913
+ ### `ReportedError`
3914
+
3915
+ The `error` field of an error response: the message, or — where the request failed
3916
+ validation before any handler ran — the validation errors themselves.
3917
+
3918
+
3919
+ ```ts
3920
+ type ReportedError = string | Record<string, unknown>[]
3921
+ ```
3922
+
2816
3923
  ### `ConditionalPricingError`
2817
3924
 
2818
- An error from a conditional-pricing operation, carrying a machine-readable `code`
2819
- from the conditional-pricing vocabulary plus any structured data about the failure,
2820
- so a client can branch on the kind of failure rather than parse the message.
2821
- Referenced only by the operations that emit these codes;
3925
+ An error from a conditional-pricing operation, carrying a `code` plus the structured data
3926
+ that code explains. `details` is typed per code: narrow on `code` and the object under it
3927
+ declares exactly the fields that code sends.
3928
+
3929
+ A request these schemas reject is answered by the request validator with a
2822
3930
 
2823
3931
  ```ts
2824
3932
  type ConditionalPricingError = {
2825
3933
  message: string
2826
3934
  status?: number
2827
3935
  cause?: string
2828
- error?: string
2829
- code?: "NOT_FOUND" | "AMBIGUOUS_RESOLUTION" | "TUPLE_CONFLICT" | "VERSION_CONFLICT" | "CONDITION_UNDEFINED" | "OPERATOR_UNSUPPORTED" | "CONTEXT_FORMAT_INVALID" | "CONDITION_VALUE_INVALID" | "TOO_MANY_MATCHES" | "WRITE_CONFLICT"
2830
- details?: Record<string, unknown>
3936
+ error?: string | Record<string, unknown>[]
2831
3937
  }
2832
3938
  ```
2833
3939
 
@@ -2902,6 +4008,7 @@ type Product = {
2902
4008
  _tags?: { ... }
2903
4009
  }>
2904
4010
  }
4011
+ is_conditional?: boolean
2905
4012
  _availability_files?: Array<{
2906
4013
  _id: string
2907
4014
  filename: string
@@ -3095,6 +4202,7 @@ type Order = {
3095
4202
  product_images?: { ... }
3096
4203
  product_downloads?: { ... }
3097
4204
  price_options?: { ... }
4205
+ is_conditional?: { ... }
3098
4206
  _availability_files?: { ... }
3099
4207
  _id?: { ... }
3100
4208
  _title?: { ... }
@@ -3105,7 +4213,6 @@ type Order = {
3105
4213
  } | {
3106
4214
  metadata?: Array<{
3107
4215
  key?: { ... }
3108
- value?: { ... }
3109
4216
  // ...
3110
4217
  }
3111
4218
  ```
@@ -3488,6 +4595,7 @@ type CatalogSearchResult = {
3488
4595
  price_options?: {
3489
4596
  $relation?: { ... }
3490
4597
  }
4598
+ is_conditional?: boolean
3491
4599
  _availability_files?: Array<{
3492
4600
  _id: { ... }
3493
4601
  filename: { ... }
@@ -3532,6 +4640,7 @@ type CatalogSearchResult = {
3532
4640
  fixed_value_currency?: string
3533
4641
  cashback_period?: "0" | "12"
3534
4642
  active?: boolean
4643
+ is_conditional?: boolean
3535
4644
  requires_promo_code?: boolean
3536
4645
  }>
3537
4646
  }
@@ -4694,6 +5803,7 @@ type BasePriceItemCommon = {
4694
5803
  price_options?: {
4695
5804
  $relation?: { ... }
4696
5805
  }
5806
+ is_conditional?: boolean
4697
5807
  _availability_files?: Array<{
4698
5808
  _id: { ... }
4699
5809
  filename: { ... }
@@ -4999,6 +6109,7 @@ type BasePriceItemDto = {
4999
6109
  price_options?: {
5000
6110
  $relation?: { ... }
5001
6111
  }
6112
+ is_conditional?: boolean
5002
6113
  _availability_files?: Array<{
5003
6114
  _id: { ... }
5004
6115
  filename: { ... }
@@ -5433,13 +6544,13 @@ type OrderPayload = {
5433
6544
  fixed_value_currency?: { ... }
5434
6545
  cashback_period?: { ... }
5435
6546
  active?: { ... }
6547
+ is_conditional?: { ... }
5436
6548
  requires_promo_code?: { ... }
5437
6549
  }>
5438
6550
  type?: "one_time" | "recurring"
5439
6551
  billing_period?: "weekly" | "monthly" | "every_quarter" | "every_6_months" | "yearly"
5440
6552
  unit_amount?: number
5441
6553
  unit_amount_gross?: number
5442
- unit_amount_currency?: string
5443
6554
  // ...
5444
6555
  }
5445
6556
  ```
@@ -5512,6 +6623,7 @@ type PriceItems = Array<{
5512
6623
  price_options?: {
5513
6624
  $relation?: { ... }
5514
6625
  }
6626
+ is_conditional?: boolean
5515
6627
  _availability_files?: Array<{
5516
6628
  _id: { ... }
5517
6629
  filename: { ... }
@@ -5548,7 +6660,6 @@ type PriceItems = Array<{
5548
6660
  value?: number
5549
6661
  metadata?: Record<string, string>
5550
6662
  }>
5551
- is_tax_inclusive?: boolean
5552
6663
  // ...
5553
6664
  }
5554
6665
  ```
@@ -5621,6 +6732,7 @@ type CompositePriceItem = {
5621
6732
  price_options?: {
5622
6733
  $relation?: { ... }
5623
6734
  }
6735
+ is_conditional?: boolean
5624
6736
  _availability_files?: Array<{
5625
6737
  _id: { ... }
5626
6738
  filename: { ... }
@@ -5710,6 +6822,7 @@ type BasePriceItem = {
5710
6822
  price_options?: {
5711
6823
  $relation?: { ... }
5712
6824
  }
6825
+ is_conditional?: boolean
5713
6826
  _availability_files?: Array<{
5714
6827
  _id: { ... }
5715
6828
  filename: { ... }
@@ -5859,6 +6972,7 @@ type PriceItem = {
5859
6972
  price_options?: {
5860
6973
  $relation?: { ... }
5861
6974
  }
6975
+ is_conditional?: boolean
5862
6976
  _availability_files?: Array<{
5863
6977
  _id: { ... }
5864
6978
  filename: { ... }
@@ -6075,6 +7189,7 @@ type PricingDetails = {
6075
7189
  product_images?: { ... }
6076
7190
  product_downloads?: { ... }
6077
7191
  price_options?: { ... }
7192
+ is_conditional?: { ... }
6078
7193
  _availability_files?: { ... }
6079
7194
  _id?: { ... }
6080
7195
  _title?: { ... }
@@ -6112,6 +7227,7 @@ type PricingDetails = {
6112
7227
  product_images?: { ... }
6113
7228
  product_downloads?: { ... }
6114
7229
  price_options?: { ... }
7230
+ is_conditional?: { ... }
6115
7231
  _availability_files?: { ... }
6116
7232
  _id?: { ... }
6117
7233
  _title?: { ... }
@@ -6142,8 +7258,6 @@ type PricingDetails = {
6142
7258
  _id: { ... }
6143
7259
  _title: { ... }
6144
7260
  _org: { ... }
6145
- _schema: { ... }
6146
- _tags?: { ... }
6147
7261
  // ...
6148
7262
  }
6149
7263
  ```
@@ -6172,6 +7286,7 @@ type PromoCodeValidationResponse = {
6172
7286
  fixed_value_currency?: string
6173
7287
  cashback_period?: "0" | "12"
6174
7288
  active?: boolean
7289
+ is_conditional?: boolean
6175
7290
  requires_promo_code?: boolean
6176
7291
  }>
6177
7292
  }
@@ -6213,6 +7328,7 @@ type PricingDetailsResponse = {
6213
7328
  product_images?: { ... }
6214
7329
  product_downloads?: { ... }
6215
7330
  price_options?: { ... }
7331
+ is_conditional?: { ... }
6216
7332
  _availability_files?: { ... }
6217
7333
  _id?: { ... }
6218
7334
  _title?: { ... }
@@ -6250,6 +7366,7 @@ type PricingDetailsResponse = {
6250
7366
  product_images?: { ... }
6251
7367
  product_downloads?: { ... }
6252
7368
  price_options?: { ... }
7369
+ is_conditional?: { ... }
6253
7370
  _availability_files?: { ... }
6254
7371
  _id?: { ... }
6255
7372
  _title?: { ... }
@@ -6280,8 +7397,6 @@ type PricingDetailsResponse = {
6280
7397
  _id: { ... }
6281
7398
  _title: { ... }
6282
7399
  _org: { ... }
6283
- _schema: { ... }
6284
- _tags?: { ... }
6285
7400
  // ...
6286
7401
  }
6287
7402
  ```
@@ -6504,6 +7619,7 @@ type BaseCouponCommon = {
6504
7619
  fixed_value_currency?: string
6505
7620
  cashback_period?: "0" | "12"
6506
7621
  active?: boolean
7622
+ is_conditional?: boolean
6507
7623
  requires_promo_code?: boolean
6508
7624
  }
6509
7625
  ```
@@ -6531,6 +7647,7 @@ type CouponWithoutPromoCodes = {
6531
7647
  fixed_value_currency?: string
6532
7648
  cashback_period?: "0" | "12"
6533
7649
  active?: boolean
7650
+ is_conditional?: boolean
6534
7651
  requires_promo_code?: boolean
6535
7652
  }
6536
7653
  ```
@@ -6558,6 +7675,7 @@ type Coupon = {
6558
7675
  fixed_value_currency?: string
6559
7676
  cashback_period?: "0" | "12"
6560
7677
  active?: boolean
7678
+ is_conditional?: boolean
6561
7679
  requires_promo_code?: boolean
6562
7680
  }
6563
7681
  ```
@@ -6583,6 +7701,7 @@ type CouponItem = {
6583
7701
  fixed_value_currency?: string
6584
7702
  cashback_period?: "0" | "12"
6585
7703
  active?: boolean
7704
+ is_conditional?: boolean
6586
7705
  requires_promo_code?: boolean
6587
7706
  }
6588
7707
  ```
@@ -6621,6 +7740,7 @@ type RedeemedPromo = {
6621
7740
  fixed_value_currency?: string
6622
7741
  cashback_period?: "0" | "12"
6623
7742
  active?: boolean
7743
+ is_conditional?: boolean
6624
7744
  requires_promo_code?: boolean
6625
7745
  }>
6626
7746
  }