@hyperscale0/udl 2.6.1 → 3.0.0

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 (213) hide show
  1. package/CHANGELOG.md +2 -330
  2. package/LICENSING.md +1 -2
  3. package/README.md +3 -114
  4. package/TRADEMARKS.md +2 -2
  5. package/dist/diagnostics.d.ts +21 -201
  6. package/dist/diagnostics.d.ts.map +1 -1
  7. package/dist/diagnostics.js +29 -193
  8. package/dist/diagnostics.js.map +1 -1
  9. package/dist/evolution.d.ts +3 -132
  10. package/dist/evolution.d.ts.map +1 -1
  11. package/dist/evolution.js +29 -633
  12. package/dist/evolution.js.map +1 -1
  13. package/dist/finance.d.ts +5 -72
  14. package/dist/finance.d.ts.map +1 -1
  15. package/dist/finance.js +233 -737
  16. package/dist/finance.js.map +1 -1
  17. package/dist/index.d.ts +7 -18
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +7 -12
  20. package/dist/index.js.map +1 -1
  21. package/dist/instrument-references.d.ts.map +1 -1
  22. package/dist/instrument-references.js +3 -2
  23. package/dist/instrument-references.js.map +1 -1
  24. package/dist/schema.d.ts +2079 -4564
  25. package/dist/schema.d.ts.map +1 -1
  26. package/dist/schema.js +270 -1609
  27. package/dist/schema.js.map +1 -1
  28. package/dist/validation.d.ts +8 -104
  29. package/dist/validation.d.ts.map +1 -1
  30. package/dist/validation.js +653 -3271
  31. package/dist/validation.js.map +1 -1
  32. package/docs/README.md +147 -14
  33. package/package.json +7 -11
  34. package/spec/README.md +151 -164
  35. package/spec/darb.udl.json +249 -0
  36. package/spec/udl.schema.json +4104 -3202
  37. package/src/diagnostics.ts +51 -246
  38. package/src/evolution.ts +39 -1045
  39. package/src/finance.ts +287 -1127
  40. package/src/index.ts +18 -142
  41. package/src/instrument-references.ts +3 -2
  42. package/src/schema.ts +285 -1843
  43. package/src/validation.ts +870 -5611
  44. package/conformance/README.md +0 -82
  45. package/conformance/evolution/action-contract.expected.json +0 -10
  46. package/conformance/evolution/action-contract.live.udl +0 -44
  47. package/conformance/evolution/action-contract.next.udl +0 -45
  48. package/conformance/evolution/product-identity.expected.json +0 -10
  49. package/conformance/evolution/product-identity.live.udl +0 -55
  50. package/conformance/evolution/product-identity.next.udl +0 -55
  51. package/conformance/evolution/version-required.expected.json +0 -10
  52. package/conformance/evolution/version-required.live.udl +0 -55
  53. package/conformance/evolution/version-required.next.udl +0 -58
  54. package/conformance/invalid/action-without-transition.expected.json +0 -10
  55. package/conformance/invalid/action-without-transition.udl +0 -60
  56. package/conformance/invalid/agent-description-too-long.expected.json +0 -10
  57. package/conformance/invalid/agent-description-too-long.udl +0 -57
  58. package/conformance/invalid/blank-title.expected.json +0 -10
  59. package/conformance/invalid/blank-title.udl +0 -54
  60. package/conformance/invalid/call-binds-results.expected.json +0 -10
  61. package/conformance/invalid/call-binds-results.udl +0 -314
  62. package/conformance/invalid/call-unknown-action.expected.json +0 -10
  63. package/conformance/invalid/call-unknown-action.udl +0 -314
  64. package/conformance/invalid/composition-dial-duplicate-key.expected.json +0 -10
  65. package/conformance/invalid/composition-dial-duplicate-key.udl +0 -73
  66. package/conformance/invalid/depth-budget.expected.json +0 -10
  67. package/conformance/invalid/depth-budget.udl +0 -49
  68. package/conformance/invalid/duplicate-subject.expected.json +0 -10
  69. package/conformance/invalid/duplicate-subject.udl +0 -230
  70. package/conformance/invalid/forged-effects.expected.json +0 -10
  71. package/conformance/invalid/forged-effects.udl +0 -76
  72. package/conformance/invalid/format-version.expected.json +0 -10
  73. package/conformance/invalid/format-version.udl +0 -54
  74. package/conformance/invalid/instrument-id-not-snake-case.expected.json +0 -10
  75. package/conformance/invalid/instrument-id-not-snake-case.udl +0 -54
  76. package/conformance/invalid/invalid-aggregate-gate-shape.expected.json +0 -10
  77. package/conformance/invalid/invalid-aggregate-gate-shape.udl +0 -1819
  78. package/conformance/invalid/invalid-check-duration.expected.json +0 -10
  79. package/conformance/invalid/invalid-check-duration.udl +0 -219
  80. package/conformance/invalid/invalid-dial-anchor.expected.json +0 -10
  81. package/conformance/invalid/invalid-dial-anchor.udl +0 -219
  82. package/conformance/invalid/invalid-exception-parent-ref.expected.json +0 -10
  83. package/conformance/invalid/invalid-exception-parent-ref.udl +0 -2487
  84. package/conformance/invalid/invalid-exposure-shape.expected.json +0 -10
  85. package/conformance/invalid/invalid-exposure-shape.udl +0 -1819
  86. package/conformance/invalid/invalid-journeys.expected.json +0 -10
  87. package/conformance/invalid/invalid-journeys.udl +0 -77
  88. package/conformance/invalid/invalid-remainder.expected.json +0 -10
  89. package/conformance/invalid/invalid-remainder.udl +0 -220
  90. package/conformance/invalid/invalid-schema-keyword.expected.json +0 -10
  91. package/conformance/invalid/invalid-schema-keyword.udl +0 -220
  92. package/conformance/invalid/invalid-utf8.expected.json +0 -10
  93. package/conformance/invalid/invalid-utf8.udl +0 -1
  94. package/conformance/invalid/leaf-effect-mismatch.expected.json +0 -10
  95. package/conformance/invalid/leaf-effect-mismatch.udl +0 -314
  96. package/conformance/invalid/malformed-json.expected.json +0 -10
  97. package/conformance/invalid/malformed-json.udl +0 -1
  98. package/conformance/invalid/missing-create-action.expected.json +0 -10
  99. package/conformance/invalid/missing-create-action.udl +0 -48
  100. package/conformance/invalid/missing-exception-amount-field.expected.json +0 -10
  101. package/conformance/invalid/missing-exception-amount-field.udl +0 -2487
  102. package/conformance/invalid/missing-exception-contract.expected.json +0 -14
  103. package/conformance/invalid/missing-exception-contract.udl +0 -2523
  104. package/conformance/invalid/missing-exception-reason-field.expected.json +0 -10
  105. package/conformance/invalid/missing-exception-reason-field.udl +0 -2487
  106. package/conformance/invalid/not-an-object.expected.json +0 -10
  107. package/conformance/invalid/not-an-object.udl +0 -1
  108. package/conformance/invalid/payout-reconcile-not-a-bank-debit.expected.json +0 -10
  109. package/conformance/invalid/payout-reconcile-not-a-bank-debit.udl +0 -259
  110. package/conformance/invalid/piece-plan-without-partition.expected.json +0 -10
  111. package/conformance/invalid/piece-plan-without-partition.udl +0 -305
  112. package/conformance/invalid/private-action-independent-approval.expected.json +0 -10
  113. package/conformance/invalid/private-action-independent-approval.udl +0 -314
  114. package/conformance/invalid/quote-freeze-set-incomplete.expected.json +0 -10
  115. package/conformance/invalid/quote-freeze-set-incomplete.udl +0 -261
  116. package/conformance/invalid/quote-named-reference-gate.expected.json +0 -10
  117. package/conformance/invalid/quote-named-reference-gate.udl +0 -50
  118. package/conformance/invalid/reconcile-named-reference-gate.expected.json +0 -10
  119. package/conformance/invalid/reconcile-named-reference-gate.udl +0 -50
  120. package/conformance/invalid/unfund-order-not-reversed.expected.json +0 -10
  121. package/conformance/invalid/unfund-order-not-reversed.udl +0 -314
  122. package/conformance/invalid/unknown-key.expected.json +0 -10
  123. package/conformance/invalid/unknown-key.udl +0 -55
  124. package/conformance/invalid/unknown-reference-gate-field.expected.json +0 -10
  125. package/conformance/invalid/unknown-reference-gate-field.udl +0 -1819
  126. package/conformance/invalid/unknown-required-field.expected.json +0 -10
  127. package/conformance/invalid/unknown-required-field.udl +0 -220
  128. package/conformance/invalid/unreachable-state.expected.json +0 -10
  129. package/conformance/invalid/unreachable-state.udl +0 -55
  130. package/conformance/invalid/wrong-exception-amount-field.expected.json +0 -10
  131. package/conformance/invalid/wrong-exception-amount-field.udl +0 -2487
  132. package/conformance/invalid/wrong-exception-reason-field.expected.json +0 -10
  133. package/conformance/invalid/wrong-exception-reason-field.udl +0 -2487
  134. package/conformance/valid/agent-description.expected.json +0 -6
  135. package/conformance/valid/agent-description.udl +0 -66
  136. package/conformance/valid/attested.expected.json +0 -6
  137. package/conformance/valid/attested.udl +0 -251
  138. package/conformance/valid/cards.expected.json +0 -6
  139. package/conformance/valid/cards.udl +0 -1579
  140. package/conformance/valid/commerce-escrow.expected.json +0 -6
  141. package/conformance/valid/commerce-escrow.udl +0 -1512
  142. package/conformance/valid/compiled-crowdfunding.expected.json +0 -6
  143. package/conformance/valid/compiled-crowdfunding.udl +0 -1843
  144. package/conformance/valid/compiled-watch-club.expected.json +0 -6
  145. package/conformance/valid/compiled-watch-club.udl +0 -2486
  146. package/conformance/valid/complete-contract.expected.json +0 -6
  147. package/conformance/valid/complete-contract.udl +0 -218
  148. package/conformance/valid/effect-signatures.expected.json +0 -6
  149. package/conformance/valid/effect-signatures.udl +0 -75
  150. package/conformance/valid/hand-edited.expected.json +0 -6
  151. package/conformance/valid/hand-edited.udl +0 -1
  152. package/conformance/valid/insured-car-marketplace.expected.json +0 -6
  153. package/conformance/valid/insured-car-marketplace.udl +0 -1050
  154. package/conformance/valid/insured-travel.expected.json +0 -6
  155. package/conformance/valid/insured-travel.udl +0 -3469
  156. package/conformance/valid/minimal.expected.json +0 -6
  157. package/conformance/valid/minimal.udl +0 -62
  158. package/conformance/valid/piece-plan-calls.expected.json +0 -6
  159. package/conformance/valid/piece-plan-calls.udl +0 -314
  160. package/conformance/valid/protection.expected.json +0 -6
  161. package/conformance/valid/protection.udl +0 -1551
  162. package/conformance/valid/string-escaping.expected.json +0 -6
  163. package/conformance/valid/string-escaping.udl +0 -54
  164. package/conformance/valid/vocabulary.expected.json +0 -6
  165. package/conformance/valid/vocabulary.udl +0 -2012
  166. package/dist/allocation.d.ts +0 -60
  167. package/dist/allocation.d.ts.map +0 -1
  168. package/dist/allocation.js +0 -177
  169. package/dist/allocation.js.map +0 -1
  170. package/dist/check-profiles.d.ts +0 -57
  171. package/dist/check-profiles.d.ts.map +0 -1
  172. package/dist/check-profiles.js +0 -62
  173. package/dist/check-profiles.js.map +0 -1
  174. package/dist/distribution.d.ts +0 -15
  175. package/dist/distribution.d.ts.map +0 -1
  176. package/dist/distribution.js +0 -49
  177. package/dist/distribution.js.map +0 -1
  178. package/dist/effects.d.ts +0 -58
  179. package/dist/effects.d.ts.map +0 -1
  180. package/dist/effects.js +0 -1126
  181. package/dist/effects.js.map +0 -1
  182. package/dist/reference.d.ts +0 -3
  183. package/dist/reference.d.ts.map +0 -1
  184. package/dist/reference.js +0 -28
  185. package/dist/reference.js.map +0 -1
  186. package/dist/vocabulary.d.ts +0 -23
  187. package/dist/vocabulary.d.ts.map +0 -1
  188. package/dist/vocabulary.js +0 -1052
  189. package/dist/vocabulary.js.map +0 -1
  190. package/docs/funding-custody.md +0 -165
  191. package/docs/guide/01-a-document.md +0 -37
  192. package/docs/guide/02-money-steps.md +0 -23
  193. package/docs/guide/03-laws.md +0 -18
  194. package/docs/guide/04-fees-and-remainder.md +0 -36
  195. package/docs/guide/05-checks-updates-dials.md +0 -7
  196. package/docs/guide/06-effects.md +0 -11
  197. package/docs/guide/07-evolution.md +0 -11
  198. package/docs/guide/08-implementing.md +0 -13
  199. package/docs/guide/09-schedules-and-allocation.md +0 -132
  200. package/docs/llms-full.txt +0 -2008
  201. package/docs/llms.txt +0 -14
  202. package/docs/piece-plans.md +0 -148
  203. package/docs/reference/canonical.md +0 -16
  204. package/docs/reference/clauses.md +0 -1585
  205. package/docs/reference/cli.md +0 -24
  206. package/docs/reference/diagnostics.md +0 -38
  207. package/skills/udl/SKILL.md +0 -28
  208. package/src/allocation.ts +0 -259
  209. package/src/check-profiles.ts +0 -80
  210. package/src/distribution.ts +0 -61
  211. package/src/effects.ts +0 -1920
  212. package/src/reference.ts +0 -31
  213. package/src/vocabulary.ts +0 -1635
