@epilot/sdk 2.20.8-alpha.0 → 2.20.9

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 (148) hide show
  1. package/definitions/environments.json +3 -211
  2. package/definitions/pricing-runtime.json +1 -1
  3. package/definitions/pricing.json +3489 -757
  4. package/definitions/validation-rules.json +184 -6
  5. package/dist/apis/access-token.cjs +6 -6
  6. package/dist/apis/access-token.js +1 -1
  7. package/dist/apis/address-suggestions.cjs +6 -6
  8. package/dist/apis/address-suggestions.js +1 -1
  9. package/dist/apis/address.cjs +6 -6
  10. package/dist/apis/address.js +1 -1
  11. package/dist/apis/ai-agents.cjs +6 -6
  12. package/dist/apis/ai-agents.js +1 -1
  13. package/dist/apis/app.cjs +6 -6
  14. package/dist/apis/app.js +1 -1
  15. package/dist/apis/audit-logs.cjs +6 -6
  16. package/dist/apis/audit-logs.js +1 -1
  17. package/dist/apis/automation.cjs +6 -6
  18. package/dist/apis/automation.js +1 -1
  19. package/dist/apis/billing.cjs +6 -6
  20. package/dist/apis/billing.js +1 -1
  21. package/dist/apis/blueprint-manifest.cjs +6 -6
  22. package/dist/apis/blueprint-manifest.js +1 -1
  23. package/dist/apis/calendar.cjs +6 -6
  24. package/dist/apis/calendar.js +1 -1
  25. package/dist/apis/configuration-hub.cjs +6 -6
  26. package/dist/apis/configuration-hub.js +1 -1
  27. package/dist/apis/consent.cjs +6 -6
  28. package/dist/apis/consent.js +1 -1
  29. package/dist/apis/customer-portal.cjs +6 -6
  30. package/dist/apis/customer-portal.js +1 -1
  31. package/dist/apis/dashboard.cjs +6 -6
  32. package/dist/apis/dashboard.js +1 -1
  33. package/dist/apis/data-governance.cjs +6 -6
  34. package/dist/apis/data-governance.js +1 -1
  35. package/dist/apis/deduplication.cjs +6 -6
  36. package/dist/apis/deduplication.js +1 -1
  37. package/dist/apis/design.cjs +6 -6
  38. package/dist/apis/design.js +1 -1
  39. package/dist/apis/document.cjs +6 -6
  40. package/dist/apis/document.js +1 -1
  41. package/dist/apis/email-settings.cjs +6 -6
  42. package/dist/apis/email-settings.js +1 -1
  43. package/dist/apis/email-template.cjs +6 -6
  44. package/dist/apis/email-template.js +1 -1
  45. package/dist/apis/entity-mapping.cjs +6 -6
  46. package/dist/apis/entity-mapping.js +1 -1
  47. package/dist/apis/entity.cjs +6 -6
  48. package/dist/apis/entity.js +1 -1
  49. package/dist/apis/environments.cjs +6 -6
  50. package/dist/apis/environments.d.cts +2 -2
  51. package/dist/apis/environments.d.ts +2 -2
  52. package/dist/apis/environments.js +1 -1
  53. package/dist/apis/event-catalog.cjs +6 -6
  54. package/dist/apis/event-catalog.js +1 -1
  55. package/dist/apis/file.cjs +6 -6
  56. package/dist/apis/file.js +1 -1
  57. package/dist/apis/iban.cjs +6 -6
  58. package/dist/apis/iban.js +1 -1
  59. package/dist/apis/integration-toolkit.cjs +6 -6
  60. package/dist/apis/integration-toolkit.js +1 -1
  61. package/dist/apis/journey.cjs +6 -6
  62. package/dist/apis/journey.js +1 -1
  63. package/dist/apis/kanban.cjs +6 -6
  64. package/dist/apis/kanban.js +1 -1
  65. package/dist/apis/message.cjs +6 -6
  66. package/dist/apis/message.js +1 -1
  67. package/dist/apis/metering.cjs +6 -6
  68. package/dist/apis/metering.js +1 -1
  69. package/dist/apis/notes.cjs +6 -6
  70. package/dist/apis/notes.js +1 -1
  71. package/dist/apis/notification.cjs +6 -6
  72. package/dist/apis/notification.js +1 -1
  73. package/dist/apis/organization.cjs +6 -6
  74. package/dist/apis/organization.js +1 -1
  75. package/dist/apis/partner-directory.cjs +6 -6
  76. package/dist/apis/partner-directory.js +1 -1
  77. package/dist/apis/permissions.cjs +6 -6
  78. package/dist/apis/permissions.js +1 -1
  79. package/dist/apis/pricing-tier.cjs +6 -6
  80. package/dist/apis/pricing-tier.js +1 -1
  81. package/dist/apis/pricing.cjs +8 -8
  82. package/dist/apis/pricing.d.cts +2 -2
  83. package/dist/apis/pricing.d.ts +2 -2
  84. package/dist/apis/pricing.js +2 -2
  85. package/dist/apis/purpose.cjs +6 -6
  86. package/dist/apis/purpose.js +1 -1
  87. package/dist/apis/query.cjs +6 -6
  88. package/dist/apis/query.js +1 -1
  89. package/dist/apis/sandbox.cjs +6 -6
  90. package/dist/apis/sandbox.js +1 -1
  91. package/dist/apis/sharing.cjs +6 -6
  92. package/dist/apis/sharing.js +1 -1
  93. package/dist/apis/snapshot.cjs +6 -6
  94. package/dist/apis/snapshot.js +1 -1
  95. package/dist/apis/submission.cjs +6 -6
  96. package/dist/apis/submission.js +1 -1
  97. package/dist/apis/target.cjs +6 -6
  98. package/dist/apis/target.js +1 -1
  99. package/dist/apis/targeting.cjs +6 -6
  100. package/dist/apis/targeting.js +1 -1
  101. package/dist/apis/template-variables.cjs +6 -6
  102. package/dist/apis/template-variables.js +1 -1
  103. package/dist/apis/user.cjs +6 -6
  104. package/dist/apis/user.js +1 -1
  105. package/dist/apis/validation-rules.cjs +6 -6
  106. package/dist/apis/validation-rules.d.cts +2 -2
  107. package/dist/apis/validation-rules.d.ts +2 -2
  108. package/dist/apis/validation-rules.js +1 -1
  109. package/dist/apis/webhooks.cjs +6 -6
  110. package/dist/apis/webhooks.js +1 -1
  111. package/dist/apis/workflow-definition.cjs +6 -6
  112. package/dist/apis/workflow-definition.js +1 -1
  113. package/dist/apis/workflow.cjs +6 -6
  114. package/dist/apis/workflow.js +1 -1
  115. package/dist/bin/cli.js +1 -1
  116. package/dist/{chunk-OHYTCUUB.js → chunk-7Q3JW72Y.js} +1 -1
  117. package/dist/{chunk-PFO4HNPR.js → chunk-JBFTKLP2.js} +4 -4
  118. package/dist/{chunk-UKHR33EL.cjs → chunk-QLWDOKGE.cjs} +1 -1
  119. package/dist/{chunk-4FP7EKQT.cjs → chunk-VCD3C4UW.cjs} +4 -4
  120. package/dist/environments-EAVUY4FC.cjs +7 -0
  121. package/dist/environments-RNOROUFZ.js +7 -0
  122. package/dist/{environments.d-Cr-oj1fN.d.cts → environments.d-C_BTxz4W.d.cts} +22 -193
  123. package/dist/{environments.d-Cr-oj1fN.d.ts → environments.d-C_BTxz4W.d.ts} +22 -193
  124. package/dist/index.cjs +10 -10
  125. package/dist/index.d.cts +3 -3
  126. package/dist/index.d.ts +3 -3
  127. package/dist/index.js +2 -2
  128. package/dist/{js-yaml-UPZKYVRY.js → js-yaml-DLCVPJ7G.js} +17 -15
  129. package/dist/pricing-PFTFDGZ3.cjs +7 -0
  130. package/dist/pricing-YZHONV3M.js +7 -0
  131. package/dist/{pricing-runtime-AT27C3BP.js → pricing-runtime-MJAIO4AY.js} +1 -1
  132. package/dist/{pricing-runtime-PFVTRERK.cjs → pricing-runtime-NMRZO6J4.cjs} +2 -2
  133. package/dist/{pricing.d-CSVO1WCD.d.cts → pricing.d-CvcYBm8A.d.cts} +9979 -1422
  134. package/dist/{pricing.d-CSVO1WCD.d.ts → pricing.d-CvcYBm8A.d.ts} +9979 -1422
  135. package/dist/validation-rules-2JQLB6PH.cjs +7 -0
  136. package/dist/validation-rules-VQXUQSMC.js +7 -0
  137. package/dist/{validation-rules.d-D8X9MYTc.d.ts → validation-rules.d-Bbo90IYn.d.cts} +178 -7
  138. package/dist/{validation-rules.d-D8X9MYTc.d.cts → validation-rules.d-Bbo90IYn.d.ts} +178 -7
  139. package/docs/environments.md +11 -252
  140. package/docs/pricing.md +1372 -204
  141. package/docs/validation-rules.md +286 -0
  142. package/package.json +1 -1
  143. package/dist/environments-DBHM4GKI.cjs +0 -7
  144. package/dist/environments-JVPK6LSD.js +0 -7
  145. package/dist/pricing-5EKKEZSL.js +0 -7
  146. package/dist/pricing-N4Z2CHGZ.cjs +0 -7
  147. package/dist/validation-rules-ETOO45CW.js +0 -7
  148. package/dist/validation-rules-MZZ7YMJM.cjs +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)
