@hyperscale0/udl 1.0.0-beta.1 → 1.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.
- package/CHANGELOG.md +78 -25
- package/README.md +37 -99
- package/conformance/README.md +44 -41
- package/conformance/evolution/action-contract.expected.json +10 -0
- package/conformance/evolution/action-contract.live.udl +44 -0
- package/conformance/evolution/action-contract.next.udl +45 -0
- package/conformance/evolution/product-identity.expected.json +10 -0
- package/conformance/evolution/product-identity.live.udl +55 -0
- package/conformance/evolution/product-identity.next.udl +55 -0
- package/conformance/evolution/version-required.expected.json +10 -0
- package/conformance/evolution/version-required.live.udl +55 -0
- package/conformance/evolution/version-required.next.udl +58 -0
- package/conformance/invalid/action-without-transition.expected.json +10 -0
- package/conformance/invalid/{verb-without-transition.udl → action-without-transition.udl} +7 -2
- package/conformance/invalid/agent-description-too-long.expected.json +10 -0
- package/conformance/invalid/agent-description-too-long.udl +57 -0
- package/conformance/invalid/blank-title.expected.json +1 -1
- package/conformance/invalid/blank-title.udl +6 -2
- package/conformance/invalid/composition-dial-duplicate-key.expected.json +10 -0
- package/conformance/invalid/composition-dial-duplicate-key.udl +73 -0
- package/conformance/invalid/depth-budget.expected.json +1 -1
- package/conformance/invalid/duplicate-subject.expected.json +10 -0
- package/conformance/invalid/duplicate-subject.udl +230 -0
- package/conformance/invalid/forged-effects.expected.json +10 -0
- package/conformance/invalid/forged-effects.udl +76 -0
- package/conformance/invalid/format-version.expected.json +1 -1
- package/conformance/invalid/format-version.udl +6 -2
- package/conformance/invalid/instrument-id-not-snake-case.expected.json +10 -0
- package/conformance/invalid/{noun-id-not-snake-case.udl → instrument-id-not-snake-case.udl} +6 -2
- package/conformance/invalid/invalid-aggregate-gate-shape.expected.json +10 -0
- package/conformance/invalid/invalid-aggregate-gate-shape.udl +1819 -0
- package/conformance/invalid/invalid-check-duration.expected.json +10 -0
- package/conformance/invalid/invalid-check-duration.udl +219 -0
- package/conformance/invalid/invalid-dial-anchor.expected.json +10 -0
- package/conformance/invalid/invalid-dial-anchor.udl +219 -0
- package/conformance/invalid/invalid-exception-parent-ref.expected.json +10 -0
- package/conformance/invalid/invalid-exception-parent-ref.udl +2487 -0
- package/conformance/invalid/invalid-exposure-shape.expected.json +10 -0
- package/conformance/invalid/invalid-exposure-shape.udl +1819 -0
- package/conformance/invalid/invalid-remainder.expected.json +10 -0
- package/conformance/invalid/invalid-remainder.udl +220 -0
- package/conformance/invalid/invalid-schema-keyword.expected.json +10 -0
- package/conformance/invalid/invalid-schema-keyword.udl +220 -0
- package/conformance/invalid/invalid-utf8.expected.json +1 -1
- package/conformance/invalid/malformed-json.expected.json +1 -1
- package/conformance/invalid/missing-create-action.expected.json +10 -0
- package/conformance/invalid/{missing-create-verb.udl → missing-create-action.udl} +5 -2
- package/conformance/invalid/missing-exception-amount-field.expected.json +10 -0
- package/conformance/invalid/missing-exception-amount-field.udl +2487 -0
- package/conformance/invalid/missing-exception-contract.expected.json +14 -0
- package/conformance/invalid/missing-exception-contract.udl +2523 -0
- package/conformance/invalid/missing-exception-reason-field.expected.json +10 -0
- package/conformance/invalid/missing-exception-reason-field.udl +2487 -0
- package/conformance/invalid/not-an-object.expected.json +1 -1
- package/conformance/invalid/payout-reconcile-not-a-bank-debit.expected.json +10 -0
- package/conformance/invalid/payout-reconcile-not-a-bank-debit.udl +259 -0
- package/conformance/invalid/quote-freeze-set-incomplete.expected.json +10 -0
- package/conformance/invalid/quote-freeze-set-incomplete.udl +261 -0
- package/conformance/invalid/quote-named-reference-gate.expected.json +10 -0
- package/conformance/invalid/quote-named-reference-gate.udl +50 -0
- package/conformance/invalid/reconcile-named-reference-gate.expected.json +10 -0
- package/conformance/invalid/reconcile-named-reference-gate.udl +50 -0
- package/conformance/invalid/unknown-key.expected.json +1 -1
- package/conformance/invalid/unknown-key.udl +6 -2
- package/conformance/invalid/unknown-reference-gate-field.expected.json +10 -0
- package/conformance/invalid/unknown-reference-gate-field.udl +1819 -0
- package/conformance/invalid/unknown-required-field.expected.json +10 -0
- package/conformance/invalid/unknown-required-field.udl +220 -0
- package/conformance/invalid/unreachable-state.expected.json +2 -2
- package/conformance/invalid/unreachable-state.udl +6 -2
- package/conformance/invalid/wrong-exception-amount-field.expected.json +10 -0
- package/conformance/invalid/wrong-exception-amount-field.udl +2487 -0
- package/conformance/invalid/wrong-exception-reason-field.expected.json +10 -0
- package/conformance/invalid/wrong-exception-reason-field.udl +2487 -0
- package/conformance/valid/agent-description.expected.json +6 -0
- package/conformance/valid/agent-description.udl +66 -0
- package/conformance/valid/cards.expected.json +1 -0
- package/conformance/valid/cards.udl +843 -356
- package/conformance/valid/commerce-escrow.expected.json +1 -0
- package/conformance/valid/commerce-escrow.udl +792 -291
- package/conformance/valid/compiled-crowdfunding.expected.json +6 -0
- package/conformance/valid/compiled-crowdfunding.udl +1843 -0
- package/conformance/valid/compiled-watch-club.expected.json +6 -0
- package/conformance/valid/compiled-watch-club.udl +2486 -0
- package/conformance/valid/complete-contract.expected.json +6 -0
- package/conformance/valid/complete-contract.udl +218 -0
- package/conformance/valid/effect-signatures.expected.json +6 -0
- package/conformance/valid/effect-signatures.udl +75 -0
- package/conformance/valid/hand-edited.expected.json +1 -0
- package/conformance/valid/hand-edited.udl +1 -1
- package/conformance/valid/insured-car-marketplace.expected.json +1 -0
- package/conformance/valid/insured-car-marketplace.udl +534 -315
- package/conformance/valid/insured-travel.expected.json +2 -1
- package/conformance/valid/insured-travel.udl +1489 -641
- package/conformance/valid/minimal.expected.json +1 -0
- package/conformance/valid/minimal.udl +18 -14
- package/conformance/valid/protection.expected.json +1 -0
- package/conformance/valid/protection.udl +719 -304
- package/conformance/valid/string-escaping.expected.json +6 -0
- package/conformance/valid/string-escaping.udl +54 -0
- package/dist/canonical.d.ts +2 -0
- package/dist/canonical.d.ts.map +1 -1
- package/dist/canonical.js +7 -0
- package/dist/canonical.js.map +1 -1
- package/dist/check-profiles.d.ts +57 -0
- package/dist/check-profiles.d.ts.map +1 -0
- package/dist/check-profiles.js +62 -0
- package/dist/check-profiles.js.map +1 -0
- package/dist/cli.js +48 -4
- package/dist/cli.js.map +1 -1
- package/dist/diagnostics.d.ts +168 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +164 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/effects.d.ts +41 -0
- package/dist/effects.d.ts.map +1 -0
- package/dist/effects.js +110 -0
- package/dist/effects.js.map +1 -0
- package/dist/evolution.d.ts +51 -18
- package/dist/evolution.d.ts.map +1 -1
- package/dist/evolution.js +244 -102
- package/dist/evolution.js.map +1 -1
- package/dist/finance.d.ts +17 -13
- package/dist/finance.d.ts.map +1 -1
- package/dist/finance.js +165 -109
- package/dist/finance.js.map +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +2 -2
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +4 -3
- package/dist/limits.js.map +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +6 -16
- package/dist/parser.js.map +1 -1
- package/dist/schema.d.ts +2059 -135
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +759 -73
- package/dist/schema.js.map +1 -1
- package/dist/validation.d.ts +22 -9
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1463 -457
- package/dist/validation.js.map +1 -1
- package/docs/README.md +14 -0
- package/docs/guide/01-a-document.md +37 -0
- package/docs/guide/02-money-steps.md +23 -0
- package/docs/guide/03-laws.md +18 -0
- package/docs/guide/04-fees-and-remainder.md +15 -0
- package/docs/guide/05-checks-updates-dials.md +7 -0
- package/docs/guide/06-effects.md +11 -0
- package/docs/guide/07-evolution.md +11 -0
- package/docs/guide/08-implementing.md +13 -0
- package/docs/llms-full.txt +1241 -0
- package/docs/llms.txt +14 -0
- package/docs/reference/canonical.md +16 -0
- package/docs/reference/clauses.md +986 -0
- package/docs/reference/cli.md +22 -0
- package/docs/reference/diagnostics.md +32 -0
- package/package.json +6 -2
- package/skills/udl/SKILL.md +28 -0
- package/spec/README.md +82 -51
- package/spec/udl.schema.json +1191 -119
- package/src/canonical.ts +11 -0
- package/src/check-profiles.ts +80 -0
- package/src/cli.ts +49 -3
- package/src/diagnostics.ts +221 -0
- package/src/effects.ts +163 -0
- package/src/evolution.ts +375 -125
- package/src/finance.ts +255 -160
- package/src/index.ts +50 -14
- package/src/limits.ts +4 -3
- package/src/parser.ts +15 -18
- package/src/schema.ts +855 -81
- package/src/validation.ts +2666 -560
- package/conformance/invalid/missing-create-verb.expected.json +0 -10
- package/conformance/invalid/noun-id-not-snake-case.expected.json +0 -10
- package/conformance/invalid/verb-without-transition.expected.json +0 -10
|
@@ -1,6 +1,105 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"instruments": [
|
|
3
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
|
+
},
|
|
4
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.",
|
|
5
104
|
"fields": {
|
|
6
105
|
"customerId": {
|
|
@@ -62,13 +161,29 @@
|
|
|
62
161
|
}
|
|
63
162
|
}
|
|
64
163
|
},
|
|
164
|
+
"nav": [
|
|
165
|
+
"Blueprints",
|
|
166
|
+
"Cardholders"
|
|
167
|
+
],
|
|
65
168
|
"required": [
|
|
66
169
|
"customerId",
|
|
67
170
|
"displayName"
|
|
68
171
|
],
|
|
69
172
|
"summary": "Customer approved to hold cards in a product.",
|
|
173
|
+
"templateId": "wallet_cards",
|
|
70
174
|
"title": "Cardholder",
|
|
71
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
|
+
],
|
|
72
187
|
"fields": [
|
|
73
188
|
"displayName",
|
|
74
189
|
"email",
|
|
@@ -79,52 +194,171 @@
|
|
|
79
194
|
"active",
|
|
80
195
|
"suspended"
|
|
81
196
|
]
|
|
82
|
-
}
|
|
83
|
-
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"actionOrder": [
|
|
201
|
+
"create",
|
|
202
|
+
"activate",
|
|
203
|
+
"freeze",
|
|
204
|
+
"unfreeze",
|
|
205
|
+
"cancel"
|
|
206
|
+
],
|
|
207
|
+
"actions": {
|
|
84
208
|
"activate": {
|
|
85
|
-
"
|
|
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
|
+
],
|
|
86
228
|
"moves": [],
|
|
229
|
+
"requiresRefs": [
|
|
230
|
+
{
|
|
231
|
+
"field": "cardholderId",
|
|
232
|
+
"statuses": [
|
|
233
|
+
"active"
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
],
|
|
87
237
|
"steps": [],
|
|
88
|
-
"summary": "Activate a
|
|
238
|
+
"summary": "Activate a card"
|
|
89
239
|
},
|
|
90
|
-
"
|
|
91
|
-
"
|
|
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
|
+
],
|
|
92
252
|
"moves": [],
|
|
93
253
|
"steps": [],
|
|
94
|
-
"summary": "
|
|
254
|
+
"summary": "Cancel a card"
|
|
95
255
|
},
|
|
96
256
|
"create": {
|
|
97
|
-
"
|
|
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",
|
|
98
268
|
"examples": [
|
|
99
269
|
{
|
|
100
270
|
"input": {
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
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"
|
|
105
290
|
},
|
|
106
|
-
"name": "
|
|
291
|
+
"name": "issue_controlled_virtual_card"
|
|
107
292
|
}
|
|
108
293
|
],
|
|
109
294
|
"moves": [],
|
|
295
|
+
"requiresRefs": [
|
|
296
|
+
{
|
|
297
|
+
"field": "cardholderId",
|
|
298
|
+
"statuses": [
|
|
299
|
+
"active"
|
|
300
|
+
]
|
|
301
|
+
}
|
|
302
|
+
],
|
|
110
303
|
"steps": [],
|
|
111
|
-
"summary": "
|
|
304
|
+
"summary": "Issue a card"
|
|
112
305
|
},
|
|
113
|
-
"
|
|
114
|
-
"
|
|
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
|
+
],
|
|
115
318
|
"moves": [],
|
|
116
319
|
"steps": [],
|
|
117
|
-
"summary": "
|
|
320
|
+
"summary": "Freeze a card"
|
|
118
321
|
},
|
|
119
|
-
"
|
|
120
|
-
"
|
|
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
|
+
],
|
|
121
343
|
"moves": [],
|
|
344
|
+
"requiresRefs": [
|
|
345
|
+
{
|
|
346
|
+
"field": "cardholderId",
|
|
347
|
+
"statuses": [
|
|
348
|
+
"active"
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
],
|
|
122
352
|
"steps": [],
|
|
123
|
-
"summary": "
|
|
353
|
+
"summary": "Unfreeze a card"
|
|
124
354
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
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
|
+
},
|
|
128
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.",
|
|
129
363
|
"fields": {
|
|
130
364
|
"accountId": {
|
|
@@ -240,6 +474,10 @@
|
|
|
240
474
|
}
|
|
241
475
|
}
|
|
242
476
|
},
|
|
477
|
+
"nav": [
|
|
478
|
+
"Blueprints",
|
|
479
|
+
"Cards"
|
|
480
|
+
],
|
|
243
481
|
"parties": {
|
|
244
482
|
"payer": "accountId"
|
|
245
483
|
},
|
|
@@ -251,8 +489,32 @@
|
|
|
251
489
|
"spendControls"
|
|
252
490
|
],
|
|
253
491
|
"summary": "Virtual payment card bound to a cardholder account.",
|
|
492
|
+
"templateId": "wallet_cards",
|
|
254
493
|
"title": "Card",
|
|
255
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
|
+
],
|
|
256
518
|
"fields": [
|
|
257
519
|
"label",
|
|
258
520
|
"spendControls"
|
|
@@ -262,92 +524,313 @@
|
|
|
262
524
|
"active",
|
|
263
525
|
"frozen"
|
|
264
526
|
]
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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": [
|
|
271
574
|
{
|
|
272
|
-
"
|
|
273
|
-
|
|
274
|
-
"
|
|
275
|
-
|
|
575
|
+
"input": {
|
|
576
|
+
"cardAuthorizationId": "cau_sandbox_purchase00001",
|
|
577
|
+
"tenantId": "ten_sandbox_cards000001"
|
|
578
|
+
},
|
|
579
|
+
"name": "approve_authorization_after_jit_decision"
|
|
276
580
|
}
|
|
277
581
|
],
|
|
278
|
-
"
|
|
279
|
-
"summary": "Activate a card"
|
|
280
|
-
},
|
|
281
|
-
"cancel": {
|
|
282
|
-
"description": "Permanently stops the virtual card. Existing posted transactions remain part of its history.",
|
|
283
|
-
"moves": [],
|
|
284
|
-
"steps": [],
|
|
285
|
-
"summary": "Cancel a card"
|
|
286
|
-
},
|
|
287
|
-
"create": {
|
|
288
|
-
"description": "Issues a virtual card to one active cardholder and binds its spend controls and funding account.",
|
|
289
|
-
"eventName": "card.issued",
|
|
290
|
-
"examples": [
|
|
582
|
+
"moves": [
|
|
291
583
|
{
|
|
292
|
-
"
|
|
293
|
-
"
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
"
|
|
298
|
-
"
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
"
|
|
307
|
-
"
|
|
308
|
-
|
|
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"
|
|
309
608
|
}
|
|
310
609
|
},
|
|
311
|
-
"
|
|
610
|
+
"capture": {
|
|
611
|
+
"authorizationTransferId": "transferId"
|
|
612
|
+
},
|
|
613
|
+
"key": "transfer",
|
|
614
|
+
"operation": "internal_transfer.reserve"
|
|
312
615
|
}
|
|
313
616
|
],
|
|
314
|
-
"moves": [],
|
|
315
617
|
"requiresRefs": [
|
|
316
618
|
{
|
|
317
|
-
"field": "
|
|
619
|
+
"field": "cardId",
|
|
318
620
|
"statuses": [
|
|
319
621
|
"active"
|
|
320
622
|
]
|
|
321
623
|
}
|
|
322
624
|
],
|
|
323
625
|
"steps": [],
|
|
324
|
-
"summary": "
|
|
626
|
+
"summary": "Approve a card authorization"
|
|
325
627
|
},
|
|
326
|
-
"
|
|
327
|
-
"
|
|
328
|
-
"
|
|
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
|
+
],
|
|
329
661
|
"steps": [],
|
|
330
|
-
"summary": "
|
|
662
|
+
"summary": "Capture a card authorization"
|
|
331
663
|
},
|
|
332
|
-
"
|
|
333
|
-
"
|
|
334
|
-
"
|
|
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
|
+
],
|
|
335
695
|
"moves": [],
|
|
336
696
|
"requiresRefs": [
|
|
337
697
|
{
|
|
338
|
-
"field": "
|
|
698
|
+
"field": "cardId",
|
|
339
699
|
"statuses": [
|
|
340
700
|
"active"
|
|
341
701
|
]
|
|
342
702
|
}
|
|
343
703
|
],
|
|
344
704
|
"steps": [],
|
|
345
|
-
"summary": "
|
|
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"
|
|
346
808
|
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
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
|
+
},
|
|
350
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
|
+
],
|
|
351
834
|
"fields": {
|
|
352
835
|
"amount": {
|
|
353
836
|
"description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
|
|
@@ -459,6 +942,10 @@
|
|
|
459
942
|
}
|
|
460
943
|
}
|
|
461
944
|
},
|
|
945
|
+
"nav": [
|
|
946
|
+
"Blueprints",
|
|
947
|
+
"Card authorizations"
|
|
948
|
+
],
|
|
462
949
|
"parties": {
|
|
463
950
|
"beneficiary": "settlementAccountId",
|
|
464
951
|
"payer": "cardAccountId"
|
|
@@ -476,165 +963,137 @@
|
|
|
476
963
|
"expiresAt"
|
|
477
964
|
],
|
|
478
965
|
"summary": "Just-in-time decision and hold for one card purchase.",
|
|
479
|
-
"
|
|
480
|
-
"
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
+
]
|
|
486
985
|
},
|
|
487
|
-
"
|
|
488
|
-
"
|
|
986
|
+
"eventName": "card_transaction.posted",
|
|
987
|
+
"examples": [
|
|
489
988
|
{
|
|
490
|
-
"
|
|
491
|
-
"
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
"currency": {
|
|
496
|
-
"from": "instance",
|
|
497
|
-
"path": "fields.currency"
|
|
498
|
-
},
|
|
499
|
-
"destinationAccountId": {
|
|
500
|
-
"from": "instance",
|
|
501
|
-
"path": "fields.settlementAccountId"
|
|
502
|
-
},
|
|
503
|
-
"expiresAt": {
|
|
504
|
-
"from": "instance",
|
|
505
|
-
"path": "fields.expiresAt"
|
|
506
|
-
},
|
|
507
|
-
"memo": {
|
|
508
|
-
"from": "const",
|
|
509
|
-
"value": "Card authorization hold"
|
|
510
|
-
},
|
|
511
|
-
"sourceAccountId": {
|
|
512
|
-
"from": "instance",
|
|
513
|
-
"path": "fields.cardAccountId"
|
|
514
|
-
}
|
|
515
|
-
},
|
|
516
|
-
"capture": {
|
|
517
|
-
"authorizationTransferId": "transferId"
|
|
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"
|
|
518
994
|
},
|
|
519
|
-
"
|
|
520
|
-
"operation": "internal_transfer.reserve"
|
|
995
|
+
"name": "record_captured_card_purchase"
|
|
521
996
|
}
|
|
522
997
|
],
|
|
998
|
+
"moves": [],
|
|
523
999
|
"requiresRefs": [
|
|
524
|
-
{
|
|
525
|
-
"field": "cardId",
|
|
526
|
-
"statuses": [
|
|
527
|
-
"active"
|
|
528
|
-
]
|
|
529
|
-
}
|
|
530
|
-
],
|
|
531
|
-
"steps": [],
|
|
532
|
-
"summary": "Approve a card authorization"
|
|
533
|
-
},
|
|
534
|
-
"capture": {
|
|
535
|
-
"description": "Posts the reserved transfer after the merchant completes the purchase.",
|
|
536
|
-
"earnable": true,
|
|
537
|
-
"moves": [
|
|
538
1000
|
{
|
|
539
1001
|
"bind": {
|
|
540
|
-
"
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
1002
|
+
"amount": "fields.amount",
|
|
1003
|
+
"cardAccountId": "fields.cardAccountId",
|
|
1004
|
+
"cardId": "fields.cardId",
|
|
1005
|
+
"currency": "fields.currency",
|
|
1006
|
+
"merchantReference": "fields.merchantReference",
|
|
1007
|
+
"settlementAccountId": "fields.settlementAccountId"
|
|
544
1008
|
},
|
|
545
|
-
"
|
|
546
|
-
"
|
|
1009
|
+
"field": "cardAuthorizationId",
|
|
1010
|
+
"statuses": [
|
|
1011
|
+
"captured"
|
|
1012
|
+
],
|
|
1013
|
+
"unique": true
|
|
547
1014
|
}
|
|
548
1015
|
],
|
|
549
1016
|
"steps": [],
|
|
550
|
-
"summary": "
|
|
1017
|
+
"summary": "Record a card transaction"
|
|
551
1018
|
},
|
|
552
|
-
"
|
|
553
|
-
"
|
|
554
|
-
"
|
|
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
|
+
},
|
|
555
1030
|
"examples": [
|
|
556
1031
|
{
|
|
557
1032
|
"input": {
|
|
558
|
-
"
|
|
559
|
-
"
|
|
560
|
-
"
|
|
561
|
-
"currency": "SAR",
|
|
562
|
-
"expiresAt": "2026-07-16T12:00:00.000Z",
|
|
563
|
-
"merchantCategory": "electronics",
|
|
564
|
-
"merchantCountry": "SA",
|
|
565
|
-
"merchantName": "Riyadh Camera Store",
|
|
566
|
-
"merchantReference": "merchant-order-1042",
|
|
567
|
-
"settlementAccountId": "acct_sandbox_merchant0001"
|
|
1033
|
+
"cardTransactionId": "ctx_sandbox_purchase00001",
|
|
1034
|
+
"reason": "Merchant accepted the returned item",
|
|
1035
|
+
"tenantId": "ten_sandbox_cards000001"
|
|
568
1036
|
},
|
|
569
|
-
"name": "
|
|
570
|
-
}
|
|
571
|
-
],
|
|
572
|
-
"moves": [],
|
|
573
|
-
"requiresRefs": [
|
|
574
|
-
{
|
|
575
|
-
"field": "cardId",
|
|
576
|
-
"statuses": [
|
|
577
|
-
"active"
|
|
578
|
-
]
|
|
1037
|
+
"name": "refund_returned_purchase"
|
|
579
1038
|
}
|
|
580
1039
|
],
|
|
581
|
-
"
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
"
|
|
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"
|
|
594
1053
|
},
|
|
595
1054
|
"moves": [
|
|
596
1055
|
{
|
|
597
1056
|
"bind": {
|
|
598
|
-
"
|
|
599
|
-
"from": "
|
|
600
|
-
"
|
|
1057
|
+
"amount": {
|
|
1058
|
+
"from": "instance",
|
|
1059
|
+
"path": "fields.amount"
|
|
601
1060
|
},
|
|
602
|
-
"
|
|
1061
|
+
"currency": {
|
|
603
1062
|
"from": "instance",
|
|
604
|
-
"path": "
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
}
|
|
610
|
-
],
|
|
611
|
-
"steps": [],
|
|
612
|
-
"summary": "Expire a card authorization"
|
|
613
|
-
},
|
|
614
|
-
"reverse": {
|
|
615
|
-
"description": "Voids an approved hold before capture and releases the card funds.",
|
|
616
|
-
"moves": [
|
|
617
|
-
{
|
|
618
|
-
"bind": {
|
|
619
|
-
"reason": {
|
|
620
|
-
"from": "const",
|
|
621
|
-
"value": "Card authorization reversed"
|
|
1063
|
+
"path": "fields.currency"
|
|
1064
|
+
},
|
|
1065
|
+
"destinationAccountId": {
|
|
1066
|
+
"from": "instance",
|
|
1067
|
+
"path": "fields.cardAccountId"
|
|
622
1068
|
},
|
|
623
|
-
"
|
|
1069
|
+
"memo": {
|
|
1070
|
+
"from": "input",
|
|
1071
|
+
"path": "reason"
|
|
1072
|
+
},
|
|
1073
|
+
"productId": {
|
|
624
1074
|
"from": "instance",
|
|
625
|
-
"path": "
|
|
1075
|
+
"path": "productId"
|
|
1076
|
+
},
|
|
1077
|
+
"sourceAccountId": {
|
|
1078
|
+
"from": "instance",
|
|
1079
|
+
"path": "fields.settlementAccountId"
|
|
626
1080
|
}
|
|
627
1081
|
},
|
|
1082
|
+
"capture": {
|
|
1083
|
+
"refundTransferId": "transferId"
|
|
1084
|
+
},
|
|
628
1085
|
"key": "transfer",
|
|
629
|
-
"operation": "internal_transfer.
|
|
1086
|
+
"operation": "internal_transfer.create"
|
|
630
1087
|
}
|
|
631
1088
|
],
|
|
632
1089
|
"steps": [],
|
|
633
|
-
"summary": "
|
|
1090
|
+
"summary": "Refund a card transaction"
|
|
634
1091
|
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
|
|
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
|
+
},
|
|
638
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.",
|
|
639
1098
|
"fields": {
|
|
640
1099
|
"amount": {
|
|
@@ -708,6 +1167,10 @@
|
|
|
708
1167
|
}
|
|
709
1168
|
}
|
|
710
1169
|
},
|
|
1170
|
+
"nav": [
|
|
1171
|
+
"Blueprints",
|
|
1172
|
+
"Card transactions"
|
|
1173
|
+
],
|
|
711
1174
|
"parties": {
|
|
712
1175
|
"beneficiary": "settlementAccountId",
|
|
713
1176
|
"payer": "cardAccountId"
|
|
@@ -723,18 +1186,47 @@
|
|
|
723
1186
|
"postedAt"
|
|
724
1187
|
],
|
|
725
1188
|
"summary": "Posted card purchase and its possible full refund.",
|
|
726
|
-
"
|
|
727
|
-
"
|
|
1189
|
+
"templateId": "wallet_cards",
|
|
1190
|
+
"title": "Card transaction"
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
"actionOrder": [
|
|
1194
|
+
"create",
|
|
1195
|
+
"review",
|
|
1196
|
+
"win",
|
|
1197
|
+
"lose"
|
|
1198
|
+
],
|
|
1199
|
+
"actions": {
|
|
728
1200
|
"create": {
|
|
729
|
-
"
|
|
730
|
-
"
|
|
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",
|
|
731
1212
|
"examples": [
|
|
732
1213
|
{
|
|
733
1214
|
"input": {
|
|
734
|
-
"
|
|
735
|
-
"
|
|
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"
|
|
736
1228
|
},
|
|
737
|
-
"name": "
|
|
1229
|
+
"name": "file_unauthorized_purchase_dispute"
|
|
738
1230
|
}
|
|
739
1231
|
],
|
|
740
1232
|
"moves": [],
|
|
@@ -745,43 +1237,98 @@
|
|
|
745
1237
|
"cardAccountId": "fields.cardAccountId",
|
|
746
1238
|
"cardId": "fields.cardId",
|
|
747
1239
|
"currency": "fields.currency",
|
|
748
|
-
"merchantReference": "fields.merchantReference",
|
|
749
1240
|
"settlementAccountId": "fields.settlementAccountId"
|
|
750
1241
|
},
|
|
751
|
-
"field": "
|
|
1242
|
+
"field": "cardTransactionId",
|
|
752
1243
|
"statuses": [
|
|
753
|
-
"
|
|
754
|
-
]
|
|
755
|
-
"unique": true
|
|
1244
|
+
"posted"
|
|
1245
|
+
]
|
|
756
1246
|
}
|
|
757
1247
|
],
|
|
758
1248
|
"steps": [],
|
|
759
|
-
"summary": "
|
|
1249
|
+
"summary": "File a card dispute"
|
|
760
1250
|
},
|
|
761
|
-
"
|
|
762
|
-
"description": "
|
|
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",
|
|
763
1265
|
"examples": [
|
|
764
1266
|
{
|
|
765
1267
|
"input": {
|
|
766
|
-
"
|
|
1268
|
+
"cardDisputeId": "cdis_sandbox_purchase0001",
|
|
1269
|
+
"tenantId": "ten_sandbox_cards000001"
|
|
767
1270
|
},
|
|
768
|
-
"name": "
|
|
1271
|
+
"name": "close_unresolved_dispute_at_deadline"
|
|
769
1272
|
}
|
|
770
1273
|
],
|
|
771
|
-
"
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
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"
|
|
778
1307
|
}
|
|
779
|
-
},
|
|
780
|
-
"required": [
|
|
781
|
-
"reason"
|
|
782
1308
|
],
|
|
783
|
-
"
|
|
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
|
+
]
|
|
784
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
|
+
],
|
|
785
1332
|
"moves": [
|
|
786
1333
|
{
|
|
787
1334
|
"bind": {
|
|
@@ -798,32 +1345,57 @@
|
|
|
798
1345
|
"path": "fields.cardAccountId"
|
|
799
1346
|
},
|
|
800
1347
|
"memo": {
|
|
801
|
-
"from": "
|
|
802
|
-
"
|
|
1348
|
+
"from": "const",
|
|
1349
|
+
"value": "Card dispute won"
|
|
803
1350
|
},
|
|
804
|
-
"
|
|
1351
|
+
"productId": {
|
|
805
1352
|
"from": "instance",
|
|
806
|
-
"path": "
|
|
1353
|
+
"path": "productId"
|
|
807
1354
|
},
|
|
808
|
-
"
|
|
1355
|
+
"sourceAccountId": {
|
|
809
1356
|
"from": "instance",
|
|
810
|
-
"path": "
|
|
1357
|
+
"path": "fields.settlementAccountId"
|
|
811
1358
|
}
|
|
812
1359
|
},
|
|
813
1360
|
"capture": {
|
|
814
|
-
"
|
|
1361
|
+
"disputeTransferId": "transferId"
|
|
815
1362
|
},
|
|
816
1363
|
"key": "transfer",
|
|
817
1364
|
"operation": "internal_transfer.create"
|
|
818
1365
|
}
|
|
819
1366
|
],
|
|
1367
|
+
"requiresRefs": [
|
|
1368
|
+
{
|
|
1369
|
+
"field": "cardTransactionId",
|
|
1370
|
+
"statuses": [
|
|
1371
|
+
"posted"
|
|
1372
|
+
]
|
|
1373
|
+
}
|
|
1374
|
+
],
|
|
820
1375
|
"steps": [],
|
|
821
|
-
"summary": "
|
|
1376
|
+
"summary": "Win a card dispute"
|
|
822
1377
|
}
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
{
|
|
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.",
|
|
826
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
|
+
],
|
|
827
1399
|
"fields": {
|
|
828
1400
|
"amount": {
|
|
829
1401
|
"description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
|
|
@@ -944,6 +1516,10 @@
|
|
|
944
1516
|
}
|
|
945
1517
|
}
|
|
946
1518
|
},
|
|
1519
|
+
"nav": [
|
|
1520
|
+
"Blueprints",
|
|
1521
|
+
"Card disputes"
|
|
1522
|
+
],
|
|
947
1523
|
"parties": {
|
|
948
1524
|
"beneficiary": "cardAccountId",
|
|
949
1525
|
"payer": "settlementAccountId"
|
|
@@ -960,8 +1536,31 @@
|
|
|
960
1536
|
"responseDueAt"
|
|
961
1537
|
],
|
|
962
1538
|
"summary": "Evidence-backed challenge to one posted card transaction.",
|
|
1539
|
+
"templateId": "wallet_cards",
|
|
963
1540
|
"title": "Card dispute",
|
|
964
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
|
+
],
|
|
965
1564
|
"fields": [
|
|
966
1565
|
"evidence"
|
|
967
1566
|
],
|
|
@@ -969,118 +1568,6 @@
|
|
|
969
1568
|
"filed",
|
|
970
1569
|
"under_review"
|
|
971
1570
|
]
|
|
972
|
-
},
|
|
973
|
-
"verbs": {
|
|
974
|
-
"create": {
|
|
975
|
-
"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.",
|
|
976
|
-
"eventName": "card_dispute.filed",
|
|
977
|
-
"examples": [
|
|
978
|
-
{
|
|
979
|
-
"input": {
|
|
980
|
-
"cardTransactionId": "ctx_sandbox_purchase00001",
|
|
981
|
-
"evidence": [
|
|
982
|
-
{
|
|
983
|
-
"kind": "customer_statement",
|
|
984
|
-
"reference": "support-case-2048",
|
|
985
|
-
"submittedAt": "2026-07-11T10:15:00.000Z",
|
|
986
|
-
"summary": "Customer confirms the purchase was not authorized."
|
|
987
|
-
}
|
|
988
|
-
],
|
|
989
|
-
"reason": "unauthorized_purchase",
|
|
990
|
-
"responseDueAt": "2026-08-10T23:59:59.000Z"
|
|
991
|
-
},
|
|
992
|
-
"name": "file_unauthorized_purchase_dispute"
|
|
993
|
-
}
|
|
994
|
-
],
|
|
995
|
-
"moves": [],
|
|
996
|
-
"requiresRefs": [
|
|
997
|
-
{
|
|
998
|
-
"bind": {
|
|
999
|
-
"amount": "fields.amount",
|
|
1000
|
-
"cardAccountId": "fields.cardAccountId",
|
|
1001
|
-
"cardId": "fields.cardId",
|
|
1002
|
-
"currency": "fields.currency",
|
|
1003
|
-
"settlementAccountId": "fields.settlementAccountId"
|
|
1004
|
-
},
|
|
1005
|
-
"field": "cardTransactionId",
|
|
1006
|
-
"statuses": [
|
|
1007
|
-
"posted"
|
|
1008
|
-
]
|
|
1009
|
-
}
|
|
1010
|
-
],
|
|
1011
|
-
"steps": [],
|
|
1012
|
-
"summary": "File a card dispute"
|
|
1013
|
-
},
|
|
1014
|
-
"lose": {
|
|
1015
|
-
"description": "Closes an unresolved dispute without moving money when its response deadline passes.",
|
|
1016
|
-
"due": {
|
|
1017
|
-
"field": "responseDueAt"
|
|
1018
|
-
},
|
|
1019
|
-
"eventName": "card_dispute.lost",
|
|
1020
|
-
"moves": [],
|
|
1021
|
-
"steps": [],
|
|
1022
|
-
"summary": "Lose a card dispute"
|
|
1023
|
-
},
|
|
1024
|
-
"review": {
|
|
1025
|
-
"description": "Accepts the filed evidence for an outcome decision before the response deadline.",
|
|
1026
|
-
"moves": [],
|
|
1027
|
-
"steps": [],
|
|
1028
|
-
"summary": "Review a card dispute"
|
|
1029
|
-
},
|
|
1030
|
-
"win": {
|
|
1031
|
-
"decision": {
|
|
1032
|
-
"capability": "banking_or_card_issuing",
|
|
1033
|
-
"deadlineMs": 15000,
|
|
1034
|
-
"onTimeout": "decline"
|
|
1035
|
-
},
|
|
1036
|
-
"description": "Asks the configured card policy for the final outcome and returns the disputed amount when the cardholder wins.",
|
|
1037
|
-
"eventName": "card_dispute.won",
|
|
1038
|
-
"moves": [
|
|
1039
|
-
{
|
|
1040
|
-
"bind": {
|
|
1041
|
-
"amount": {
|
|
1042
|
-
"from": "instance",
|
|
1043
|
-
"path": "fields.amount"
|
|
1044
|
-
},
|
|
1045
|
-
"currency": {
|
|
1046
|
-
"from": "instance",
|
|
1047
|
-
"path": "fields.currency"
|
|
1048
|
-
},
|
|
1049
|
-
"destinationAccountId": {
|
|
1050
|
-
"from": "instance",
|
|
1051
|
-
"path": "fields.cardAccountId"
|
|
1052
|
-
},
|
|
1053
|
-
"memo": {
|
|
1054
|
-
"from": "const",
|
|
1055
|
-
"value": "Card dispute won"
|
|
1056
|
-
},
|
|
1057
|
-
"sourceAccountId": {
|
|
1058
|
-
"from": "instance",
|
|
1059
|
-
"path": "fields.settlementAccountId"
|
|
1060
|
-
},
|
|
1061
|
-
"workspaceId": {
|
|
1062
|
-
"from": "instance",
|
|
1063
|
-
"path": "workspaceId"
|
|
1064
|
-
}
|
|
1065
|
-
},
|
|
1066
|
-
"capture": {
|
|
1067
|
-
"disputeTransferId": "transferId"
|
|
1068
|
-
},
|
|
1069
|
-
"key": "transfer",
|
|
1070
|
-
"operation": "internal_transfer.create"
|
|
1071
|
-
}
|
|
1072
|
-
],
|
|
1073
|
-
"requiresRefs": [
|
|
1074
|
-
{
|
|
1075
|
-
"field": "cardTransactionId",
|
|
1076
|
-
"statuses": [
|
|
1077
|
-
"posted"
|
|
1078
|
-
]
|
|
1079
|
-
}
|
|
1080
|
-
],
|
|
1081
|
-
"steps": [],
|
|
1082
|
-
"summary": "Win a card dispute"
|
|
1083
|
-
}
|
|
1084
1571
|
}
|
|
1085
1572
|
}
|
|
1086
1573
|
],
|