@@ -1,1579 +0,0 @@
1
- {
2
- "instruments": [
3
- {
4
- "actionOrder": [
5
- "create",
6
- "activate",
7
- "suspend",
8
- "resume",
9
- "close"
10
- ],
11
- "actions": {
12
- "activate": {
13
- "agentDescription": "Approve the customer to hold and use cards. Only a pending cardholder can activate. Card create, activate, and unfreeze all require an active cardholder, so call this first.",
14
- "description": "Approves the customer to hold and use cards.",
15
- "examples": [
16
- {
17
- "input": {
18
- "cardholderId": "chd_sandbox_customer0001",
19
- "tenantId": "ten_sandbox_cards000001"
20
- },
21
- "name": "activate_approved_cardholder"
22
- }
23
- ],
24
- "moves": [],
25
- "steps": [],
26
- "summary": "Activate a cardholder"
27
- },
28
- "close": {
29
- "agentDescription": "Permanently end the cardholder relationship. This does not reverse and it does not cancel their cards. Cancel each card separately on the card instrument.",
30
- "description": "Permanently ends the customer's cardholder relationship. Existing cards must be canceled separately.",
31
- "examples": [
32
- {
33
- "input": {
34
- "cardholderId": "chd_sandbox_customer0001",
35
- "tenantId": "ten_sandbox_cards000001"
36
- },
37
- "name": "close_cardholder_relationship"
38
- }
39
- ],
40
- "moves": [],
41
- "steps": [],
42
- "summary": "Close a cardholder"
43
- },
44
- "create": {
45
- "agentDescription": "Register a customer as a pending cardholder. The caller supplies the tenant-local customer ID and display name, with email and phone optional. A pending cardholder cannot be issued a card yet. No money moves.",
46
- "description": "Creates a pending cardholder for one verified first-party customer.",
47
- "examples": [
48
- {
49
- "input": {
50
- "customerId": "cus_sandbox_customer0001",
51
- "displayName": "Noura Al Saud",
52
- "email": "noura@example.test",
53
- "phoneNumber": "+966500000001",
54
- "productId": "prd_sandbox_cards000001",
55
- "tenantId": "ten_sandbox_cards000001"
56
- },
57
- "name": "create_customer_cardholder"
58
- }
59
- ],
60
- "moves": [],
61
- "steps": [],
62
- "summary": "Create a cardholder"
63
- },
64
- "resume": {
65
- "agentDescription": "Return a suspended cardholder to active so cards can be issued and activated again. Only a suspended cardholder can resume.",
66
- "description": "Restores card access after a suspension is resolved.",
67
- "examples": [
68
- {
69
- "input": {
70
- "cardholderId": "chd_sandbox_customer0001",
71
- "tenantId": "ten_sandbox_cards000001"
72
- },
73
- "name": "resume_cardholder_access"
74
- }
75
- ],
76
- "moves": [],
77
- "steps": [],
78
- "summary": "Resume a cardholder"
79
- },
80
- "suspend": {
81
- "agentDescription": "Pause the customer's card access without ending the relationship. Only an active cardholder can suspend, and suspending blocks new card issuance, activation, and unfreezing. Cards already active keep authorizing until you freeze them.",
82
- "description": "Pauses the customer's card access without closing the cardholder.",
83
- "examples": [
84
- {
85
- "input": {
86
- "cardholderId": "chd_sandbox_customer0001",
87
- "tenantId": "ten_sandbox_cards000001"
88
- },
89
- "name": "suspend_cardholder_access"
90
- }
91
- ],
92
- "moves": [],
93
- "steps": [],
94
- "summary": "Suspend a cardholder"
95
- }
96
- },
97
- "agentDescription": "Reach for cardholder when a customer must be approved to hold cards before any card exists. A suspended or closed cardholder blocks issuing, activating, and unfreezing cards. Cards already active keep working, so freeze or cancel those on the card instrument.",
98
- "callerParkedStates": {
99
- "active": "a cardholder in good standing stays active until the issuer or holder acts",
100
- "pending": "activation follows the issuer's verification outcome",
101
- "suspended": "reinstatement or closure is an issuer decision"
102
- },
103
- "description": "A cardholder links one first-party customer to the card program, becomes active after approval, may be suspended and resumed, and closes permanently when card access ends.",
104
- "fields": {
105
- "customerId": {
106
- "description": "Tenant-local customer ID",
107
- "pattern": "^cus_(sandbox|live)_[a-z0-9]{8,64}$",
108
- "type": "string"
109
- },
110
- "displayName": {
111
- "maxLength": 120,
112
- "minLength": 1,
113
- "type": "string"
114
- },
115
- "email": {
116
- "format": "hyperscale-email",
117
- "type": "string"
118
- },
119
- "phoneNumber": {
120
- "maxLength": 32,
121
- "minLength": 6,
122
- "type": "string"
123
- }
124
- },
125
- "id": "cardholder",
126
- "idPrefix": "chd",
127
- "lifecycle": {
128
- "initial": "pending",
129
- "states": [
130
- "pending",
131
- "active",
132
- "suspended",
133
- "closed"
134
- ],
135
- "transitions": {
136
- "activate": {
137
- "from": [
138
- "pending"
139
- ],
140
- "to": "active"
141
- },
142
- "close": {
143
- "from": [
144
- "pending",
145
- "active",
146
- "suspended"
147
- ],
148
- "to": "closed"
149
- },
150
- "resume": {
151
- "from": [
152
- "suspended"
153
- ],
154
- "to": "active"
155
- },
156
- "suspend": {
157
- "from": [
158
- "active"
159
- ],
160
- "to": "suspended"
161
- }
162
- }
163
- },
164
- "nav": [
165
- "Blueprints",
166
- "Cardholders"
167
- ],
168
- "required": [
169
- "customerId",
170
- "displayName"
171
- ],
172
- "summary": "Customer approved to hold cards in a product.",
173
- "templateId": "wallet_cards",
174
- "title": "Cardholder",
175
- "update": {
176
- "examples": [
177
- {
178
- "input": {
179
- "cardholderId": "chd_sandbox_customer0001",
180
- "displayName": "Noura Al Saud",
181
- "email": "noura@example.test",
182
- "tenantId": "ten_sandbox_cards000001"
183
- },
184
- "name": "update_cardholder_contact"
185
- }
186
- ],
187
- "fields": [
188
- "displayName",
189
- "email",
190
- "phoneNumber"
191
- ],
192
- "states": [
193
- "pending",
194
- "active",
195
- "suspended"
196
- ]
197
- }
198
- },
199
- {
200
- "actionOrder": [
201
- "create",
202
- "activate",
203
- "freeze",
204
- "unfreeze",
205
- "cancel"
206
- ],
207
- "actions": {
208
- "activate": {
209
- "agentDescription": "Make an issued card able to authorize. Call this once the cardholder confirms they hold the card. A card that is already active, frozen, or canceled refuses.",
210
- "description": "Makes the issued virtual card available for authorization.",
211
- "effects": {
212
- "reads": [
213
- {
214
- "signature": "reads.requires_refs",
215
- "source": "requiresRefs"
216
- }
217
- ]
218
- },
219
- "examples": [
220
- {
221
- "input": {
222
- "cardId": "card_sandbox_virtual00001",
223
- "tenantId": "ten_sandbox_cards000001"
224
- },
225
- "name": "activate_virtual_card"
226
- }
227
- ],
228
- "moves": [],
229
- "requiresRefs": [
230
- {
231
- "field": "cardholderId",
232
- "statuses": [
233
- "active"
234
- ]
235
- }
236
- ],
237
- "steps": [],
238
- "summary": "Activate a card"
239
- },
240
- "cancel": {
241
- "agentDescription": "Permanently retire the card. This does not reverse: a canceled card never authorizes again and replacing it means issuing a new card. Posted transactions stay in its history.",
242
- "description": "Permanently stops the virtual card. Existing posted transactions remain part of its history.",
243
- "examples": [
244
- {
245
- "input": {
246
- "cardId": "card_sandbox_virtual00001",
247
- "tenantId": "ten_sandbox_cards000001"
248
- },
249
- "name": "cancel_virtual_card"
250
- }
251
- ],
252
- "moves": [],
253
- "steps": [],
254
- "summary": "Cancel a card"
255
- },
256
- "create": {
257
- "agentDescription": "Issue a new virtual card. The cardholder must already exist and be active, and the funding account must be a customer balance account in the card currency. All three spend limits are required: single purchase, daily, and monthly.",
258
- "description": "Issues a virtual card to one active cardholder and binds its spend controls and funding account.",
259
- "effects": {
260
- "reads": [
261
- {
262
- "signature": "reads.requires_refs",
263
- "source": "requiresRefs"
264
- }
265
- ]
266
- },
267
- "eventName": "card.issued",
268
- "examples": [
269
- {
270
- "input": {
271
- "accountId": "acct_sandbox_cardfund0001",
272
- "cardholderId": "chd_sandbox_customer0001",
273
- "currency": "SAR",
274
- "label": "Primary virtual card",
275
- "productId": "prd_sandbox_cards000001",
276
- "spendControls": {
277
- "allowedCountries": [
278
- "SA"
279
- ],
280
- "allowedMerchantCategories": [
281
- "retail",
282
- "travel",
283
- "lodging"
284
- ],
285
- "dailyLimit": "100000",
286
- "monthlyLimit": "500000",
287
- "singlePurchaseLimit": "50000"
288
- },
289
- "tenantId": "ten_sandbox_cards000001"
290
- },
291
- "name": "issue_controlled_virtual_card"
292
- }
293
- ],
294
- "moves": [],
295
- "requiresRefs": [
296
- {
297
- "field": "cardholderId",
298
- "statuses": [
299
- "active"
300
- ]
301
- }
302
- ],
303
- "steps": [],
304
- "summary": "Issue a card"
305
- },
306
- "freeze": {
307
- "agentDescription": "Stop new authorizations without destroying the card or its history. Use this for a reversible hold, such as a suspected compromise. Only an active card can freeze.",
308
- "description": "Stops new authorizations while preserving the card and its history.",
309
- "examples": [
310
- {
311
- "input": {
312
- "cardId": "card_sandbox_virtual00001",
313
- "tenantId": "ten_sandbox_cards000001"
314
- },
315
- "name": "freeze_virtual_card"
316
- }
317
- ],
318
- "moves": [],
319
- "steps": [],
320
- "summary": "Freeze a card"
321
- },
322
- "unfreeze": {
323
- "agentDescription": "Return a frozen card to active so it authorizes again. Use this once the reason for the freeze clears. Only a frozen card can unfreeze.",
324
- "description": "Restores authorization after a temporary freeze.",
325
- "effects": {
326
- "reads": [
327
- {
328
- "signature": "reads.requires_refs",
329
- "source": "requiresRefs"
330
- }
331
- ]
332
- },
333
- "eventName": "card.unfrozen",
334
- "examples": [
335
- {
336
- "input": {
337
- "cardId": "card_sandbox_virtual00001",
338
- "tenantId": "ten_sandbox_cards000001"
339
- },
340
- "name": "unfreeze_virtual_card"
341
- }
342
- ],
343
- "moves": [],
344
- "requiresRefs": [
345
- {
346
- "field": "cardholderId",
347
- "statuses": [
348
- "active"
349
- ]
350
- }
351
- ],
352
- "steps": [],
353
- "summary": "Unfreeze a card"
354
- }
355
- },
356
- "agentDescription": "Reach for card when the caller wants to issue a virtual payment card to an existing cardholder, or to freeze, unfreeze, and cancel one. Spend controls are declarative limits stored on the card. Authorizations and postings against the card are separate instruments.",
357
- "callerParkedStates": {
358
- "active": "a live card stays usable until the holder or issuer freezes or cancels it",
359
- "frozen": "unfreezing or canceling a frozen card is a deliberate holder or issuer act",
360
- "issued": "activation is the cardholder's own act"
361
- },
362
- "description": "A card is issued to one active cardholder, activates for spending, can be frozen and unfrozen without replacement, and is canceled permanently. Spend controls remain declarative data on the card.",
363
- "fields": {
364
- "accountId": {
365
- "description": "Hyperscale account ID",
366
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
367
- "type": "string",
368
- "x-hyperscale-reference-filter": {
369
- "column": "role",
370
- "values": [
371
- "customer_balance"
372
- ]
373
- }
374
- },
375
- "cardholderId": {
376
- "description": "Active cardholder receiving this card",
377
- "pattern": "^chd_(sandbox|live)_[a-z0-9]{8,64}$",
378
- "type": "string"
379
- },
380
- "currency": {
381
- "description": "ISO 4217 currency code",
382
- "maxLength": 3,
383
- "minLength": 3,
384
- "pattern": "^[A-Z]{3}$",
385
- "type": "string"
386
- },
387
- "label": {
388
- "maxLength": 80,
389
- "minLength": 1,
390
- "type": "string"
391
- },
392
- "spendControls": {
393
- "additionalProperties": false,
394
- "properties": {
395
- "allowedCountries": {
396
- "items": {
397
- "description": "ISO 3166-1 alpha-2 country code",
398
- "maxLength": 2,
399
- "minLength": 2,
400
- "pattern": "^[A-Z]{2}$",
401
- "type": "string"
402
- },
403
- "maxItems": 64,
404
- "type": "array"
405
- },
406
- "allowedMerchantCategories": {
407
- "items": {
408
- "pattern": "^[a-z][a-z0-9_]{1,79}$",
409
- "type": "string"
410
- },
411
- "maxItems": 64,
412
- "type": "array"
413
- },
414
- "dailyLimit": {
415
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
416
- "pattern": "^[1-9][0-9]{0,17}$",
417
- "type": "string"
418
- },
419
- "monthlyLimit": {
420
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
421
- "pattern": "^[1-9][0-9]{0,17}$",
422
- "type": "string"
423
- },
424
- "singlePurchaseLimit": {
425
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
426
- "pattern": "^[1-9][0-9]{0,17}$",
427
- "type": "string"
428
- }
429
- },
430
- "required": [
431
- "singlePurchaseLimit",
432
- "dailyLimit",
433
- "monthlyLimit"
434
- ],
435
- "type": "object"
436
- }
437
- },
438
- "id": "card",
439
- "idPrefix": "card",
440
- "lifecycle": {
441
- "initial": "issued",
442
- "states": [
443
- "issued",
444
- "active",
445
- "frozen",
446
- "canceled"
447
- ],
448
- "transitions": {
449
- "activate": {
450
- "from": [
451
- "issued"
452
- ],
453
- "to": "active"
454
- },
455
- "cancel": {
456
- "from": [
457
- "issued",
458
- "active",
459
- "frozen"
460
- ],
461
- "to": "canceled"
462
- },
463
- "freeze": {
464
- "from": [
465
- "active"
466
- ],
467
- "to": "frozen"
468
- },
469
- "unfreeze": {
470
- "from": [
471
- "frozen"
472
- ],
473
- "to": "active"
474
- }
475
- }
476
- },
477
- "nav": [
478
- "Blueprints",
479
- "Cards"
480
- ],
481
- "parties": {
482
- "payer": "accountId"
483
- },
484
- "required": [
485
- "cardholderId",
486
- "accountId",
487
- "currency",
488
- "label",
489
- "spendControls"
490
- ],
491
- "summary": "Virtual payment card bound to a cardholder account.",
492
- "templateId": "wallet_cards",
493
- "title": "Card",
494
- "update": {
495
- "examples": [
496
- {
497
- "input": {
498
- "cardId": "card_sandbox_virtual00001",
499
- "label": "Travel card",
500
- "spendControls": {
501
- "allowedCountries": [
502
- "SA",
503
- "AE"
504
- ],
505
- "allowedMerchantCategories": [
506
- "travel",
507
- "lodging"
508
- ],
509
- "dailyLimit": "50000",
510
- "monthlyLimit": "200000",
511
- "singlePurchaseLimit": "25000"
512
- },
513
- "tenantId": "ten_sandbox_cards000001"
514
- },
515
- "name": "tighten_virtual_card_controls"
516
- }
517
- ],
518
- "fields": [
519
- "label",
520
- "spendControls"
521
- ],
522
- "states": [
523
- "issued",
524
- "active",
525
- "frozen"
526
- ]
527
- }
528
- },
529
- {
530
- "actionOrder": [
531
- "create",
532
- "approve",
533
- "capture",
534
- "decline",
535
- "reverse",
536
- "expire"
537
- ],
538
- "actions": {
539
- "approve": {
540
- "agentDescription": "Ask the card policy for a just-in-time verdict and reserve the requested amount on the card account. Only a pending authorization can approve, and the card must still be active. A policy that misses the deadline declines by default. The reserve holds money, it does not settle it.",
541
- "decision": {
542
- "capability": "banking_or_card_issuing",
543
- "deadlineMs": 1500,
544
- "onTimeout": "decline"
545
- },
546
- "description": "Asks the configured card policy for a just-in-time decision and reserves the immutable authorization amount when approved.",
547
- "effects": {
548
- "decides": [
549
- {
550
- "signature": "decides.banking_or_card_issuing",
551
- "source": "decision"
552
- }
553
- ],
554
- "holds": [
555
- {
556
- "signature": "holds.reserve",
557
- "source": "moves[0]"
558
- }
559
- ],
560
- "moves": [
561
- {
562
- "signature": "moves.transfer.internal",
563
- "source": "moves[0]"
564
- }
565
- ],
566
- "reads": [
567
- {
568
- "signature": "reads.requires_refs",
569
- "source": "requiresRefs"
570
- }
571
- ]
572
- },
573
- "examples": [
574
- {
575
- "input": {
576
- "cardAuthorizationId": "cau_sandbox_purchase00001",
577
- "tenantId": "ten_sandbox_cards000001"
578
- },
579
- "name": "approve_authorization_after_jit_decision"
580
- }
581
- ],
582
- "moves": [
583
- {
584
- "bind": {
585
- "amount": {
586
- "from": "instance",
587
- "path": "fields.amount"
588
- },
589
- "currency": {
590
- "from": "instance",
591
- "path": "fields.currency"
592
- },
593
- "destinationAccountId": {
594
- "from": "instance",
595
- "path": "fields.settlementAccountId"
596
- },
597
- "expiresAt": {
598
- "from": "instance",
599
- "path": "fields.expiresAt"
600
- },
601
- "memo": {
602
- "from": "const",
603
- "value": "Card authorization hold"
604
- },
605
- "sourceAccountId": {
606
- "from": "instance",
607
- "path": "fields.cardAccountId"
608
- }
609
- },
610
- "capture": {
611
- "authorizationTransferId": "transferId"
612
- },
613
- "key": "transfer",
614
- "operation": "internal_transfer.reserve"
615
- }
616
- ],
617
- "requiresRefs": [
618
- {
619
- "field": "cardId",
620
- "statuses": [
621
- "active"
622
- ]
623
- }
624
- ],
625
- "steps": [],
626
- "summary": "Approve a card authorization"
627
- },
628
- "capture": {
629
- "agentDescription": "Post the reserved hold once the merchant completes the purchase. Only an approved authorization can capture and the hold must still exist. Capture settles money and does not reverse. Record the settled purchase afterwards with card transaction create.",
630
- "description": "Posts the reserved transfer after the merchant completes the purchase.",
631
- "earnable": true,
632
- "effects": {
633
- "moves": [
634
- {
635
- "signature": "moves.transfer.internal",
636
- "source": "moves[0]"
637
- }
638
- ]
639
- },
640
- "examples": [
641
- {
642
- "input": {
643
- "cardAuthorizationId": "cau_sandbox_purchase00001",
644
- "tenantId": "ten_sandbox_cards000001"
645
- },
646
- "name": "capture_completed_purchase"
647
- }
648
- ],
649
- "moves": [
650
- {
651
- "bind": {
652
- "transferId": {
653
- "from": "instance",
654
- "path": "refs.authorizationTransferId"
655
- }
656
- },
657
- "key": "transfer",
658
- "operation": "internal_transfer.post"
659
- }
660
- ],
661
- "steps": [],
662
- "summary": "Capture a card authorization"
663
- },
664
- "create": {
665
- "agentDescription": "Record one pending merchant request against a card. The card must already be active. The caller supplies the amount, currency, merchant name, category, country, reference, and an expiry moment for the hold. No money is held yet. Approve places the hold.",
666
- "description": "Records one pending merchant request against an active virtual card. No money is held before approval.",
667
- "effects": {
668
- "reads": [
669
- {
670
- "signature": "reads.requires_refs",
671
- "source": "requiresRefs"
672
- }
673
- ]
674
- },
675
- "eventName": "card_authorization.requested",
676
- "examples": [
677
- {
678
- "input": {
679
- "amount": "12500",
680
- "cardAccountId": "acct_sandbox_cardfund0001",
681
- "cardId": "card_sandbox_virtual00001",
682
- "currency": "SAR",
683
- "expiresAt": "2026-07-16T12:00:00.000Z",
684
- "merchantCategory": "electronics",
685
- "merchantCountry": "SA",
686
- "merchantName": "Riyadh Camera Store",
687
- "merchantReference": "merchant-order-1042",
688
- "productId": "prd_sandbox_cards000001",
689
- "settlementAccountId": "acct_sandbox_merchant0001",
690
- "tenantId": "ten_sandbox_cards000001"
691
- },
692
- "name": "request_retail_authorization"
693
- }
694
- ],
695
- "moves": [],
696
- "requiresRefs": [
697
- {
698
- "field": "cardId",
699
- "statuses": [
700
- "active"
701
- ]
702
- }
703
- ],
704
- "steps": [],
705
- "summary": "Request a card authorization"
706
- },
707
- "decline": {
708
- "agentDescription": "Close a pending request without placing any hold. Use this when the card policy refuses the purchase. Only a pending authorization can decline, and a declined one never captures.",
709
- "description": "Closes a pending request without placing a hold after a declined card-policy decision.",
710
- "examples": [
711
- {
712
- "input": {
713
- "cardAuthorizationId": "cau_sandbox_purchase00001",
714
- "tenantId": "ten_sandbox_cards000001"
715
- },
716
- "name": "decline_rejected_authorization"
717
- }
718
- ],
719
- "moves": [],
720
- "steps": [],
721
- "summary": "Decline a card authorization"
722
- },
723
- "expire": {
724
- "description": "Voids an approved hold at its declared expiry under the machine principal.",
725
- "due": {
726
- "field": "expiresAt"
727
- },
728
- "effects": {
729
- "moves": [
730
- {
731
- "signature": "moves.transfer.internal",
732
- "source": "moves[0]"
733
- }
734
- ],
735
- "schedules": [
736
- {
737
- "signature": "schedules.due",
738
- "source": "due"
739
- }
740
- ]
741
- },
742
- "examples": [
743
- {
744
- "input": {
745
- "cardAuthorizationId": "cau_sandbox_purchase00001",
746
- "tenantId": "ten_sandbox_cards000001"
747
- },
748
- "name": "expire_uncaptured_authorization"
749
- }
750
- ],
751
- "moves": [
752
- {
753
- "bind": {
754
- "reason": {
755
- "from": "const",
756
- "value": "Card authorization expired"
757
- },
758
- "transferId": {
759
- "from": "instance",
760
- "path": "refs.authorizationTransferId"
761
- }
762
- },
763
- "key": "transfer",
764
- "operation": "internal_transfer.void"
765
- }
766
- ],
767
- "steps": [],
768
- "summary": "Expire a card authorization"
769
- },
770
- "reverse": {
771
- "agentDescription": "Void an approved hold before capture and release the reserved funds back to the card account. Only an approved authorization can reverse. This is terminal, so the authorization never captures afterwards.",
772
- "description": "Voids an approved hold before capture and releases the card funds.",
773
- "effects": {
774
- "moves": [
775
- {
776
- "signature": "moves.transfer.internal",
777
- "source": "moves[0]"
778
- }
779
- ]
780
- },
781
- "examples": [
782
- {
783
- "input": {
784
- "cardAuthorizationId": "cau_sandbox_purchase00001",
785
- "tenantId": "ten_sandbox_cards000001"
786
- },
787
- "name": "reverse_uncaptured_authorization"
788
- }
789
- ],
790
- "moves": [
791
- {
792
- "bind": {
793
- "reason": {
794
- "from": "const",
795
- "value": "Card authorization reversed"
796
- },
797
- "transferId": {
798
- "from": "instance",
799
- "path": "refs.authorizationTransferId"
800
- }
801
- },
802
- "key": "transfer",
803
- "operation": "internal_transfer.void"
804
- }
805
- ],
806
- "steps": [],
807
- "summary": "Reverse a card authorization"
808
- }
809
- },
810
- "agentDescription": "Reach for card authorization when a merchant asks whether one card purchase may go ahead. Approve asks the card policy for a just-in-time verdict and reserves the amount as a hold on the card account. The settled purchase record and any refund live in card transaction, and chargebacks live in card dispute.",
811
- "callerParkedStates": {
812
- "pending": "the approve or decline verdict arrives from the card network's decision flow"
813
- },
814
- "description": "A card authorization starts pending, asks the configured card policy for an immediate decision, reserves the approved amount, and then either captures the hold, reverses it, or expires it. Declined requests never hold money.",
815
- "dials": [
816
- {
817
- "field": "expiresAt",
818
- "key": "authorization_window",
819
- "kind": "window",
820
- "maxOffset": "P30D",
821
- "summary": "Grace beyond the authorization expiry timestamp before an uncaptured hold expires.",
822
- "title": "Authorization window"
823
- },
824
- {
825
- "action": "approve",
826
- "key": "policy_decision_deadline_ms",
827
- "kind": "decision_deadline_ms",
828
- "maxMs": 5000,
829
- "minMs": 500,
830
- "summary": "How long approve waits for the card policy's just-in-time decision before the timeout default declines.",
831
- "title": "Policy decision deadline"
832
- }
833
- ],
834
- "fields": {
835
- "amount": {
836
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
837
- "pattern": "^[1-9][0-9]{0,17}$",
838
- "type": "string"
839
- },
840
- "cardAccountId": {
841
- "description": "Hyperscale account ID",
842
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
843
- "type": "string",
844
- "x-hyperscale-reference-filter": {
845
- "column": "role",
846
- "values": [
847
- "customer_balance"
848
- ]
849
- }
850
- },
851
- "cardId": {
852
- "description": "Active card presented for this authorization",
853
- "pattern": "^card_(sandbox|live)_[a-z0-9]{8,64}$",
854
- "type": "string"
855
- },
856
- "currency": {
857
- "description": "ISO 4217 currency code",
858
- "maxLength": 3,
859
- "minLength": 3,
860
- "pattern": "^[A-Z]{3}$",
861
- "type": "string"
862
- },
863
- "expiresAt": {
864
- "format": "hyperscale-date-time",
865
- "type": "string"
866
- },
867
- "merchantCategory": {
868
- "pattern": "^[a-z][a-z0-9_]{1,79}$",
869
- "type": "string"
870
- },
871
- "merchantCountry": {
872
- "description": "ISO 3166-1 alpha-2 country code",
873
- "maxLength": 2,
874
- "minLength": 2,
875
- "pattern": "^[A-Z]{2}$",
876
- "type": "string"
877
- },
878
- "merchantName": {
879
- "maxLength": 120,
880
- "minLength": 1,
881
- "type": "string"
882
- },
883
- "merchantReference": {
884
- "maxLength": 120,
885
- "minLength": 1,
886
- "type": "string"
887
- },
888
- "settlementAccountId": {
889
- "description": "Hyperscale account ID",
890
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
891
- "type": "string",
892
- "x-hyperscale-reference-filter": {
893
- "column": "role",
894
- "values": [
895
- "customer_balance"
896
- ]
897
- }
898
- }
899
- },
900
- "id": "card_authorization",
901
- "idPrefix": "cau",
902
- "lifecycle": {
903
- "initial": "pending",
904
- "states": [
905
- "pending",
906
- "approved",
907
- "captured",
908
- "declined",
909
- "reversed",
910
- "expired"
911
- ],
912
- "transitions": {
913
- "approve": {
914
- "from": [
915
- "pending"
916
- ],
917
- "to": "approved"
918
- },
919
- "capture": {
920
- "from": [
921
- "approved"
922
- ],
923
- "to": "captured"
924
- },
925
- "decline": {
926
- "from": [
927
- "pending"
928
- ],
929
- "to": "declined"
930
- },
931
- "expire": {
932
- "from": [
933
- "approved"
934
- ],
935
- "to": "expired"
936
- },
937
- "reverse": {
938
- "from": [
939
- "approved"
940
- ],
941
- "to": "reversed"
942
- }
943
- }
944
- },
945
- "nav": [
946
- "Blueprints",
947
- "Card authorizations"
948
- ],
949
- "parties": {
950
- "beneficiary": "settlementAccountId",
951
- "payer": "cardAccountId"
952
- },
953
- "required": [
954
- "cardId",
955
- "cardAccountId",
956
- "settlementAccountId",
957
- "amount",
958
- "currency",
959
- "merchantName",
960
- "merchantCategory",
961
- "merchantCountry",
962
- "merchantReference",
963
- "expiresAt"
964
- ],
965
- "summary": "Just-in-time decision and hold for one card purchase.",
966
- "templateId": "wallet_cards",
967
- "title": "Card authorization"
968
- },
969
- {
970
- "actionOrder": [
971
- "create",
972
- "refund"
973
- ],
974
- "actions": {
975
- "create": {
976
- "agentDescription": "Record the posted purchase for one captured authorization. The authorization must be in the captured state and must not already have a transaction. Amount, currency, card, merchant reference, and the account pair come from the authorization. The caller supplies only the posted moment.",
977
- "description": "Records the posted purchase produced by one captured authorization. The amount, currency, card, and account pair are derived from the locked captured authorization -- never caller-supplied -- and each authorization settles into at most one transaction.",
978
- "effects": {
979
- "reads": [
980
- {
981
- "signature": "reads.requires_refs",
982
- "source": "requiresRefs"
983
- }
984
- ]
985
- },
986
- "eventName": "card_transaction.posted",
987
- "examples": [
988
- {
989
- "input": {
990
- "cardAuthorizationId": "cau_sandbox_purchase00001",
991
- "postedAt": "2026-07-10T12:05:00.000Z",
992
- "productId": "prd_sandbox_cards000001",
993
- "tenantId": "ten_sandbox_cards000001"
994
- },
995
- "name": "record_captured_card_purchase"
996
- }
997
- ],
998
- "moves": [],
999
- "requiresRefs": [
1000
- {
1001
- "bind": {
1002
- "amount": "fields.amount",
1003
- "cardAccountId": "fields.cardAccountId",
1004
- "cardId": "fields.cardId",
1005
- "currency": "fields.currency",
1006
- "merchantReference": "fields.merchantReference",
1007
- "settlementAccountId": "fields.settlementAccountId"
1008
- },
1009
- "field": "cardAuthorizationId",
1010
- "statuses": [
1011
- "captured"
1012
- ],
1013
- "unique": true
1014
- }
1015
- ],
1016
- "steps": [],
1017
- "summary": "Record a card transaction"
1018
- },
1019
- "refund": {
1020
- "agentDescription": "Return the full posted amount from the settlement account back to the card account and close the transaction as refunded. Only a posted transaction can refund, the amount is always the full one, and a reason string is required. This settles money and is terminal.",
1021
- "description": "Returns the full posted amount from the settlement account to the card account and closes the transaction as refunded.",
1022
- "effects": {
1023
- "moves": [
1024
- {
1025
- "signature": "moves.transfer.internal",
1026
- "source": "moves[0]"
1027
- }
1028
- ]
1029
- },
1030
- "examples": [
1031
- {
1032
- "input": {
1033
- "cardTransactionId": "ctx_sandbox_purchase00001",
1034
- "reason": "Merchant accepted the returned item",
1035
- "tenantId": "ten_sandbox_cards000001"
1036
- },
1037
- "name": "refund_returned_purchase"
1038
- }
1039
- ],
1040
- "input": {
1041
- "additionalProperties": false,
1042
- "properties": {
1043
- "reason": {
1044
- "maxLength": 180,
1045
- "minLength": 1,
1046
- "type": "string"
1047
- }
1048
- },
1049
- "required": [
1050
- "reason"
1051
- ],
1052
- "type": "object"
1053
- },
1054
- "moves": [
1055
- {
1056
- "bind": {
1057
- "amount": {
1058
- "from": "instance",
1059
- "path": "fields.amount"
1060
- },
1061
- "currency": {
1062
- "from": "instance",
1063
- "path": "fields.currency"
1064
- },
1065
- "destinationAccountId": {
1066
- "from": "instance",
1067
- "path": "fields.cardAccountId"
1068
- },
1069
- "memo": {
1070
- "from": "input",
1071
- "path": "reason"
1072
- },
1073
- "productId": {
1074
- "from": "instance",
1075
- "path": "productId"
1076
- },
1077
- "sourceAccountId": {
1078
- "from": "instance",
1079
- "path": "fields.settlementAccountId"
1080
- }
1081
- },
1082
- "capture": {
1083
- "refundTransferId": "transferId"
1084
- },
1085
- "key": "transfer",
1086
- "operation": "internal_transfer.create"
1087
- }
1088
- ],
1089
- "steps": [],
1090
- "summary": "Refund a card transaction"
1091
- }
1092
- },
1093
- "agentDescription": "Reach for card transaction when a captured authorization has settled and the purchase needs a posted record, or when the merchant agrees to return the full amount. Refunds here are full and voluntary. A charge the merchant will not return goes to card dispute.",
1094
- "callerParkedStates": {
1095
- "posted": "posted is the settled resting state; refund is an optional scheme-window follow-up"
1096
- },
1097
- "description": "A card transaction records the settled result of one captured authorization. It remains posted unless the full immutable amount is returned to the card account, after which it is refunded permanently.",
1098
- "fields": {
1099
- "amount": {
1100
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
1101
- "pattern": "^[1-9][0-9]{0,17}$",
1102
- "type": "string"
1103
- },
1104
- "cardAccountId": {
1105
- "description": "Hyperscale account ID",
1106
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1107
- "type": "string",
1108
- "x-hyperscale-reference-filter": {
1109
- "column": "role",
1110
- "values": [
1111
- "customer_balance"
1112
- ]
1113
- }
1114
- },
1115
- "cardAuthorizationId": {
1116
- "description": "Captured authorization settled by this transaction",
1117
- "pattern": "^cau_(sandbox|live)_[a-z0-9]{8,64}$",
1118
- "type": "string"
1119
- },
1120
- "cardId": {
1121
- "description": "Card used for this transaction",
1122
- "pattern": "^card_(sandbox|live)_[a-z0-9]{8,64}$",
1123
- "type": "string"
1124
- },
1125
- "currency": {
1126
- "description": "ISO 4217 currency code",
1127
- "maxLength": 3,
1128
- "minLength": 3,
1129
- "pattern": "^[A-Z]{3}$",
1130
- "type": "string"
1131
- },
1132
- "merchantReference": {
1133
- "maxLength": 120,
1134
- "minLength": 1,
1135
- "type": "string"
1136
- },
1137
- "postedAt": {
1138
- "format": "hyperscale-date-time",
1139
- "type": "string"
1140
- },
1141
- "settlementAccountId": {
1142
- "description": "Hyperscale account ID",
1143
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1144
- "type": "string",
1145
- "x-hyperscale-reference-filter": {
1146
- "column": "role",
1147
- "values": [
1148
- "customer_balance"
1149
- ]
1150
- }
1151
- }
1152
- },
1153
- "id": "card_transaction",
1154
- "idPrefix": "ctx",
1155
- "lifecycle": {
1156
- "initial": "posted",
1157
- "states": [
1158
- "posted",
1159
- "refunded"
1160
- ],
1161
- "transitions": {
1162
- "refund": {
1163
- "from": [
1164
- "posted"
1165
- ],
1166
- "to": "refunded"
1167
- }
1168
- }
1169
- },
1170
- "nav": [
1171
- "Blueprints",
1172
- "Card transactions"
1173
- ],
1174
- "parties": {
1175
- "beneficiary": "settlementAccountId",
1176
- "payer": "cardAccountId"
1177
- },
1178
- "required": [
1179
- "cardAuthorizationId",
1180
- "cardId",
1181
- "cardAccountId",
1182
- "settlementAccountId",
1183
- "amount",
1184
- "currency",
1185
- "merchantReference",
1186
- "postedAt"
1187
- ],
1188
- "summary": "Posted card purchase and its possible full refund.",
1189
- "templateId": "wallet_cards",
1190
- "title": "Card transaction"
1191
- },
1192
- {
1193
- "actionOrder": [
1194
- "create",
1195
- "review",
1196
- "win",
1197
- "lose"
1198
- ],
1199
- "actions": {
1200
- "create": {
1201
- "agentDescription": "File an evidence-backed challenge against one card transaction. The transaction must be posted. The caller supplies the reason code, at least one evidence item, and the response deadline. Amount, currency, card, and the account pair come from the transaction, never from the caller. No money moves at filing.",
1202
- "description": "Files an evidence-backed challenge against one transaction that is still posted. The disputed amount, currency, card, and account pair are derived from the locked transaction -- never caller-supplied.",
1203
- "effects": {
1204
- "reads": [
1205
- {
1206
- "signature": "reads.requires_refs",
1207
- "source": "requiresRefs"
1208
- }
1209
- ]
1210
- },
1211
- "eventName": "card_dispute.filed",
1212
- "examples": [
1213
- {
1214
- "input": {
1215
- "cardTransactionId": "ctx_sandbox_purchase00001",
1216
- "evidence": [
1217
- {
1218
- "kind": "customer_statement",
1219
- "reference": "support-case-2048",
1220
- "submittedAt": "2026-07-11T10:15:00.000Z",
1221
- "summary": "Customer confirms the purchase was not authorized."
1222
- }
1223
- ],
1224
- "productId": "prd_sandbox_cards000001",
1225
- "reason": "unauthorized_purchase",
1226
- "responseDueAt": "2026-08-10T23:59:59.000Z",
1227
- "tenantId": "ten_sandbox_cards000001"
1228
- },
1229
- "name": "file_unauthorized_purchase_dispute"
1230
- }
1231
- ],
1232
- "moves": [],
1233
- "requiresRefs": [
1234
- {
1235
- "bind": {
1236
- "amount": "fields.amount",
1237
- "cardAccountId": "fields.cardAccountId",
1238
- "cardId": "fields.cardId",
1239
- "currency": "fields.currency",
1240
- "settlementAccountId": "fields.settlementAccountId"
1241
- },
1242
- "field": "cardTransactionId",
1243
- "statuses": [
1244
- "posted"
1245
- ]
1246
- }
1247
- ],
1248
- "steps": [],
1249
- "summary": "File a card dispute"
1250
- },
1251
- "lose": {
1252
- "description": "Closes an unresolved dispute without moving money when its response deadline passes.",
1253
- "due": {
1254
- "field": "responseDueAt"
1255
- },
1256
- "effects": {
1257
- "schedules": [
1258
- {
1259
- "signature": "schedules.due",
1260
- "source": "due"
1261
- }
1262
- ]
1263
- },
1264
- "eventName": "card_dispute.lost",
1265
- "examples": [
1266
- {
1267
- "input": {
1268
- "cardDisputeId": "cdis_sandbox_purchase0001",
1269
- "tenantId": "ten_sandbox_cards000001"
1270
- },
1271
- "name": "close_unresolved_dispute_at_deadline"
1272
- }
1273
- ],
1274
- "moves": [],
1275
- "steps": [],
1276
- "summary": "Lose a card dispute"
1277
- },
1278
- "review": {
1279
- "agentDescription": "Move a filed dispute into review once its evidence is ready for an outcome decision. Only a filed dispute can review and no money moves. Evidence can still be added by update while the dispute is filed or under review.",
1280
- "description": "Accepts the filed evidence for an outcome decision before the response deadline.",
1281
- "examples": [
1282
- {
1283
- "input": {
1284
- "cardDisputeId": "cdis_sandbox_purchase0001",
1285
- "tenantId": "ten_sandbox_cards000001"
1286
- },
1287
- "name": "begin_card_dispute_review"
1288
- }
1289
- ],
1290
- "moves": [],
1291
- "steps": [],
1292
- "summary": "Review a card dispute"
1293
- },
1294
- "win": {
1295
- "agentDescription": "Ask the card policy for the final outcome and return the disputed amount from the settlement account to the card account when the cardholder wins. Only a dispute under review can win, and the challenged transaction must still be posted. This settles money and is terminal.",
1296
- "decision": {
1297
- "capability": "banking_or_card_issuing",
1298
- "deadlineMs": 15000,
1299
- "onTimeout": "decline"
1300
- },
1301
- "description": "Asks the configured card policy for the final outcome and returns the disputed amount when the cardholder wins.",
1302
- "effects": {
1303
- "decides": [
1304
- {
1305
- "signature": "decides.banking_or_card_issuing",
1306
- "source": "decision"
1307
- }
1308
- ],
1309
- "moves": [
1310
- {
1311
- "signature": "moves.transfer.internal",
1312
- "source": "moves[0]"
1313
- }
1314
- ],
1315
- "reads": [
1316
- {
1317
- "signature": "reads.requires_refs",
1318
- "source": "requiresRefs"
1319
- }
1320
- ]
1321
- },
1322
- "eventName": "card_dispute.won",
1323
- "examples": [
1324
- {
1325
- "input": {
1326
- "cardDisputeId": "cdis_sandbox_purchase0001",
1327
- "tenantId": "ten_sandbox_cards000001"
1328
- },
1329
- "name": "return_won_dispute_amount"
1330
- }
1331
- ],
1332
- "moves": [
1333
- {
1334
- "bind": {
1335
- "amount": {
1336
- "from": "instance",
1337
- "path": "fields.amount"
1338
- },
1339
- "currency": {
1340
- "from": "instance",
1341
- "path": "fields.currency"
1342
- },
1343
- "destinationAccountId": {
1344
- "from": "instance",
1345
- "path": "fields.cardAccountId"
1346
- },
1347
- "memo": {
1348
- "from": "const",
1349
- "value": "Card dispute won"
1350
- },
1351
- "productId": {
1352
- "from": "instance",
1353
- "path": "productId"
1354
- },
1355
- "sourceAccountId": {
1356
- "from": "instance",
1357
- "path": "fields.settlementAccountId"
1358
- }
1359
- },
1360
- "capture": {
1361
- "disputeTransferId": "transferId"
1362
- },
1363
- "key": "transfer",
1364
- "operation": "internal_transfer.create"
1365
- }
1366
- ],
1367
- "requiresRefs": [
1368
- {
1369
- "field": "cardTransactionId",
1370
- "statuses": [
1371
- "posted"
1372
- ]
1373
- }
1374
- ],
1375
- "steps": [],
1376
- "summary": "Win a card dispute"
1377
- }
1378
- },
1379
- "agentDescription": "Reach for card dispute when the cardholder challenges one already-posted card transaction. The disputed amount, card, and both accounts are copied from the locked transaction, so the caller supplies only the reason, evidence, and response deadline. A refund the merchant agrees to is card transaction refund instead.",
1380
- "description": "A card dispute is filed with evidence against one posted transaction, enters review, and ends won or lost. A win returns the immutable disputed amount to the card account; an unresolved case is lost at its response deadline.",
1381
- "dials": [
1382
- {
1383
- "field": "responseDueAt",
1384
- "key": "response_window",
1385
- "kind": "window",
1386
- "maxOffset": "P90D",
1387
- "summary": "Grace beyond the response deadline before an unresolved dispute closes as lost.",
1388
- "title": "Response window"
1389
- },
1390
- {
1391
- "action": "win",
1392
- "key": "outcome_decision_deadline_ms",
1393
- "kind": "decision_deadline_ms",
1394
- "minMs": 1000,
1395
- "summary": "How long win waits for the card policy's final outcome before the timeout default declines.",
1396
- "title": "Outcome decision deadline"
1397
- }
1398
- ],
1399
- "fields": {
1400
- "amount": {
1401
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
1402
- "pattern": "^[1-9][0-9]{0,17}$",
1403
- "type": "string"
1404
- },
1405
- "cardAccountId": {
1406
- "description": "Hyperscale account ID",
1407
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1408
- "type": "string",
1409
- "x-hyperscale-reference-filter": {
1410
- "column": "role",
1411
- "values": [
1412
- "customer_balance"
1413
- ]
1414
- }
1415
- },
1416
- "cardId": {
1417
- "description": "Card whose transaction is challenged",
1418
- "pattern": "^card_(sandbox|live)_[a-z0-9]{8,64}$",
1419
- "type": "string"
1420
- },
1421
- "cardTransactionId": {
1422
- "description": "Posted card transaction challenged by this dispute",
1423
- "pattern": "^ctx_(sandbox|live)_[a-z0-9]{8,64}$",
1424
- "type": "string"
1425
- },
1426
- "currency": {
1427
- "description": "ISO 4217 currency code",
1428
- "maxLength": 3,
1429
- "minLength": 3,
1430
- "pattern": "^[A-Z]{3}$",
1431
- "type": "string"
1432
- },
1433
- "evidence": {
1434
- "items": {
1435
- "additionalProperties": false,
1436
- "properties": {
1437
- "kind": {
1438
- "pattern": "^[a-z][a-z0-9_]{1,79}$",
1439
- "type": "string"
1440
- },
1441
- "reference": {
1442
- "maxLength": 180,
1443
- "minLength": 1,
1444
- "type": "string"
1445
- },
1446
- "submittedAt": {
1447
- "format": "hyperscale-date-time",
1448
- "type": "string"
1449
- },
1450
- "summary": {
1451
- "maxLength": 1000,
1452
- "minLength": 1,
1453
- "type": "string"
1454
- }
1455
- },
1456
- "required": [
1457
- "kind",
1458
- "summary",
1459
- "submittedAt"
1460
- ],
1461
- "type": "object"
1462
- },
1463
- "maxItems": 20,
1464
- "minItems": 1,
1465
- "type": "array"
1466
- },
1467
- "reason": {
1468
- "pattern": "^[a-z][a-z0-9_]{1,79}$",
1469
- "type": "string"
1470
- },
1471
- "responseDueAt": {
1472
- "format": "hyperscale-date-time",
1473
- "type": "string"
1474
- },
1475
- "settlementAccountId": {
1476
- "description": "Hyperscale account ID",
1477
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1478
- "type": "string",
1479
- "x-hyperscale-reference-filter": {
1480
- "column": "role",
1481
- "values": [
1482
- "customer_balance"
1483
- ]
1484
- }
1485
- }
1486
- },
1487
- "id": "card_dispute",
1488
- "idPrefix": "cdis",
1489
- "lifecycle": {
1490
- "initial": "filed",
1491
- "states": [
1492
- "filed",
1493
- "under_review",
1494
- "won",
1495
- "lost"
1496
- ],
1497
- "transitions": {
1498
- "lose": {
1499
- "from": [
1500
- "filed",
1501
- "under_review"
1502
- ],
1503
- "to": "lost"
1504
- },
1505
- "review": {
1506
- "from": [
1507
- "filed"
1508
- ],
1509
- "to": "under_review"
1510
- },
1511
- "win": {
1512
- "from": [
1513
- "under_review"
1514
- ],
1515
- "to": "won"
1516
- }
1517
- }
1518
- },
1519
- "nav": [
1520
- "Blueprints",
1521
- "Card disputes"
1522
- ],
1523
- "parties": {
1524
- "beneficiary": "cardAccountId",
1525
- "payer": "settlementAccountId"
1526
- },
1527
- "required": [
1528
- "cardTransactionId",
1529
- "cardId",
1530
- "cardAccountId",
1531
- "settlementAccountId",
1532
- "amount",
1533
- "currency",
1534
- "reason",
1535
- "evidence",
1536
- "responseDueAt"
1537
- ],
1538
- "summary": "Evidence-backed challenge to one posted card transaction.",
1539
- "templateId": "wallet_cards",
1540
- "title": "Card dispute",
1541
- "update": {
1542
- "examples": [
1543
- {
1544
- "input": {
1545
- "cardDisputeId": "cdis_sandbox_purchase0001",
1546
- "evidence": [
1547
- {
1548
- "kind": "customer_statement",
1549
- "reference": "support-case-2048",
1550
- "submittedAt": "2026-07-11T10:15:00.000Z",
1551
- "summary": "Customer confirms the purchase was not authorized."
1552
- },
1553
- {
1554
- "kind": "merchant_correspondence",
1555
- "submittedAt": "2026-07-12T09:30:00.000Z",
1556
- "summary": "Merchant could not produce proof of delivery."
1557
- }
1558
- ],
1559
- "tenantId": "ten_sandbox_cards000001"
1560
- },
1561
- "name": "add_card_dispute_evidence"
1562
- }
1563
- ],
1564
- "fields": [
1565
- "evidence"
1566
- ],
1567
- "states": [
1568
- "filed",
1569
- "under_review"
1570
- ]
1571
- }
1572
- }
1573
- ],
1574
- "product": "cards",
1575
- "subjects": [],
1576
- "title": "Cards",
1577
- "udl": 1,
1578
- "version": 1
1579
- }