@@ -1841,11 +1876,17 @@ const { data } = await client.$getConditionSets({
1841
1876
  "description": "string",
1842
1877
  "conditions": [
1843
1878
  {
1879
+ "id": "d5839b94-ba20-4225-a78e-76951d352bd6",
1844
1880
  "name": "postal_code",
1845
1881
  "label": "Postal Code",
1846
1882
  "type": "string",
1847
- "options": ["private", "commercial"],
1848
- "allow_any": false,
1883
+ "options": [
1884
+ "private",
1885
+ {
1886
+ "value": "commercial",
1887
+ "title": "Commercial customers"
1888
+ }
1889
+ ],
1849
1890
  "format": "zipcode"
1850
1891
  }
1851
1892
  ]
@@ -1860,8 +1901,8 @@ const { data } = await client.$getConditionSets({
1860
1901
 
1861
1902
  ### `$resolveConditionalEntity`
1862
1903
 
1863
- Resolves which of a conditional entity's variants apply to a situation, and returns each one
1864
- composed: the base entity overlaid with the values of the version in effect at `as_of`.
1904
+ Resolves which of a conditional entity's variants apply, and returns each one composed: the
1905
+ base entity overlaid with the values of the version in effect at `as_of`.
1865
1906
 
1866
1907
  `POST /v1/conditional-pricing:resolve`
1867
1908
 
@@ -1879,7 +1920,8 @@ const { data } = await client.$resolveConditionalEntity(
1879
1920
  },
1880
1921
  as_of: '2027-03-15T00:00:00Z',
1881
1922
  options: {
1882
- resolve_one: false
1923
+ resolve_one: false,
1924
+ hydrate: false
1883
1925
  }
1884
1926
  },
1885
1927
  )
@@ -1898,7 +1940,13 @@ const { data } = await client.$resolveConditionalEntity(
1898
1940
  "_conditions": {
1899
1941
  "postal_code": "46045",
1900
1942
  "default": false
1901
- }
1943
+ },
1944
+ "_inert_overrides": [
1945
+ {
1946
+ "attribute": "unit_amount",
1947
+ "reason": "ATTRIBUTE_NOT_OVERRIDABLE"
1948
+ }
1949
+ ]
1902
1950
  }
1903
1951
  ]
1904
1952
  }
@@ -1911,8 +1959,7 @@ const { data } = await client.$resolveConditionalEntity(
1911
1959
  ### `$createConditionalVariant`
1912
1960
 
1913
1961
  Creates one variant of a conditional entity, together with the first version carrying its
1914
- values. Never two calls: a variant that existed without a version would be an entity holding
1915
- a condition tuple
1962
+ values: a variant always has at least one version.
1916
1963
 
1917
1964
  `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants`
1918
1965
 
@@ -1960,8 +2007,10 @@ const { data } = await client.$createConditionalVariant(
1960
2007
  {
1961
2008
  "code": "VARIANT_COUNT_APPROACHING_CAP",
1962
2009
  "message": "string",
1963
- "variant_count": 0,
1964
- "cap": 0
2010
+ "details": {
2011
+ "variant_count": 0,
2012
+ "cap": 0
2013
+ }
1965
2014
  }
1966
2015
  ]
1967
2016
  }
@@ -1971,6 +2020,132 @@ const { data } = await client.$createConditionalVariant(
1971
2020
 
1972
2021
  ---
1973
2022
 
2023
+ ### `$listConditionalVariants`
2024
+
2025
+ Lists a conditional entity's variants and the conditions each one pins — the browse, filter
2026
+ and search read behind the Entity UI's variant screens.
2027
+
2028
+ `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants:list`
2029
+
2030
+ ```ts
2031
+ const { data } = await client.$listConditionalVariants(
2032
+ {
2033
+ slug: 'example',
2034
+ entity_id: 'example',
2035
+ },
2036
+ {
2037
+ conditions: {
2038
+ postal_code: '46045',
2039
+ consumption: {
2040
+ lt: 5000
2041
+ }
2042
+ },
2043
+ search: '460',
2044
+ sort: 'conditions.postal_code:asc',
2045
+ from: 0,
2046
+ size: 10,
2047
+ cursor: 'eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0'
2048
+ },
2049
+ )
2050
+ ```
2051
+
2052
+ <details>
2053
+ <summary>Response</summary>
2054
+
2055
+ ```json
2056
+ {
2057
+ "hits": 8128,
2058
+ "results": [
2059
+ {
2060
+ "variant_id": "var-46045",
2061
+ "entity_id": "price-sp26d1yo",
2062
+ "schema": "product",
2063
+ "conditions": {
2064
+ "postal_code": "46045",
2065
+ "default": false
2066
+ }
2067
+ }
2068
+ ],
2069
+ "next": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0"
2070
+ }
2071
+ ```
2072
+
2073
+ </details>
2074
+
2075
+ ---
2076
+
2077
+ ### `$getConditionalVariantTree`
2078
+
2079
+ The variants list, each row carrying the version in effect at `as_of` — the Entity UI's main
2080
+ editing screen in one call rather than one call per row.
2081
+
2082
+ `POST /v1/conditional-pricing/{slug}/entities/{entity_id}/variants:tree`
2083
+
2084
+ ```ts
2085
+ const { data } = await client.$getConditionalVariantTree(
2086
+ {
2087
+ slug: 'example',
2088
+ entity_id: 'example',
2089
+ },
2090
+ {
2091
+ conditions: {
2092
+ postal_code: '46045',
2093
+ consumption: {
2094
+ lt: 5000
2095
+ }
2096
+ },
2097
+ search: '460',
2098
+ sort: 'conditions.postal_code:asc',
2099
+ from: 0,
2100
+ size: 10,
2101
+ cursor: 'eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0',
2102
+ as_of: '2027-03-15T00:00:00Z'
2103
+ },
2104
+ )
2105
+ ```
2106
+
2107
+ <details>
2108
+ <summary>Response</summary>
2109
+
2110
+ ```json
2111
+ {
2112
+ "hits": 8128,
2113
+ "results": [
2114
+ {
2115
+ "variant_id": "var-46045",
2116
+ "entity_id": "price-sp26d1yo",
2117
+ "schema": "product",
2118
+ "conditions": {
2119
+ "postal_code": "46045",
2120
+ "default": false
2121
+ },
2122
+ "status": "active",
2123
+ "version": {
2124
+ "variant_id": "var-46045",
2125
+ "entity_id": "price-sp26d1yo",
2126
+ "schema": "product",
2127
+ "conditions": {
2128
+ "postal_code": "46045",
2129
+ "default": false
2130
+ },
2131
+ "valid_from": "2027-01-01T00:00:00.000Z",
2132
+ "values": {
2133
+ "unit_amount": 2499,
2134
+ "unit_amount_decimal": "24.99"
2135
+ },
2136
+ "_created_at": "string",
2137
+ "_updated_at": "string"
2138
+ }
2139
+ }
2140
+ ],
2141
+ "next": "eyJmcm9tIjoyNSwibGlzdGluZyI6IjNmOWMxZTJhIn0"
2142
+ }
2143
+ ```
2144
+
2145
+ </details>
2146
+
2147
+ ---
2148
+
1974
2149
  ### `$getActiveConditionalVariantVersion`
1975
2150
 
1976
2151
  Returns the version of this variant that is currently in effect — the one with the latest
@@ -2062,10 +2237,12 @@ const { data } = await client.$replaceActiveConditionalVariantVersion(
2062
2237
  "_revision": 3,
2063
2238
  "warnings": [
2064
2239
  {
2065
- "code": "ACTIVE_VERSION_REPLACED",
2240
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2066
2241
  "message": "string",
2067
- "valid_from": "2026-08-01T00:00:00.000Z",
2068
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2242
+ "details": {
2243
+ "variant_count": 0,
2244
+ "cap": 0
2245
+ }
2069
2246
  }
2070
2247
  ]
2071
2248
  }
@@ -2124,10 +2301,12 @@ const { data } = await client.$patchActiveConditionalVariantVersion(
2124
2301
  "_revision": 3,
2125
2302
  "warnings": [
2126
2303
  {
2127
- "code": "ACTIVE_VERSION_REPLACED",
2304
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2128
2305
  "message": "string",
2129
- "valid_from": "2026-08-01T00:00:00.000Z",
2130
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2306
+ "details": {
2307
+ "variant_count": 0,
2308
+ "cap": 0
2309
+ }
2131
2310
  }
2132
2311
  ]
2133
2312
  }
@@ -2169,6 +2348,55 @@ const { data } = await client.$deleteConditionalVariant({
2169
2348
 
2170
2349
  ---
2171
2350
 
2351
+ ### `$listConditionalVariantVersions`
2352
+
2353
+ Lists one variant's versions — its whole timeline, oldest first, which is what expanding a row
2354
+ of the tree loads.
2355
+
2356
+ `GET /v1/conditional-pricing/{slug}/entities/{entity_id}/variants/{variant_id}/versions`
2357
+
2358
+ ```ts
2359
+ const { data } = await client.$listConditionalVariantVersions({
2360
+ slug: 'example',
2361
+ entity_id: 'example',
2362
+ variant_id: 'example',
2363
+ limit: 1,
2364
+ order: 'example',
2365
+ cursor: 'example',
2366
+ })
2367
+ ```
2368
+
2369
+ <details>
2370
+ <summary>Response</summary>
2371
+
2372
+ ```json
2373
+ {
2374
+ "results": [
2375
+ {
2376
+ "variant_id": "var-46045",
2377
+ "entity_id": "price-sp26d1yo",
2378
+ "schema": "product",
2379
+ "conditions": {
2380
+ "postal_code": "46045",
2381
+ "default": false
2382
+ },
2383
+ "valid_from": "2027-01-01T00:00:00.000Z",
2384
+ "values": {
2385
+ "unit_amount": 2499,
2386
+ "unit_amount_decimal": "24.99"
2387
+ },
2388
+ "_created_at": "string",
2389
+ "_updated_at": "string"
2390
+ }
2391
+ ],
2392
+ "next": "eyJzayI6IlYjcHJpY2Utc3AyNmQxeW8jdmFyLTQ2MDQ1IzIwMjYtMDEtMDFUMDA6MDA6MDAuMDAwWiIsIm9yZGVyIjoiYXNjIn0"
2393
+ }
2394
+ ```
2395
+
2396
+ </details>
2397
+
2398
+ ---
2399
+
2172
2400
  ### `$appendConditionalVariantVersion`
2173
2401
 
2174
2402
  Appends a version to a variant: a new set of values taking effect at its own instant.
@@ -2217,10 +2445,12 @@ const { data } = await client.$appendConditionalVariantVersion(
2217
2445
  "_revision": 3,
2218
2446
  "warnings": [
2219
2447
  {
2220
- "code": "ACTIVE_VERSION_REPLACED",
2448
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2221
2449
  "message": "string",
2222
- "valid_from": "2026-08-01T00:00:00.000Z",
2223
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2450
+ "details": {
2451
+ "variant_count": 0,
2452
+ "cap": 0
2453
+ }
2224
2454
  }
2225
2455
  ]
2226
2456
  }
@@ -2323,10 +2553,12 @@ const { data } = await client.$replaceConditionalVariantVersion(
2323
2553
  "_revision": 3,
2324
2554
  "warnings": [
2325
2555
  {
2326
- "code": "ACTIVE_VERSION_REPLACED",
2556
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2327
2557
  "message": "string",
2328
- "valid_from": "2026-08-01T00:00:00.000Z",
2329
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2558
+ "details": {
2559
+ "variant_count": 0,
2560
+ "cap": 0
2561
+ }
2330
2562
  }
2331
2563
  ]
2332
2564
  }
@@ -2386,10 +2618,12 @@ const { data } = await client.$patchConditionalVariantVersion(
2386
2618
  "_revision": 3,
2387
2619
  "warnings": [
2388
2620
  {
2389
- "code": "ACTIVE_VERSION_REPLACED",
2621
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2390
2622
  "message": "string",
2391
- "valid_from": "2026-08-01T00:00:00.000Z",
2392
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2623
+ "details": {
2624
+ "variant_count": 0,
2625
+ "cap": 0
2626
+ }
2393
2627
  }
2394
2628
  ]
2395
2629
  }
@@ -2426,10 +2660,157 @@ const { data } = await client.$deleteConditionalVariantVersion({
2426
2660
  "valid_from": "2027-01-01T00:00:00.000Z",
2427
2661
  "warnings": [
2428
2662
  {
2429
- "code": "ACTIVE_VERSION_REPLACED",
2663
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2430
2664
  "message": "string",
2431
- "valid_from": "2026-08-01T00:00:00.000Z",
2432
- "active_valid_from": "2026-01-01T00:00:00.000Z"
2665
+ "details": {
2666
+ "variant_count": 0,
2667
+ "cap": 0
2668
+ }
2669
+ }
2670
+ ]
2671
+ }
2672
+ ```
2673
+
2674
+ </details>
2675
+
2676
+ ---
2677
+
2678
+ ### `$batchUpsertConditionalVariants`
2679
+
2680
+ Writes up to 100 variants or versions in one call — the endpoint a bulk importer drives a
2681
+ refresh cycle through, so hundreds of thousands of keys are a stream of calls rather than a
2682
+ call per key.
2683
+
2684
+ `POST /v1/conditional-pricing/{slug}/variants:batchUpsert`
2685
+
2686
+ ```ts
2687
+ const { data } = await client.$batchUpsertConditionalVariants(
2688
+ {
2689
+ slug: 'example',
2690
+ },
2691
+ {
2692
+ correlation_id: 'tariff-refresh-2027-01',
2693
+ items: [
2694
+ {
2695
+ entity_id: 'price-sp26d1yo',
2696
+ conditions: {
2697
+ postal_code: '46045'
2698
+ },
2699
+ default: false,
2700
+ valid_from: '2027-01-01T00:00:00Z',
2701
+ values: {
2702
+ unit_amount: 2499,
2703
+ unit_amount_decimal: '24.99'
2704
+ }
2705
+ }
2706
+ ]
2707
+ },
2708
+ )
2709
+ ```
2710
+
2711
+ <details>
2712
+ <summary>Response</summary>
2713
+
2714
+ ```json
2715
+ {
2716
+ "correlation_id": "tariff-refresh-2027-01",
2717
+ "counts": {
2718
+ "variant_created": 1,
2719
+ "version_created": 1,
2720
+ "updated": 1,
2721
+ "skipped": 1,
2722
+ "error": 1
2723
+ },
2724
+ "results": [
2725
+ {
2726
+ "outcome": "variant_created",
2727
+ "entity_id": "price-sp26d1yo",
2728
+ "variant_id": "var-46045",
2729
+ "valid_from": "2027-01-01T00:00:00.000Z",
2730
+ "warnings": [
2731
+ {
2732
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2733
+ "message": "string",
2734
+ "details": {
2735
+ "variant_count": 0,
2736
+ "cap": 0
2737
+ }
2738
+ }
2739
+ ],
2740
+ "error": {
2741
+ "code": "SCHEMA_NOT_FOUND",
2742
+ "details": {
2743
+ "schema": "price"
2744
+ }
2745
+ }
2746
+ }
2747
+ ]
2748
+ }
2749
+ ```
2750
+
2751
+ </details>
2752
+
2753
+ ---
2754
+
2755
+ ### `$batchDeleteConditionalVariants`
2756
+
2757
+ Removes up to 100 variants or versions in one call — the symmetric bulk withdrawal, so
2758
+ retiring a generation of variants, or a scheduled adjustment across many of them, is as
2759
+ cheap as creating it was.
2760
+
2761
+ `POST /v1/conditional-pricing/{slug}/variants:batchDelete`
2762
+
2763
+ ```ts
2764
+ const { data } = await client.$batchDeleteConditionalVariants(
2765
+ {
2766
+ slug: 'example',
2767
+ },
2768
+ {
2769
+ correlation_id: 'postal-code-cleanup-2026-09',
2770
+ items: [
2771
+ {
2772
+ entity_id: 'price-sp26d1yo',
2773
+ variant_id: 'var-46045',
2774
+ valid_from: '2027-01-01T00:00:00Z'
2775
+ }
2776
+ ]
2777
+ },
2778
+ )
2779
+ ```
2780
+
2781
+ <details>
2782
+ <summary>Response</summary>
2783
+
2784
+ ```json
2785
+ {
2786
+ "correlation_id": "postal-code-cleanup-2026-09",
2787
+ "counts": {
2788
+ "deleted": 1,
2789
+ "skipped": 1,
2790
+ "error": 1
2791
+ },
2792
+ "results": [
2793
+ {
2794
+ "outcome": "deleted",
2795
+ "entity_id": "price-sp26d1yo",
2796
+ "variant_id": "var-46045",
2797
+ "valid_from": "2027-01-01T00:00:00.000Z",
2798
+ "warnings": [
2799
+ {
2800
+ "code": "VARIANT_COUNT_APPROACHING_CAP",
2801
+ "message": "string",
2802
+ "details": {
2803
+ "variant_count": 0,
2804
+ "cap": 0
2805
+ }
2806
+ }
2807
+ ],
2808
+ "error": {
2809
+ "code": "SCHEMA_NOT_FOUND",
2810
+ "details": {
2811
+ "schema": "price"
2812
+ }
2813
+ }
2433
2814
  }
2434
2815
  ]
2435
2816
  }
@@ -2479,6 +2860,7 @@ verbatim.
2479
2860
 
2480
2861
  ```ts
2481
2862
  type ConditionDefinition = {
2863
+ id: string // uuid
2482
2864
  name: string
2483
2865
  label: string
2484
2866
  type: "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"
@@ -2486,8 +2868,7 @@ type ConditionDefinition = {
2486
2868
  value: string
2487
2869
  title?: string
2488
2870
  }>
2489
- allow_any?: boolean
2490
- format?: "zipcode" | "zipcode + town"
2871
+ format?: "zipcode" | "zipcode_town"
2491
2872
  }
2492
2873
  ```
2493
2874
 
@@ -2501,6 +2882,7 @@ type ConditionSet = {
2501
2882
  label: string
2502
2883
  description: string
2503
2884
  conditions: Array<{
2885
+ id: string // uuid
2504
2886
  name: string
2505
2887
  label: string
2506
2888
  type: "string" | "number" | "date" | "daterange" | "boolean" | "select" | "location"
@@ -2508,8 +2890,7 @@ type ConditionSet = {
2508
2890
  value: { ... }
2509
2891
  title?: { ... }
2510
2892
  }>
2511
- allow_any?: boolean
2512
- format?: "zipcode" | "zipcode + town"
2893
+ format?: "zipcode" | "zipcode_town"
2513
2894
  }>
2514
2895
  }
2515
2896
  ```
@@ -2523,11 +2904,11 @@ type ConditionSetCatalog = {
2523
2904
  label: string
2524
2905
  description: string
2525
2906
  conditions: Array<{
2907
+ id: { ... }
2526
2908
  name: { ... }
2527
2909
  label: { ... }
2528
2910
  type: { ... }
2529
2911
  options?: { ... }
2530
- allow_any?: { ... }
2531
2912
  format?: { ... }
2532
2913
  }>
2533
2914
  }>
@@ -2539,23 +2920,77 @@ type ConditionSetCatalog = {
2539
2920
  Machine-readable failure mode of a conditional-pricing operation, allowing clients
2540
2921
  to branch on the kind of failure instead of parsing the error message.
2541
2922
 
2542
- - `NOT_FOUND` (404): the addressed entity, variant or version does not exist
2543
- - `AMBIGUOUS_RESOLUTION` (409): several variants match the given con
2923
+ - `SCHEMA_NOT_FOUND` (404): no conditional entity type by that slug
2924
+ - `ENTITY_NOT_FOUND` (404): the schema holds no entity with that id
2925
+ - `ENTITY
2544
2926
 
2545
2927
  ```ts
2546
- 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"
2928
+ 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"
2547
2929
  ```
2548
2930
 
2549
2931
  ### `ResolveConditionalEntityRequest`
2550
2932
 
2933
+ A resolve names one conditional entity, then says which of its variants it means — one of two
2934
+ ways, and never both. `context` describes a situation and asks which variants apply to it;
2935
+ `variant_id` names one variant and skips matching entirely.
2936
+
2937
+ A body carrying both, or neither, is a validation `400
2938
+
2551
2939
  ```ts
2552
2940
  type ResolveConditionalEntityRequest = {
2553
2941
  schema: "product" | "price" | "coupon"
2554
2942
  entity_id: string
2555
- context?: Record<string, unknown>
2943
+ context: Record<string, unknown>
2944
+ as_of?: string
2945
+ options?: {
2946
+ resolve_one?: boolean
2947
+ hydrate?: boolean
2948
+ }
2949
+ } | {
2950
+ schema: "product" | "price" | "coupon"
2951
+ entity_id: string
2952
+ variant_id: string
2953
+ as_of?: string
2954
+ options?: {
2955
+ hydrate?: boolean
2956
+ }
2957
+ }
2958
+ ```
2959
+
2960
+ ### `ResolveByContextRequest`
2961
+
2962
+ Resolve by matching a situation: which of this entity's variants apply to `context`, each
2963
+ composed with the version in effect at `as_of`.
2964
+
2965
+
2966
+ ```ts
2967
+ type ResolveByContextRequest = {
2968
+ schema: "product" | "price" | "coupon"
2969
+ entity_id: string
2970
+ context: Record<string, unknown>
2556
2971
  as_of?: string
2557
2972
  options?: {
2558
2973
  resolve_one?: boolean
2974
+ hydrate?: boolean
2975
+ }
2976
+ }
2977
+ ```
2978
+
2979
+ ### `ResolveByPinRequest`
2980
+
2981
+ Resolve by naming a variant: compose this one, whatever a context would have matched. What an
2982
+ order needs to show the numbers a customer agreed to, and what a contract needs to show what
2983
+ is billable now — the two differ only in whether `as_of` is supplied.
2984
+
2985
+
2986
+ ```ts
2987
+ type ResolveByPinRequest = {
2988
+ schema: "product" | "price" | "coupon"
2989
+ entity_id: string
2990
+ variant_id: string
2991
+ as_of?: string
2992
+ options?: {
2993
+ hydrate?: boolean
2559
2994
  }
2560
2995
  }
2561
2996
  ```
@@ -2569,54 +3004,638 @@ that leave that condition unpinned.
2569
3004
  Each value is either an exact value, typed by its condition, or a single-operator
2570
3005
 
2571
3006
  ```ts
2572
- type ResolveContext = Record<string, unknown>
3007
+ type ResolveContext = Record<string, unknown>
3008
+ ```
3009
+
3010
+ ### `ResolveOptions`
3011
+
3012
+ The options a context resolve accepts. A pin takes `PinnedResolveOptions` instead.
3013
+
3014
+ ```ts
3015
+ type ResolveOptions = {
3016
+ resolve_one?: boolean
3017
+ hydrate?: boolean
3018
+ }
3019
+ ```
3020
+
3021
+ ### `PinnedResolveOptions`
3022
+
3023
+ The options a pinned resolve accepts — `hydrate` and nothing else. `resolve_one` has nothing
3024
+ to change on this branch, where the answer is exactly one result or a 404, so a body sending
3025
+ it is a validation `400`. `hydrate` means what `ResolveOptions.hydrate` means.
3026
+
3027
+
3028
+ ```ts
3029
+ type PinnedResolveOptions = {
3030
+ hydrate?: boolean
3031
+ }
3032
+ ```
3033
+
3034
+ ### `ResolvedVariants`
3035
+
3036
+ ```ts
3037
+ type ResolvedVariants = {
3038
+ results: Array<{
3039
+ _id: string
3040
+ _variant_id: string
3041
+ _version_valid_from: string
3042
+ _conditions: {
3043
+ default: { ... }
3044
+ }
3045
+ _inert_overrides: Array<{
3046
+ attribute: { ... }
3047
+ reason: { ... }
3048
+ }>
3049
+ }>
3050
+ }
3051
+ ```
3052
+
3053
+ ### `ResolvedVariant`
3054
+
3055
+ The entity as this variant leaves it — every attribute of a plain entity read, with the
3056
+ applicable version's overrides applied — plus the discriminators saying where the numbers
3057
+ came from.
3058
+
3059
+ With `options.hydrate`, a relation attribute holds the entities it references rather than the
3060
+ references thems
3061
+
3062
+ ```ts
3063
+ type ResolvedVariant = {
3064
+ _id: string
3065
+ _variant_id: string
3066
+ _version_valid_from: string
3067
+ _conditions: {
3068
+ default: boolean
3069
+ }
3070
+ _inert_overrides: Array<{
3071
+ attribute: string
3072
+ reason: "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"
3073
+ }>
3074
+ }
3075
+ ```
3076
+
3077
+ ### `CreateVariantRequest`
3078
+
3079
+ ```ts
3080
+ type CreateVariantRequest = {
3081
+ conditions?: Record<string, unknown>
3082
+ default?: boolean
3083
+ valid_from?: string
3084
+ values: Record<string, unknown>
3085
+ }
3086
+ ```
3087
+
3088
+ ### `VariantConditions`
3089
+
3090
+ A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a
3091
+ boolean `default` saying whether this is the entity's fallback.
3092
+
3093
+ `default` is always present and always a boolean, so a client can branch on "did I get the
3094
+ fallback?" without knowing how one is stored. The rese
3095
+
3096
+ ```ts
3097
+ type VariantConditions = {
3098
+ default: boolean
3099
+ }
3100
+ ```
3101
+
3102
+ ### `PinnedConditions`
3103
+
3104
+ The situation this variant applies to: a flat map keyed by condition name, as the entity's
3105
+ schema declares them. A condition left out is a wildcard — the variant applies whatever the
3106
+ context says for it, which is what makes adding a condition to a schema non-breaking for the
3107
+ variants that already ex
3108
+
3109
+ ```ts
3110
+ type PinnedConditions = Record<string, unknown>
3111
+ ```
3112
+
3113
+ ### `VariantValues`
3114
+
3115
+ The attribute values this version overrides on the base entity, keyed by attribute name.
3116
+
3117
+ Only attributes currently declaring `overridable_attribute` are applied. Metadata fields
3118
+ (anything underscore-prefixed), readonly attributes, hidden attributes, computed attributes
3119
+ and non-overridable attribute
3120
+
3121
+ ```ts
3122
+ type VariantValues = Record<string, unknown>
3123
+ ```
3124
+
3125
+ ### `CreatedVariant`
3126
+
3127
+ ```ts
3128
+ type CreatedVariant = {
3129
+ variant_id: string
3130
+ entity_id: string
3131
+ schema: "product" | "price" | "coupon"
3132
+ conditions: {
3133
+ default: boolean
3134
+ }
3135
+ valid_from: string
3136
+ values: Record<string, unknown>
3137
+ _created_at: string
3138
+ _updated_at: string
3139
+ _revision: number
3140
+ warnings: Array<{
3141
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3142
+ message: string
3143
+ details: {
3144
+ variant_count: { ... }
3145
+ cap: { ... }
3146
+ }
3147
+ } | {
3148
+ code: "ACTIVE_VERSION_CHANGED"
3149
+ message: string
3150
+ details: {
3151
+ valid_from: { ... }
3152
+ active_valid_from?: { ... }
3153
+ }
3154
+ } | {
3155
+ code: "SUPERSEDED_VERSION_WRITTEN"
3156
+ message: string
3157
+ details: {
3158
+ valid_from: { ... }
3159
+ active_valid_from?: { ... }
3160
+ }
3161
+ } | {
3162
+ code: "ATTRIBUTES_NOT_APPLIED"
3163
+ message: string
3164
+ details: {
3165
+ attributes: { ... }
3166
+ }
3167
+ }>
3168
+ }
3169
+ ```
3170
+
3171
+ ### `WriteWarning`
3172
+
3173
+ Something worth knowing that did not stop a write.
3174
+
3175
+ One vocabulary for every write, so a client branches on what happened rather than on which
3176
+ endpoint it called. `code` and `message` are the only two fields every code shares; everything
3177
+ else lives in a `details` object typed per code, so narrowing
3178
+
3179
+ ```ts
3180
+ type WriteWarning = {
3181
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3182
+ message: string
3183
+ details: {
3184
+ variant_count: number
3185
+ cap: number
3186
+ }
3187
+ } | {
3188
+ code: "ACTIVE_VERSION_CHANGED"
3189
+ message: string
3190
+ details: {
3191
+ valid_from: string
3192
+ active_valid_from?: string
3193
+ }
3194
+ } | {
3195
+ code: "SUPERSEDED_VERSION_WRITTEN"
3196
+ message: string
3197
+ details: {
3198
+ valid_from: string
3199
+ active_valid_from?: string
3200
+ }
3201
+ } | {
3202
+ code: "ATTRIBUTES_NOT_APPLIED"
3203
+ message: string
3204
+ details: {
3205
+ attributes: Array<{
3206
+ attribute: { ... }
3207
+ reason: { ... }
3208
+ }>
3209
+ }
3210
+ }
3211
+ ```
3212
+
3213
+ ### `VersionMoved`
3214
+
3215
+ Which version a write moved, and which one was in effect while it did.
3216
+
3217
+
3218
+ ```ts
3219
+ type VersionMoved = {
3220
+ valid_from: string
3221
+ active_valid_from?: string
3222
+ }
3223
+ ```
3224
+
3225
+ ### `InertOverride`
3226
+
3227
+ One override that did not apply, and why.
3228
+
3229
+ The same entry on both sides of the feature: a write reports the attributes in its body it did
3230
+ not store, and a resolved payload reports the stored overrides composition did not apply. Those
3231
+ are the same fact observed at two moments, so a client learns one
3232
+
3233
+ ```ts
3234
+ type InertOverride = {
3235
+ attribute: string
3236
+ reason: "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"
3237
+ }
3238
+ ```
3239
+
3240
+ ### `InertOverrideReason`
3241
+
3242
+ Why one override did not apply.
3243
+
3244
+ - `ATTRIBUTE_NOT_OVERRIDABLE`: the entity's schema declares the attribute but has not granted
3245
+ it `overridable_attribute`. Granting the flag is an ordinary schema edit, which makes this
3246
+ the reason most often worth acting on.
3247
+ - `ATTRIBUTE_READONLY`: the attribute i
3248
+
3249
+ ```ts
3250
+ type InertOverrideReason = "ATTRIBUTE_NOT_OVERRIDABLE" | "ATTRIBUTE_READONLY" | "ATTRIBUTE_HIDDEN" | "ATTRIBUTE_COMPUTED" | "ATTRIBUTE_UNDECLARED" | "TYPE_NOT_OVERRIDABLE" | "CAPABILITY_NOT_OVERRIDABLE"
3251
+ ```
3252
+
3253
+ ### `DeletedVariant`
3254
+
3255
+ ```ts
3256
+ type DeletedVariant = {
3257
+ variant_id: string
3258
+ entity_id: string
3259
+ schema: "product" | "price" | "coupon"
3260
+ tuple_released: boolean
3261
+ versions_deleted: number
3262
+ }
3263
+ ```
3264
+
3265
+ ### `VariantVersion`
3266
+
3267
+ One version of one variant: the attribute overrides it carries, the instant it takes effect,
3268
+ and the variant it belongs to.
3269
+
3270
+ These are the version's **own** overrides, not the base entity overlaid with them — this is
3271
+ what an editing screen loads and saves, and what it edits is the overrides. Composi
3272
+
3273
+ ```ts
3274
+ type VariantVersion = {
3275
+ variant_id: string
3276
+ entity_id: string
3277
+ schema: "product" | "price" | "coupon"
3278
+ conditions: {
3279
+ default: boolean
3280
+ }
3281
+ valid_from: string
3282
+ values: Record<string, unknown>
3283
+ _created_at: string
3284
+ _updated_at: string
3285
+ _revision: number
3286
+ }
3287
+ ```
3288
+
3289
+ ### `WrittenVariantVersion`
3290
+
3291
+ A version as a write left it, together with anything the write moved.
3292
+
3293
+
3294
+ ```ts
3295
+ type WrittenVariantVersion = {
3296
+ variant_id: string
3297
+ entity_id: string
3298
+ schema: "product" | "price" | "coupon"
3299
+ conditions: {
3300
+ default: boolean
3301
+ }
3302
+ valid_from: string
3303
+ values: Record<string, unknown>
3304
+ _created_at: string
3305
+ _updated_at: string
3306
+ _revision: number
3307
+ warnings: Array<{
3308
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3309
+ message: string
3310
+ details: {
3311
+ variant_count: { ... }
3312
+ cap: { ... }
3313
+ }
3314
+ } | {
3315
+ code: "ACTIVE_VERSION_CHANGED"
3316
+ message: string
3317
+ details: {
3318
+ valid_from: { ... }
3319
+ active_valid_from?: { ... }
3320
+ }
3321
+ } | {
3322
+ code: "SUPERSEDED_VERSION_WRITTEN"
3323
+ message: string
3324
+ details: {
3325
+ valid_from: { ... }
3326
+ active_valid_from?: { ... }
3327
+ }
3328
+ } | {
3329
+ code: "ATTRIBUTES_NOT_APPLIED"
3330
+ message: string
3331
+ details: {
3332
+ attributes: { ... }
3333
+ }
3334
+ }>
3335
+ }
3336
+ ```
3337
+
3338
+ ### `DeletedVariantVersion`
3339
+
3340
+ ```ts
3341
+ type DeletedVariantVersion = {
3342
+ variant_id: string
3343
+ entity_id: string
3344
+ schema: "product" | "price" | "coupon"
3345
+ valid_from: string
3346
+ warnings: Array<{
3347
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3348
+ message: string
3349
+ details: {
3350
+ variant_count: { ... }
3351
+ cap: { ... }
3352
+ }
3353
+ } | {
3354
+ code: "ACTIVE_VERSION_CHANGED"
3355
+ message: string
3356
+ details: {
3357
+ valid_from: { ... }
3358
+ active_valid_from?: { ... }
3359
+ }
3360
+ } | {
3361
+ code: "SUPERSEDED_VERSION_WRITTEN"
3362
+ message: string
3363
+ details: {
3364
+ valid_from: { ... }
3365
+ active_valid_from?: { ... }
3366
+ }
3367
+ } | {
3368
+ code: "ATTRIBUTES_NOT_APPLIED"
3369
+ message: string
3370
+ details: {
3371
+ attributes: { ... }
3372
+ }
3373
+ }>
3374
+ }
3375
+ ```
3376
+
3377
+ ### `AppendVersionRequest`
3378
+
3379
+ ```ts
3380
+ type AppendVersionRequest = {
3381
+ valid_from?: string
3382
+ values: Record<string, unknown>
3383
+ conditions?: Record<string, unknown>
3384
+ }
3385
+ ```
3386
+
3387
+ ### `ReplaceVersionRequest`
3388
+
3389
+ ```ts
3390
+ type ReplaceVersionRequest = {
3391
+ values: Record<string, unknown>
3392
+ _revision: number
3393
+ valid_from?: string
3394
+ conditions?: Record<string, unknown>
3395
+ }
3396
+ ```
3397
+
3398
+ ### `PatchVersionRequest`
3399
+
3400
+ ```ts
3401
+ type PatchVersionRequest = {
3402
+ values: Record<string, unknown>
3403
+ _revision: number
3404
+ valid_from?: string
3405
+ conditions?: Record<string, unknown>
3406
+ }
3407
+ ```
3408
+
3409
+ ### `ListVariantsRequest`
3410
+
3411
+ How to narrow and page a variant listing. Every property is optional, so `{}` is a valid body
3412
+ and asks for the first ten variants of the entity in `variant_id` order — the body itself is
3413
+ required, and an omitted one is a request-validation `400` rather than an unnarrowed page.
3414
+
3415
+ `conditions` and `sea
3416
+
3417
+ ```ts
3418
+ type ListVariantsRequest = {
3419
+ conditions?: Record<string, unknown>
3420
+ search?: string
3421
+ sort?: string
3422
+ from?: number
3423
+ size?: number
3424
+ cursor?: string
3425
+ }
3426
+ ```
3427
+
3428
+ ### `VariantTreeRequest`
3429
+
3430
+ The variants list's request plus `as_of`, the instant each row's version is selected at.
3431
+ `size` is clamped at 100 here; every other shared property means what it means on the list.
3432
+
3433
+
3434
+ ```ts
3435
+ type VariantTreeRequest = {
3436
+ conditions?: Record<string, unknown>
3437
+ search?: string
3438
+ sort?: string
3439
+ from?: number
3440
+ size?: number
3441
+ cursor?: string
3442
+ as_of?: string
3443
+ }
3444
+ ```
3445
+
3446
+ ### `VariantConditionFilter`
3447
+
3448
+ Which pins a variant must carry to be listed: a flat map keyed by condition name, as the
3449
+ entity's schema declares them. A condition left out of the map is not filtered on at all.
3450
+
3451
+ Each value is either an exact value, typed by its condition, or a single-operator predicate
3452
+ object — the same seven a re
3453
+
3454
+ ```ts
3455
+ type VariantConditionFilter = Record<string, unknown>
3456
+ ```
3457
+
3458
+ ### `VariantList`
3459
+
3460
+ ```ts
3461
+ type VariantList = {
3462
+ hits: number
3463
+ results: Array<{
3464
+ variant_id: string
3465
+ entity_id: string
3466
+ schema: "product" | "price" | "coupon"
3467
+ conditions: {
3468
+ default: { ... }
3469
+ }
3470
+ }>
3471
+ next?: string
3472
+ }
3473
+ ```
3474
+
3475
+ ### `VariantListRow`
3476
+
3477
+ One variant as a listing reports it: which variant it is and what it pins.
3478
+
3479
+ No `_revision` — a write re-reads its version through that version's own `GET` — and no
3480
+ `_inert_overrides`, since a listing reports what is stored and only `:resolve` honours the
3481
+ schema.
3482
+
3483
+
3484
+ ```ts
3485
+ type VariantListRow = {
3486
+ variant_id: string
3487
+ entity_id: string
3488
+ schema: "product" | "price" | "coupon"
3489
+ conditions: {
3490
+ default: boolean
3491
+ }
3492
+ }
3493
+ ```
3494
+
3495
+ ### `VariantTree`
3496
+
3497
+ ```ts
3498
+ type VariantTree = {
3499
+ hits: number
3500
+ results: Array<{
3501
+ variant_id: string
3502
+ entity_id: string
3503
+ schema: "product" | "price" | "coupon"
3504
+ conditions: {
3505
+ default: { ... }
3506
+ }
3507
+ status: "active" | "scheduled"
3508
+ version: {
3509
+ variant_id: { ... }
3510
+ entity_id: { ... }
3511
+ schema: { ... }
3512
+ conditions: { ... }
3513
+ valid_from: { ... }
3514
+ values: { ... }
3515
+ _created_at: { ... }
3516
+ _updated_at: { ... }
3517
+ }
3518
+ }>
3519
+ next?: string
3520
+ }
3521
+ ```
3522
+
3523
+ ### `VariantTreeRow`
3524
+
3525
+ A listing row plus the one version the tree view shows for it, and the status saying which
3526
+ version that is.
3527
+
3528
+
3529
+ ```ts
3530
+ type VariantTreeRow = {
3531
+ variant_id: string
3532
+ entity_id: string
3533
+ schema: "product" | "price" | "coupon"
3534
+ conditions: {
3535
+ default: boolean
3536
+ }
3537
+ status: "active" | "scheduled"
3538
+ version: {
3539
+ variant_id: string
3540
+ entity_id: string
3541
+ schema: "product" | "price" | "coupon"
3542
+ conditions: {
3543
+ default: { ... }
3544
+ }
3545
+ valid_from: string
3546
+ values: Record<string, unknown>
3547
+ _created_at: string
3548
+ _updated_at: string
3549
+ }
3550
+ }
3551
+ ```
3552
+
3553
+ ### `VariantTreeRowStatus`
3554
+
3555
+ Whether a tree row's version is the one in effect at `as_of`, or one still ahead of it.
3556
+
3557
+ Exactly two values, and every row has one: a variant always has at least one version, so
3558
+ either a version is in effect at `as_of` or every version of that variant is still to come.
3559
+
3560
+ - `active`: `version` is the
3561
+
3562
+ ```ts
3563
+ type VariantTreeRowStatus = "active" | "scheduled"
2573
3564
  ```
2574
3565
 
2575
- ### `ResolveOptions`
3566
+ ### `VariantVersionSnapshot`
3567
+
3568
+ One version of one variant as a listing reports it: `VariantVersion` without `_revision`.
3569
+
3570
+ The revision is missing on purpose. An editing screen re-reads the one version it is about to
3571
+ write through that version's own `GET`, which is strongly consistent, and writes with the
3572
+ revision it gets back.
3573
+
3574
+ E
2576
3575
 
2577
3576
  ```ts
2578
- type ResolveOptions = {
2579
- resolve_one?: boolean
3577
+ type VariantVersionSnapshot = {
3578
+ variant_id: string
3579
+ entity_id: string
3580
+ schema: "product" | "price" | "coupon"
3581
+ conditions: {
3582
+ default: boolean
3583
+ }
3584
+ valid_from: string
3585
+ values: Record<string, unknown>
3586
+ _created_at: string
3587
+ _updated_at: string
2580
3588
  }
2581
3589
  ```
2582
3590
 
2583
- ### `ResolvedVariants`
3591
+ ### `VariantVersionList`
2584
3592
 
2585
3593
  ```ts
2586
- type ResolvedVariants = {
3594
+ type VariantVersionList = {
2587
3595
  results: Array<{
2588
- _id: string
2589
- _variant_id: string
2590
- _version_valid_from: string
2591
- _conditions: {
3596
+ variant_id: string
3597
+ entity_id: string
3598
+ schema: "product" | "price" | "coupon"
3599
+ conditions: {
2592
3600
  default: { ... }
2593
3601
  }
3602
+ valid_from: string
3603
+ values: Record<string, unknown>
3604
+ _created_at: string
3605
+ _updated_at: string
2594
3606
  }>
3607
+ next?: string
2595
3608
  }
2596
3609
  ```
2597
3610
 
2598
- ### `ResolvedVariant`
3611
+ ### `BatchUpsertVariantsRequest`
2599
3612
 
2600
- The entity as this variant leaves it — every attribute of a plain entity read, with the
2601
- applicable version's overrides applied — plus the discriminators saying where the numbers
2602
- came from.
3613
+ A batch of variant writes under one schema, each item naming the entity it writes to.
2603
3614
 
2604
3615
 
2605
3616
  ```ts
2606
- type ResolvedVariant = {
2607
- _id: string
2608
- _variant_id: string
2609
- _version_valid_from: string
2610
- _conditions: {
2611
- default: boolean
2612
- }
3617
+ type BatchUpsertVariantsRequest = {
3618
+ correlation_id?: string
3619
+ items: Array<{
3620
+ entity_id: string
3621
+ conditions?: Record<string, unknown>
3622
+ default?: boolean
3623
+ valid_from?: string
3624
+ values: Record<string, unknown>
3625
+ }>
2613
3626
  }
2614
3627
  ```
2615
3628
 
2616
- ### `CreateVariantRequest`
3629
+ ### `BatchUpsertItem`
3630
+
3631
+ One variant write: the entity it belongs to, the situation it applies to, and the values it
3632
+ carries — the single-item create's body plus `entity_id`. The two differ on `conditions`: on
3633
+ a create an existing tuple is `TUPLE_CONFLICT`, and here it is a version appended to the
3634
+ variant already holding it
2617
3635
 
2618
3636
  ```ts
2619
- type CreateVariantRequest = {
3637
+ type BatchUpsertItem = {
3638
+ entity_id: string
2620
3639
  conditions?: Record<string, unknown>
2621
3640
  default?: boolean
2622
3641
  valid_from?: string
@@ -2624,204 +3643,328 @@ type CreateVariantRequest = {
2624
3643
  }
2625
3644
  ```
2626
3645
 
2627
- ### `VariantConditions`
3646
+ ### `BatchDeleteVariantsRequest`
2628
3647
 
2629
- A variant's pinned conditions as a reader sees them: the pins the schema declares, plus a
2630
- boolean `default` saying whether this is the entity's fallback.
3648
+ A batch of variant and version deletes under one schema, each item naming the entity it
3649
+ removes from.
2631
3650
 
2632
- `default` is always present and always a boolean, so a client can branch on "did I get the
2633
- fallback?" without knowing how one is stored. The rese
2634
3651
 
2635
3652
  ```ts
2636
- type VariantConditions = {
2637
- default: boolean
3653
+ type BatchDeleteVariantsRequest = {
3654
+ correlation_id?: string
3655
+ items: Array<{
3656
+ entity_id: string
3657
+ variant_id: string
3658
+ valid_from?: string
3659
+ } | {
3660
+ entity_id: string
3661
+ conditions?: Record<string, unknown>
3662
+ default?: boolean
3663
+ valid_from?: string
3664
+ }>
2638
3665
  }
2639
3666
  ```
2640
3667
 
2641
- ### `PinnedConditions`
3668
+ ### `BatchDeleteItem`
2642
3669
 
2643
- The situation this variant applies to: a flat map keyed by condition name, as the entity's
2644
- schema declares them. A condition left out is a wildcard — the variant applies whatever the
2645
- context says for it, which is what makes adding a condition to a schema non-breaking for the
2646
- variants that already ex
3670
+ One delete: the variant, addressed by id or by the condition tuple it pins, and optionally
3671
+ the one version of it to remove.
3672
+
3673
+ Exactly one of the two forms. An item carrying both a `variant_id` and `conditions` matches
3674
+ neither branch and is an envelope `400`, since the request validator rejects the bo
2647
3675
 
2648
3676
  ```ts
2649
- type PinnedConditions = Record<string, unknown>
3677
+ type BatchDeleteItem = {
3678
+ entity_id: string
3679
+ variant_id: string
3680
+ valid_from?: string
3681
+ } | {
3682
+ entity_id: string
3683
+ conditions?: Record<string, unknown>
3684
+ default?: boolean
3685
+ valid_from?: string
3686
+ }
2650
3687
  ```
2651
3688
 
2652
- ### `VariantValues`
2653
-
2654
- The attribute values this version overrides on the base entity, keyed by attribute name.
2655
-
2656
- Only attributes currently declaring `overridable_attribute` are applied. Metadata fields
2657
- (anything underscore-prefixed), readonly attributes, hidden attributes and non-overridable
2658
- attributes present here are ig
3689
+ ### `BatchDeleteByVariantId`
2659
3690
 
2660
- ```ts
2661
- type VariantValues = Record<string, unknown>
2662
- ```
3691
+ A delete addressing its variant by id — the form a cleanup pass uses after the schema has
3692
+ drifted, since a tuple naming a condition the schema no longer declares addresses nothing.
2663
3693
 
2664
- ### `CreatedVariant`
2665
3694
 
2666
3695
  ```ts
2667
- type CreatedVariant = {
2668
- variant_id: string
3696
+ type BatchDeleteByVariantId = {
2669
3697
  entity_id: string
2670
- schema: "product" | "price" | "coupon"
2671
- conditions: {
2672
- default: boolean
2673
- }
2674
- valid_from: string
2675
- values: Record<string, unknown>
2676
- _created_at: string
2677
- _updated_at: string
2678
- _revision: number
2679
- warnings: Array<{
2680
- code: "VARIANT_COUNT_APPROACHING_CAP"
2681
- message: string
2682
- variant_count: number
2683
- cap: number
2684
- }>
3698
+ variant_id: string
3699
+ valid_from?: string
2685
3700
  }
2686
3701
  ```
2687
3702
 
2688
- ### `VariantWriteWarning`
3703
+ ### `BatchDeleteByConditions`
2689
3704
 
2690
- ```ts
2691
- type VariantWriteWarning = {
2692
- code: "VARIANT_COUNT_APPROACHING_CAP"
2693
- message: string
2694
- variant_count: number
2695
- cap: number
2696
- }
2697
- ```
3705
+ A delete addressing its variant by the situation it applies to — the form an importer uses
3706
+ when it knows the source rows rather than the ids they produced.
2698
3707
 
2699
- ### `DeletedVariant`
3708
+ `conditions` is optional because the entity's fallback variant pins nothing: an item
3709
+ addressing it sends `default: true` and no `conditions`, e
2700
3710
 
2701
3711
  ```ts
2702
- type DeletedVariant = {
2703
- variant_id: string
3712
+ type BatchDeleteByConditions = {
2704
3713
  entity_id: string
2705
- schema: "product" | "price" | "coupon"
2706
- tuple_released: boolean
2707
- versions_deleted: number
3714
+ conditions?: Record<string, unknown>
3715
+ default?: boolean
3716
+ valid_from?: string
2708
3717
  }
2709
3718
  ```
2710
3719
 
2711
- ### `VariantVersion`
3720
+ ### `BatchUpsertResult`
2712
3721
 
2713
- One version of one variant: the attribute overrides it carries, the instant it takes effect,
2714
- and the variant it belongs to.
3722
+ What a batch upsert did: one entry per item, in request order, and a count per outcome.
2715
3723
 
2716
- These are the version's **own** overrides, not the base entity overlaid with them — this is
2717
- what an editing screen loads and saves, and what it edits is the overrides. Composi
2718
3724
 
2719
3725
  ```ts
2720
- type VariantVersion = {
2721
- variant_id: string
2722
- entity_id: string
2723
- schema: "product" | "price" | "coupon"
2724
- conditions: {
2725
- default: boolean
3726
+ type BatchUpsertResult = {
3727
+ correlation_id?: string
3728
+ counts: {
3729
+ variant_created: number
3730
+ version_created: number
3731
+ updated: number
3732
+ skipped: number
3733
+ error: number
2726
3734
  }
2727
- valid_from: string
2728
- values: Record<string, unknown>
2729
- _created_at: string
2730
- _updated_at: string
2731
- _revision: number
3735
+ results: Array<{
3736
+ outcome: "variant_created" | "version_created" | "updated" | "skipped" | "error"
3737
+ entity_id: string
3738
+ variant_id?: string
3739
+ valid_from?: string
3740
+ warnings: Array<{
3741
+ code: { ... }
3742
+ message: { ... }
3743
+ details: { ... }
3744
+ } | {
3745
+ code: { ... }
3746
+ message: { ... }
3747
+ details: { ... }
3748
+ } | {
3749
+ code: { ... }
3750
+ message: { ... }
3751
+ details: { ... }
3752
+ } | {
3753
+ code: { ... }
3754
+ message: { ... }
3755
+ details: { ... }
3756
+ }>
3757
+ error?: {
3758
+ message: { ... }
3759
+ status?: { ... }
3760
+ cause?: { ... }
3761
+ error?: { ... }
3762
+ }
3763
+ }>
2732
3764
  }
2733
3765
  ```
2734
3766
 
2735
- ### `WrittenVariantVersion`
3767
+ ### `BatchDeleteResult`
2736
3768
 
2737
- A version as a write left it, together with anything the write moved.
3769
+ What a batch delete did: one entry per item, in request order, and a count per outcome.
2738
3770
 
2739
3771
 
2740
3772
  ```ts
2741
- type WrittenVariantVersion = {
2742
- variant_id: string
2743
- entity_id: string
2744
- schema: "product" | "price" | "coupon"
2745
- conditions: {
2746
- default: boolean
3773
+ type BatchDeleteResult = {
3774
+ correlation_id?: string
3775
+ counts: {
3776
+ deleted: number
3777
+ skipped: number
3778
+ error: number
2747
3779
  }
2748
- valid_from: string
2749
- values: Record<string, unknown>
2750
- _created_at: string
2751
- _updated_at: string
2752
- _revision: number
2753
- warnings: Array<{
2754
- code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"
2755
- message: string
2756
- valid_from: string
2757
- active_valid_from?: string
3780
+ results: Array<{
3781
+ outcome: "deleted" | "skipped" | "error"
3782
+ entity_id: string
3783
+ variant_id?: string
3784
+ valid_from?: string
3785
+ warnings: Array<{
3786
+ code: { ... }
3787
+ message: { ... }
3788
+ details: { ... }
3789
+ } | {
3790
+ code: { ... }
3791
+ message: { ... }
3792
+ details: { ... }
3793
+ } | {
3794
+ code: { ... }
3795
+ message: { ... }
3796
+ details: { ... }
3797
+ } | {
3798
+ code: { ... }
3799
+ message: { ... }
3800
+ details: { ... }
3801
+ }>
3802
+ error?: {
3803
+ message: { ... }
3804
+ status?: { ... }
3805
+ cause?: { ... }
3806
+ error?: { ... }
3807
+ }
2758
3808
  }>
2759
3809
  }
2760
3810
  ```
2761
3811
 
2762
- ### `DeletedVariantVersion`
3812
+ ### `BatchUpsertOutcome`
3813
+
3814
+ What one upsert item did, derived from what was stored rather than from a mode the caller
3815
+ declared.
3816
+
3817
+ - `variant_created`: the condition tuple was unknown, so a variant and its first version were
3818
+ created. The entry's `variant_id` is the id an order or contract pins.
3819
+ - `version_created`: the tuple w
2763
3820
 
2764
3821
  ```ts
2765
- type DeletedVariantVersion = {
2766
- variant_id: string
2767
- entity_id: string
2768
- schema: "product" | "price" | "coupon"
2769
- valid_from: string
2770
- warnings: Array<{
2771
- code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"
2772
- message: string
2773
- valid_from: string
2774
- active_valid_from?: string
2775
- }>
2776
- }
3822
+ type BatchUpsertOutcome = "variant_created" | "version_created" | "updated" | "skipped" | "error"
2777
3823
  ```
2778
3824
 
2779
- ### `VersionWriteWarning`
3825
+ ### `BatchDeleteOutcome`
2780
3826
 
2781
- Something a version write moved. A version write is never refused for being late — backdating a
2782
- version, and editing or deleting one that has already been superseded, are both accepted — so
2783
- what a caller gets instead is a warning naming exactly what changed. One write can carry both
2784
- codes.
3827
+ What one delete item did.
2785
3828
 
3829
+ - `deleted`: the variant, or the one version the item named, is gone.
3830
+ - `skipped`: the item addressed nothing — **the variant or the version**, never the entity. An
3831
+ entity that cannot answer the item is an `error` carrying `ENTITY_NOT_FOUND`,
3832
+ `ENTITY_TYPE_MISMATCH` or
2786
3833
 
2787
3834
  ```ts
2788
- type VersionWriteWarning = {
2789
- code: "ACTIVE_VERSION_REPLACED" | "SUPERSEDED_VERSION_WRITTEN"
2790
- message: string
2791
- valid_from: string
2792
- active_valid_from?: string
3835
+ type BatchDeleteOutcome = "deleted" | "skipped" | "error"
3836
+ ```
3837
+
3838
+ ### `BatchUpsertCounts`
3839
+
3840
+ How many items reached each outcome. Keyed by exactly the values of `BatchUpsertOutcome`, all
3841
+ of them present, so a logger reads a count without `?? 0`.
3842
+
3843
+ **They sum to the length of `results`.** There is no `total`.
3844
+
3845
+
3846
+ ```ts
3847
+ type BatchUpsertCounts = {
3848
+ variant_created: number
3849
+ version_created: number
3850
+ updated: number
3851
+ skipped: number
3852
+ error: number
2793
3853
  }
2794
3854
  ```
2795
3855
 
2796
- ### `AppendVersionRequest`
3856
+ ### `BatchDeleteCounts`
3857
+
3858
+ How many items reached each outcome. Keyed by exactly the values of `BatchDeleteOutcome`, all
3859
+ of them present, and summing to the length of `results`. No `total`.
3860
+
2797
3861
 
2798
3862
  ```ts
2799
- type AppendVersionRequest = {
2800
- valid_from?: string
2801
- values: Record<string, unknown>
2802
- conditions?: Record<string, unknown>
3863
+ type BatchDeleteCounts = {
3864
+ deleted: number
3865
+ skipped: number
3866
+ error: number
2803
3867
  }
2804
3868
  ```
2805
3869
 
2806
- ### `ReplaceVersionRequest`
3870
+ ### `BatchUpsertResultEntry`
3871
+
3872
+ What one upsert item did, and anything worth knowing about it.
3873
+
3874
+ **It carries nothing else.** Position in `results` is the contract, so no entry carries an
3875
+ index; nothing the caller sent is echoed back beyond `entity_id`; and there is no `_revision`
3876
+ — an editing screen re-reads the version it is abou
2807
3877
 
2808
3878
  ```ts
2809
- type ReplaceVersionRequest = {
2810
- values: Record<string, unknown>
2811
- _revision: number
3879
+ type BatchUpsertResultEntry = {
3880
+ outcome: "variant_created" | "version_created" | "updated" | "skipped" | "error"
3881
+ entity_id: string
3882
+ variant_id?: string
2812
3883
  valid_from?: string
2813
- conditions?: Record<string, unknown>
3884
+ warnings: Array<{
3885
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3886
+ message: string
3887
+ details: {
3888
+ variant_count: { ... }
3889
+ cap: { ... }
3890
+ }
3891
+ } | {
3892
+ code: "ACTIVE_VERSION_CHANGED"
3893
+ message: string
3894
+ details: {
3895
+ valid_from: { ... }
3896
+ active_valid_from?: { ... }
3897
+ }
3898
+ } | {
3899
+ code: "SUPERSEDED_VERSION_WRITTEN"
3900
+ message: string
3901
+ details: {
3902
+ valid_from: { ... }
3903
+ active_valid_from?: { ... }
3904
+ }
3905
+ } | {
3906
+ code: "ATTRIBUTES_NOT_APPLIED"
3907
+ message: string
3908
+ details: {
3909
+ attributes: { ... }
3910
+ }
3911
+ }>
3912
+ error?: {
3913
+ message: string
3914
+ status?: number
3915
+ cause?: string
3916
+ error?: string | Record<string, unknown>[]
3917
+ }
2814
3918
  }
2815
3919
  ```
2816
3920
 
2817
- ### `PatchVersionRequest`
3921
+ ### `BatchDeleteResultEntry`
3922
+
3923
+ What one delete item did, and anything worth knowing about it.
3924
+
3925
+ The same six properties as a batch upsert entry, and it carries nothing else.
3926
+
2818
3927
 
2819
3928
  ```ts
2820
- type PatchVersionRequest = {
2821
- values: Record<string, unknown>
2822
- _revision: number
3929
+ type BatchDeleteResultEntry = {
3930
+ outcome: "deleted" | "skipped" | "error"
3931
+ entity_id: string
3932
+ variant_id?: string
2823
3933
  valid_from?: string
2824
- conditions?: Record<string, unknown>
3934
+ warnings: Array<{
3935
+ code: "VARIANT_COUNT_APPROACHING_CAP"
3936
+ message: string
3937
+ details: {
3938
+ variant_count: { ... }
3939
+ cap: { ... }
3940
+ }
3941
+ } | {
3942
+ code: "ACTIVE_VERSION_CHANGED"
3943
+ message: string
3944
+ details: {
3945
+ valid_from: { ... }
3946
+ active_valid_from?: { ... }
3947
+ }
3948
+ } | {
3949
+ code: "SUPERSEDED_VERSION_WRITTEN"
3950
+ message: string
3951
+ details: {
3952
+ valid_from: { ... }
3953
+ active_valid_from?: { ... }
3954
+ }
3955
+ } | {
3956
+ code: "ATTRIBUTES_NOT_APPLIED"
3957
+ message: string
3958
+ details: {
3959
+ attributes: { ... }
3960
+ }
3961
+ }>
3962
+ error?: {
3963
+ message: string
3964
+ status?: number
3965
+ cause?: string
3966
+ error?: string | Record<string, unknown>[]
3967
+ }
2825
3968
  }
2826
3969
  ```
2827
3970
 
@@ -2835,21 +3978,32 @@ type Error = {
2835
3978
  }
2836
3979
  ```
2837
3980
 
3981
+ ### `ReportedError`
3982
+
3983
+ The `error` field of an error response: the message, or — where the request itself failed
3984
+ validation before any handler ran — the validation errors themselves, which those 400s put
3985
+ here in place of a string.
3986
+
3987
+ A conditional-pricing operation answers a body its schema rejects with the list, and
3988
+ everyt
3989
+
3990
+ ```ts
3991
+ type ReportedError = string | Record<string, unknown>[]
3992
+ ```
3993
+
2838
3994
  ### `ConditionalPricingError`
2839
3995
 
2840
- An error from a conditional-pricing operation, carrying a machine-readable `code`
2841
- from the conditional-pricing vocabulary plus any structured data about the failure,
2842
- so a client can branch on the kind of failure rather than parse the message.
2843
- Referenced only by the operations that emit these codes;
3996
+ An error from a conditional-pricing operation, carrying a machine-readable `code` from the
3997
+ conditional-pricing vocabulary plus the structured data that code explains, so a client can
3998
+ branch on the kind of failure rather than parse the message.
3999
+ Referenced only by the operations that emit these codes;
2844
4000
 
2845
4001
  ```ts
2846
4002
  type ConditionalPricingError = {
2847
4003
  message: string
2848
4004
  status?: number
2849
4005
  cause?: string
2850
- error?: string
2851
- code?: "NOT_FOUND" | "AMBIGUOUS_RESOLUTION" | "TUPLE_CONFLICT" | "VERSION_CONFLICT" | "CONDITION_UNDEFINED" | "OPERATOR_UNSUPPORTED" | "CONTEXT_FORMAT_INVALID" | "CONDITION_VALUE_INVALID" | "TOO_MANY_MATCHES" | "WRITE_CONFLICT"
2852
- details?: Record<string, unknown>
4006
+ error?: string | Record<string, unknown>[]
2853
4007
  }
2854
4008
  ```
2855
4009
 
@@ -2924,6 +4078,7 @@ type Product = {
2924
4078
  _tags?: { ... }
2925
4079
  }>
2926
4080
  }
4081
+ is_conditional?: boolean
2927
4082
  _availability_files?: Array<{
2928
4083
  _id: string
2929
4084
  filename: string
@@ -3117,6 +4272,7 @@ type Order = {
3117
4272
  product_images?: { ... }
3118
4273
  product_downloads?: { ... }
3119
4274
  price_options?: { ... }
4275
+ is_conditional?: { ... }
3120
4276
  _availability_files?: { ... }
3121
4277
  _id?: { ... }
3122
4278
  _title?: { ... }
@@ -3127,7 +4283,6 @@ type Order = {
3127
4283
  } | {
3128
4284
  metadata?: Array<{
3129
4285
  key?: { ... }
3130
- value?: { ... }
3131
4286
  // ...
3132
4287
  }
3133
4288
  ```
@@ -3499,6 +4654,7 @@ type CatalogSearchResult = {
3499
4654
  price_options?: {
3500
4655
  $relation?: { ... }
3501
4656
  }
4657
+ is_conditional?: boolean
3502
4658
  _availability_files?: Array<{
3503
4659
  _id: { ... }
3504
4660
  filename: { ... }
@@ -3543,6 +4699,7 @@ type CatalogSearchResult = {
3543
4699
  fixed_value_currency?: string
3544
4700
  cashback_period?: "0" | "12"
3545
4701
  active?: boolean
4702
+ is_conditional?: boolean
3546
4703
  requires_promo_code?: boolean
3547
4704
  }>
3548
4705
  }
@@ -4671,6 +5828,7 @@ type BasePriceItemCommon = {
4671
5828
  price_options?: {
4672
5829
  $relation?: { ... }
4673
5830
  }
5831
+ is_conditional?: boolean
4674
5832
  _availability_files?: Array<{
4675
5833
  _id: { ... }
4676
5834
  filename: { ... }
@@ -4976,6 +6134,7 @@ type BasePriceItemDto = {
4976
6134
  price_options?: {
4977
6135
  $relation?: { ... }
4978
6136
  }
6137
+ is_conditional?: boolean
4979
6138
  _availability_files?: Array<{
4980
6139
  _id: { ... }
4981
6140
  filename: { ... }
@@ -5409,6 +6568,7 @@ type OrderPayload = {
5409
6568
  fixed_value_currency?: { ... }
5410
6569
  cashback_period?: { ... }
5411
6570
  active?: { ... }
6571
+ is_conditional?: { ... }
5412
6572
  requires_promo_code?: { ... }
5413
6573
  }>
5414
6574
  type?: "one_time" | "recurring"
@@ -5416,7 +6576,6 @@ type OrderPayload = {
5416
6576
  unit_amount?: number
5417
6577
  unit_amount_gross?: number
5418
6578
  unit_amount_currency?: string
5419
- unit_amount_decimal?: string
5420
6579
  // ...
5421
6580
  }
5422
6581
  ```
@@ -5489,6 +6648,7 @@ type PriceItems = Array<{
5489
6648
  price_options?: {
5490
6649
  $relation?: { ... }
5491
6650
  }
6651
+ is_conditional?: boolean
5492
6652
  _availability_files?: Array<{
5493
6653
  _id: { ... }
5494
6654
  filename: { ... }
@@ -5525,7 +6685,6 @@ type PriceItems = Array<{
5525
6685
  value?: number
5526
6686
  metadata?: Record<string, string>
5527
6687
  }>
5528
- is_tax_inclusive?: boolean
5529
6688
  // ...
5530
6689
  }
5531
6690
  ```
@@ -5598,6 +6757,7 @@ type CompositePriceItem = {
5598
6757
  price_options?: {
5599
6758
  $relation?: { ... }
5600
6759
  }
6760
+ is_conditional?: boolean
5601
6761
  _availability_files?: Array<{
5602
6762
  _id: { ... }
5603
6763
  filename: { ... }
@@ -5687,6 +6847,7 @@ type BasePriceItem = {
5687
6847
  price_options?: {
5688
6848
  $relation?: { ... }
5689
6849
  }
6850
+ is_conditional?: boolean
5690
6851
  _availability_files?: Array<{
5691
6852
  _id: { ... }
5692
6853
  filename: { ... }
@@ -5836,6 +6997,7 @@ type PriceItem = {
5836
6997
  price_options?: {
5837
6998
  $relation?: { ... }
5838
6999
  }
7000
+ is_conditional?: boolean
5839
7001
  _availability_files?: Array<{
5840
7002
  _id: { ... }
5841
7003
  filename: { ... }
@@ -6052,6 +7214,7 @@ type PricingDetails = {
6052
7214
  product_images?: { ... }
6053
7215
  product_downloads?: { ... }
6054
7216
  price_options?: { ... }
7217
+ is_conditional?: { ... }
6055
7218
  _availability_files?: { ... }
6056
7219
  _id?: { ... }
6057
7220
  _title?: { ... }
@@ -6089,6 +7252,7 @@ type PricingDetails = {
6089
7252
  product_images?: { ... }
6090
7253
  product_downloads?: { ... }
6091
7254
  price_options?: { ... }
7255
+ is_conditional?: { ... }
6092
7256
  _availability_files?: { ... }
6093
7257
  _id?: { ... }
6094
7258
  _title?: { ... }
@@ -6119,8 +7283,6 @@ type PricingDetails = {
6119
7283
  _id: { ... }
6120
7284
  _title: { ... }
6121
7285
  _org: { ... }
6122
- _schema: { ... }
6123
- _tags?: { ... }
6124
7286
  // ...
6125
7287
  }
6126
7288
  ```
@@ -6149,6 +7311,7 @@ type PromoCodeValidationResponse = {
6149
7311
  fixed_value_currency?: string
6150
7312
  cashback_period?: "0" | "12"
6151
7313
  active?: boolean
7314
+ is_conditional?: boolean
6152
7315
  requires_promo_code?: boolean
6153
7316
  }>
6154
7317
  }
@@ -6190,6 +7353,7 @@ type PricingDetailsResponse = {
6190
7353
  product_images?: { ... }
6191
7354
  product_downloads?: { ... }
6192
7355
  price_options?: { ... }
7356
+ is_conditional?: { ... }
6193
7357
  _availability_files?: { ... }
6194
7358
  _id?: { ... }
6195
7359
  _title?: { ... }
@@ -6227,6 +7391,7 @@ type PricingDetailsResponse = {
6227
7391
  product_images?: { ... }
6228
7392
  product_downloads?: { ... }
6229
7393
  price_options?: { ... }
7394
+ is_conditional?: { ... }
6230
7395
  _availability_files?: { ... }
6231
7396
  _id?: { ... }
6232
7397
  _title?: { ... }
@@ -6257,8 +7422,6 @@ type PricingDetailsResponse = {
6257
7422
  _id: { ... }
6258
7423
  _title: { ... }
6259
7424
  _org: { ... }
6260
- _schema: { ... }
6261
- _tags?: { ... }
6262
7425
  // ...
6263
7426
  }
6264
7427
  ```
@@ -6481,6 +7644,7 @@ type BaseCouponCommon = {
6481
7644
  fixed_value_currency?: string
6482
7645
  cashback_period?: "0" | "12"
6483
7646
  active?: boolean
7647
+ is_conditional?: boolean
6484
7648
  requires_promo_code?: boolean
6485
7649
  }
6486
7650
  ```
@@ -6508,6 +7672,7 @@ type CouponWithoutPromoCodes = {
6508
7672
  fixed_value_currency?: string
6509
7673
  cashback_period?: "0" | "12"
6510
7674
  active?: boolean
7675
+ is_conditional?: boolean
6511
7676
  requires_promo_code?: boolean
6512
7677
  }
6513
7678
  ```
@@ -6535,6 +7700,7 @@ type Coupon = {
6535
7700
  fixed_value_currency?: string
6536
7701
  cashback_period?: "0" | "12"
6537
7702
  active?: boolean
7703
+ is_conditional?: boolean
6538
7704
  requires_promo_code?: boolean
6539
7705
  }
6540
7706
  ```
@@ -6560,6 +7726,7 @@ type CouponItem = {
6560
7726
  fixed_value_currency?: string
6561
7727
  cashback_period?: "0" | "12"
6562
7728
  active?: boolean
7729
+ is_conditional?: boolean
6563
7730
  requires_promo_code?: boolean
6564
7731
  }
6565
7732
  ```
@@ -6598,6 +7765,7 @@ type RedeemedPromo = {
6598
7765
  fixed_value_currency?: string
6599
7766
  cashback_period?: "0" | "12"
6600
7767
  active?: boolean
7768
+ is_conditional?: boolean
6601
7769
  requires_promo_code?: boolean
6602
7770
  }>
6603
7771
  }