@agent-cards/sdk 0.20.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 (121) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/PREFLIGHT.md +314 -0
  3. package/README.md +864 -0
  4. package/dist/adyen-merchant-hosted.generated.d.ts +277 -0
  5. package/dist/adyen-merchant-hosted.generated.js +1902 -0
  6. package/dist/adyen.generated.d.ts +24 -0
  7. package/dist/adyen.generated.js +64 -0
  8. package/dist/agentcard.d.ts +72 -0
  9. package/dist/agentcard.js +71 -0
  10. package/dist/api-module.d.ts +54 -0
  11. package/dist/api-module.js +85 -0
  12. package/dist/attachment.d.ts +11 -0
  13. package/dist/attachment.js +50 -0
  14. package/dist/braintree.d.ts +2 -0
  15. package/dist/braintree.generated.d.ts +10 -0
  16. package/dist/braintree.generated.js +302 -0
  17. package/dist/braintree.js +2 -0
  18. package/dist/builtin-registry.generated.d.ts +2 -0
  19. package/dist/builtin-registry.generated.js +1 -0
  20. package/dist/buy.d.ts +374 -0
  21. package/dist/buy.js +314 -0
  22. package/dist/card-fields.generated.d.ts +3 -0
  23. package/dist/card-fields.generated.js +88 -0
  24. package/dist/cdp.d.ts +202 -0
  25. package/dist/cdp.js +2540 -0
  26. package/dist/checkout-com.generated.d.ts +4 -0
  27. package/dist/checkout-com.generated.js +183 -0
  28. package/dist/client.d.ts +929 -0
  29. package/dist/client.js +1896 -0
  30. package/dist/cse-body.d.ts +25 -0
  31. package/dist/cse-body.js +41 -0
  32. package/dist/fiserv.d.ts +65 -0
  33. package/dist/fiserv.generated.d.ts +73 -0
  34. package/dist/fiserv.generated.js +830 -0
  35. package/dist/fiserv.js +104 -0
  36. package/dist/hosted-form.d.ts +44 -0
  37. package/dist/hosted-form.js +78 -0
  38. package/dist/index.d.ts +37 -0
  39. package/dist/index.js +26 -0
  40. package/dist/languages.d.ts +23 -0
  41. package/dist/languages.js +76 -0
  42. package/dist/lifecycle.d.ts +235 -0
  43. package/dist/lifecycle.js +405 -0
  44. package/dist/mercado-checkout.d.ts +20 -0
  45. package/dist/mercado-checkout.generated.d.ts +52 -0
  46. package/dist/mercado-checkout.generated.js +198 -0
  47. package/dist/mercado-checkout.js +108 -0
  48. package/dist/merchant-handoff.d.ts +54 -0
  49. package/dist/merchant-handoff.js +100 -0
  50. package/dist/merchant-hosted.d.ts +140 -0
  51. package/dist/merchant-hosted.js +170 -0
  52. package/dist/merchant-total-watch.d.ts +115 -0
  53. package/dist/merchant-total-watch.js +268 -0
  54. package/dist/merchant-total.d.ts +257 -0
  55. package/dist/merchant-total.js +383 -0
  56. package/dist/owned-shop.generated.d.ts +24 -0
  57. package/dist/owned-shop.generated.js +108 -0
  58. package/dist/paysafe.generated.d.ts +12 -0
  59. package/dist/paysafe.generated.js +87 -0
  60. package/dist/playwright.d.ts +3 -0
  61. package/dist/playwright.js +3 -0
  62. package/dist/pre-claim.d.ts +123 -0
  63. package/dist/pre-claim.js +386 -0
  64. package/dist/preflight-capabilities.generated.d.ts +1311 -0
  65. package/dist/preflight-capabilities.generated.js +2007 -0
  66. package/dist/preflight-catalog.json +5031 -0
  67. package/dist/preflight-playwright.d.ts +34 -0
  68. package/dist/preflight-playwright.js +355 -0
  69. package/dist/preflight-schemas.json +1144 -0
  70. package/dist/preflight.d.ts +1 -0
  71. package/dist/preflight.generated.d.ts +2023 -0
  72. package/dist/preflight.generated.js +604 -0
  73. package/dist/preflight.js +2 -0
  74. package/dist/preparation.d.ts +38 -0
  75. package/dist/preparation.js +191 -0
  76. package/dist/prepared-processor.d.ts +43 -0
  77. package/dist/prepared-processor.js +172 -0
  78. package/dist/recurly.generated.d.ts +1 -0
  79. package/dist/recurly.generated.js +87 -0
  80. package/dist/registry.d.ts +145 -0
  81. package/dist/registry.js +338 -0
  82. package/dist/requests.d.ts +66 -0
  83. package/dist/requests.js +76 -0
  84. package/dist/spreedly.generated.d.ts +10 -0
  85. package/dist/spreedly.generated.js +332 -0
  86. package/dist/stripe-checkout.d.ts +81 -0
  87. package/dist/stripe-checkout.generated.d.ts +82 -0
  88. package/dist/stripe-checkout.generated.js +1153 -0
  89. package/dist/stripe-checkout.js +140 -0
  90. package/dist/substitute.d.ts +38 -0
  91. package/dist/substitute.js +23 -0
  92. package/dist/substitutions.generated.d.ts +11 -0
  93. package/dist/substitutions.generated.js +818 -0
  94. package/dist/voice-pkce.d.ts +49 -0
  95. package/dist/voice-pkce.js +147 -0
  96. package/dist/voice-retry.d.ts +6 -0
  97. package/dist/voice-retry.js +27 -0
  98. package/dist/voice-stream.generated.d.ts +118 -0
  99. package/dist/voice-stream.generated.js +170 -0
  100. package/dist/voice-types.d.ts +708 -0
  101. package/dist/voice-types.js +16 -0
  102. package/dist/voice.d.ts +365 -0
  103. package/dist/voice.js +807 -0
  104. package/dist/webhooks.d.ts +87 -0
  105. package/dist/webhooks.js +136 -0
  106. package/examples/existing-browser.mjs +62 -0
  107. package/examples/preflight/classify-direct.mjs +21 -0
  108. package/examples/preflight/classify-kernel.mjs +30 -0
  109. package/examples/preflight/inspect-browser.mjs +44 -0
  110. package/examples/preflight/kernel-native/README.md +112 -0
  111. package/examples/preflight/kernel-native/documented-adapters.json +113 -0
  112. package/examples/preflight/kernel-native/inventory.json +242 -0
  113. package/examples/preflight/kernel-native/qualification.mjs +182 -0
  114. package/examples/preflight/kernel-profile.empty.json +11 -0
  115. package/examples/preflight/mollie-hosted.observations.json +23 -0
  116. package/examples/preflight/mollie-hosted.result.json +103 -0
  117. package/examples/preflight/stripe-script.direct.result.json +92 -0
  118. package/examples/preflight/stripe-script.observations.json +16 -0
  119. package/examples/preflight/stripe-script.result.json +87 -0
  120. package/package.json +53 -0
  121. package/readme.test.mjs +53 -0
@@ -0,0 +1,929 @@
1
+ import { type CheckoutMode, type Recognizer } from './registry.js';
2
+ import type { Substitutions } from './substitute.js';
3
+ import { type MerchantHostedSubstitutions, type MerchantProfile, type SandboxMerchantDeclaration } from './merchant-hosted.js';
4
+ import { type MerchantTotalApproved, type MerchantTotalCapture } from './merchant-total.js';
5
+ import { type PreparationMode, type PreparationProcessor } from './prepared-processor.js';
6
+ import { VoiceModule, type VoiceOptions } from './voice.js';
7
+ import { BuyModule } from './buy.js';
8
+ import { RequestRegistry } from './requests.js';
9
+ import type { ApiTransport } from './api-module.js';
10
+ export interface PausedRequest {
11
+ url: string;
12
+ method: string;
13
+ headers: Record<string, string>;
14
+ body: string;
15
+ /** Captured native Checkout Pro initialization, validated before use. */
16
+ mercado_checkout?: unknown;
17
+ }
18
+ /**
19
+ * The modes this SDK can finish. Asked for on syncRegistry (the API serves
20
+ * only recognizers in these modes, so a request this build cannot complete
21
+ * is never paused) and sent on every create.
22
+ */
23
+ export declare const SUPPORTED_MODES: readonly CheckoutMode[];
24
+ /**
25
+ * Registry features this SDK honours, asked for on syncRegistry next to the
26
+ * modes. `card_fields`: it reads a recognizer's cardFields and claims only a
27
+ * request whose body carries the card, so the API may serve it recognizers
28
+ * whose endpoints also run without a card. `checkout_sessions`: it lets a
29
+ * request the recognizer marks as routine without a card (passWithoutCard)
30
+ * through ahead of its holds, so the API may serve Stripe's Checkout Session
31
+ * confirm, which hosted Checkout sends after an approval.
32
+ */
33
+ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
34
+ /**
35
+ * Dark-launch capabilities this build can finish. Sent on syncRegistry as
36
+ * ?capabilities= so the API also serves the recognizers gated behind one of
37
+ * these. `fiserv_card_capture`: Fiserv Commerce Hub's Secure Data Capture card
38
+ * capture, which this build pauses and pays only through a prepared checkout
39
+ * (pre-claim.ts, fiserv.ts). The API serves Fiserv's recognizer only to a build
40
+ * that lists it and only for a company Agentcard turned Fiserv on for, so an older
41
+ * SDK never pauses a capture it cannot finish and no SDK pauses one for a company
42
+ * Fiserv is off for; the API also refuses a Fiserv payment for every such company.
43
+ */
44
+ export declare const SUPPORTED_CAPABILITIES: readonly string[];
45
+ /**
46
+ * What the amount on an authorization IS: held to a Stripe PaymentIntent
47
+ * (read back at create and before the replay), the parked form's own sum
48
+ * (hosted_form: the bytes the device submits name the amount), or a display
49
+ * fact on a template that carries no amount.
50
+ */
51
+ /**
52
+ * Who named the amount an authorization carries: `processor` (the paused
53
+ * request's own bytes, or the Stripe intent it names, read back by Agentcard),
54
+ * `agent` (the `amount` you passed), `page` (the total read off the checkout
55
+ * page), or `none` (nobody yet; the processor is read right before the card
56
+ * is sent).
57
+ */
58
+ export type AmountAuthority = 'processor' | 'agent' | 'page' | 'none';
59
+ /** An integer in the smallest unit, or a decimal string in normal units with a point; nothing else. */
60
+ export declare function validAmountInput(amount: unknown): amount is number | string;
61
+ /** How an existing authorization is being handled; omitted by older APIs. */
62
+ export interface ExecutionMetadata {
63
+ executionMode?: 'user_approval' | 'autopilot';
64
+ grantId?: string;
65
+ }
66
+ /**
67
+ * The token flow: the cardholder's device called the processor itself, and
68
+ * this is the processor's answer to replay into the paused request.
69
+ */
70
+ export interface TokenReplay extends ExecutionMetadata {
71
+ /** Authenticated selected-card metadata; the processor response body stays unchanged. */
72
+ processorContext?: unknown;
73
+ /** Present only after validating the native TEST Checkout completion. */
74
+ checkoutSessionId?: string;
75
+ /** Present only after validating the explicit owned-shop purchase receipt. */
76
+ shopOrderId?: string;
77
+ /** Absent on older API versions; always 'token' here. */
78
+ mode?: 'token';
79
+ /** The approved authorization (`cauth_…`). */
80
+ authorizationId: string;
81
+ status: number;
82
+ headers: Record<string, string>;
83
+ /** Body to hand back to the browser, verbatim. */
84
+ body: string;
85
+ /**
86
+ * Post-replay reconciliation, when the API has it: whether the amount the
87
+ * processor reported charging equals the amount the user approved (null
88
+ * when there was nothing to compare, e.g. a tokenization request), and the
89
+ * charged pair itself. A `false` here means the approval stood (money had
90
+ * moved) and Agentcard also sent your server checkout_authorization.amount_mismatch.
91
+ */
92
+ amountVerified?: boolean | null;
93
+ /** What the processor collected, an integer in the currency's smallest unit (Stripe's `amount`). */
94
+ chargedAmount?: number | null;
95
+ chargedCurrency?: string | null;
96
+ /**
97
+ * What `chargedAmount` is: 'captured' (the intent succeeded; this is
98
+ * amount_received), 'authorized' (requires_capture; amount_capturable, the
99
+ * merchant captures later), 'none' (a PaymentIntent was reported but
100
+ * nothing is collected yet: processing, requires_action), or null when no
101
+ * PaymentIntent was reported at all (a tokenization request).
102
+ */
103
+ chargedKind?: 'captured' | 'authorized' | 'none' | null;
104
+ /** Who named the amount the person approved. */
105
+ amountAuthority?: AmountAuthority;
106
+ }
107
+ /**
108
+ * The cse flow (Adyen): the cardholder's device encrypted the card under the
109
+ * processor's public key and reported the ciphertext. Nothing was sent to the
110
+ * processor yet: write `substitutions` into the paused body
111
+ * (substituteEncryptedFields) and let the request CONTINUE from the browser
112
+ * that paused it, so its session data, risk data and cookies stay its own.
113
+ * The processor's answer then reaches the page as it normally would; the
114
+ * merchant's order state is where the outcome shows up. A Fiserv card capture
115
+ * (a prepared checkout only) carries its envelope at `source.encryptionData`:
116
+ * write it with substituteFiservEnvelope, never substituteEncryptedFields.
117
+ */
118
+ export interface CseReplay extends ExecutionMetadata {
119
+ mode: 'cse';
120
+ /** Absent on a processor-hosted cse approval; see MerchantHostedReplay. */
121
+ kind?: undefined;
122
+ authorizationId: string;
123
+ substitutions: Substitutions;
124
+ amountAuthority?: AmountAuthority;
125
+ }
126
+ /**
127
+ * The cse flow at an Adyen merchant's OWN endpoint (a reviewed merchant
128
+ * profile, see merchant-hosted.ts): the cardholder's device encrypted the card
129
+ * under the key Agentcard reviewed for that merchant, and nothing was sent. The
130
+ * paused request continues from this browser with the ciphertext written where
131
+ * the profile holds it (substituteMerchantHostedBody), and only when the live
132
+ * body still hashes to `bodySha256`, the body the API checked at create. The
133
+ * merchant's server charges the card and answers its own page; its order state is
134
+ * the outcome. Only a prepared checkout pays one, never Autopilot.
135
+ */
136
+ export interface MerchantHostedReplay extends ExecutionMetadata {
137
+ mode: 'cse';
138
+ kind: 'merchant_hosted';
139
+ authorizationId: string;
140
+ /** The reviewed merchant profile the approval pays. */
141
+ profile: string;
142
+ substitutions: MerchantHostedSubstitutions;
143
+ /** SHA-256 (lowercase hex) of the paused body the API checked at create. */
144
+ bodySha256: string;
145
+ /** When the API stops serving this ciphertext, if it said. */
146
+ substitutionsExpiresAt: string | null;
147
+ /** Present when the approval pays this client's own sandbox declaration (VaultClientOptions.sandboxMerchants). */
148
+ sandboxDeclaration?: Readonly<{
149
+ endpoint: string;
150
+ clientKey: string;
151
+ }>;
152
+ /**
153
+ * The merchant's own total this approval was created at, when its profile is priced by
154
+ * one: the adapters read it again at release (merchantTotalAtRelease) and hold the card
155
+ * request unless it is still this amount, then report what the merchant says it charged.
156
+ */
157
+ merchantTotal?: MerchantTotalApproved;
158
+ amountAuthority?: AmountAuthority;
159
+ }
160
+ /**
161
+ * The hosted_form flow (Tranzila): the cardholder's device rebuilt the
162
+ * processor's own form with the real card and submitted it itself, top-level,
163
+ * at `submittedAt`. The processor answered THE DEVICE, not the browser that
164
+ * paused the navigation, so there is no response to replay and no outcome
165
+ * here: resolve the paused navigation with hostedFormSubmittedPage() (the
166
+ * adapters do), never resubmit the form, and confirm the order with the
167
+ * merchant, which learns the outcome from the processor.
168
+ *
169
+ * THIS IS NOT AN APPROVED PAYMENT. `kind` and `outcome` say so in words so
170
+ * no caller mistakes it for one: the API finishes such an authorization as
171
+ * `submitted_on_device` (never `approved`) and sends your server
172
+ * `checkout_authorization.submitted` (never `.approved`). The stamp is the
173
+ * cardholder's device attesting that the form left it; Agentcard holds no
174
+ * processor evidence on this mode and cannot obtain any. Treat it as "the
175
+ * person paid, or tried to, on their own device" and confirm with the merchant.
176
+ */
177
+ export interface HostedFormReplay extends ExecutionMetadata {
178
+ mode: 'hosted_form';
179
+ /** What this resolution is: a device-attested submission, not a processor answer. */
180
+ kind: 'submitted_on_device';
181
+ /** Always 'unverified': no processor evidence exists for a hosted form. */
182
+ outcome: 'unverified';
183
+ authorizationId: string;
184
+ /** When the device reported the form left it (ISO 8601). */
185
+ submittedAt: string;
186
+ amountAuthority?: AmountAuthority;
187
+ }
188
+ /** What authorize() resolves with; branch on `mode` (absent means token). */
189
+ export type ReplayResponse = TokenReplay | CseReplay | MerchantHostedReplay | HostedFormReplay;
190
+ export interface PrepareCheckoutOptions {
191
+ psp: PreparationProcessor;
192
+ /** The processor environment, independent of your Agentcard client's mode. */
193
+ environment: 'production' | 'sandbox' | 'shared';
194
+ /**
195
+ * An Adyen merchant that takes the card on its own server: the id of the
196
+ * profile Agentcard reviewed for it (psp 'adyen'; the environment is the
197
+ * profile's). The profile must be enabled on this client (syncRegistry); its
198
+ * card request is then the one request this preparation pays.
199
+ *
200
+ * A Fiserv checkout (psp 'fiserv'): the id of the key Agentcard pinned for the
201
+ * merchant, `agentcard_sandbox` in the sandbox environment. Required for Fiserv,
202
+ * and refused for every processor but Adyen and Fiserv. The cardholder is asked to
203
+ * approve a payment to the merchant that key belongs to, so the checkout's `merchant`
204
+ * must be that merchant's name (`Agentcard sandbox` for `agentcard_sandbox`), and the
205
+ * one card capture this preparation pays must carry an envelope under that key.
206
+ */
207
+ merchantProfile?: string;
208
+ signal?: AbortSignal;
209
+ }
210
+ export interface PrepareCheckoutInput extends PrepareCheckoutOptions {
211
+ user: string;
212
+ merchant: string;
213
+ /** An integer in the currency's smallest unit (2306 for $23.06), or a decimal string in normal units ("23.06"). */
214
+ amount: number | string;
215
+ currency: string;
216
+ cardId?: string;
217
+ merchantOrigin: string;
218
+ checkoutKey: string;
219
+ timeoutMs?: number;
220
+ onPreparationCreated?: (id: string) => void;
221
+ onApprovalUrl?: (url: string) => void;
222
+ }
223
+ /** Real user consent and an unlocked device; no processor request or payment yet. */
224
+ export interface PreparedCheckout {
225
+ readonly id: string;
226
+ readonly status: 'ready';
227
+ readonly psp: PreparationProcessor;
228
+ readonly environment: 'production' | 'sandbox' | 'shared';
229
+ /** How the approved card reaches the processor: ciphertext the device produces (Adyen, `cse`) or the device's own request (`token`). */
230
+ readonly mode: PreparationMode;
231
+ readonly expiresAt: string;
232
+ readonly cardId: string;
233
+ readonly user: string;
234
+ readonly merchant: string;
235
+ /** The approved amount, an integer in the currency's smallest unit, as the API confirmed it. */
236
+ readonly amount: number;
237
+ readonly amountDisplay: string | null;
238
+ readonly currency: string;
239
+ readonly merchantOrigin: string;
240
+ readonly checkoutKey: string;
241
+ readonly paymentStatus: 'not_started';
242
+ readonly amountAuthority: 'agent';
243
+ /** The reviewed merchant profile this preparation pays, or the Fiserv key pin it pays under; absent for a processor-hosted checkout. */
244
+ readonly merchantProfile?: string;
245
+ /** The declared test endpoint and key this preparation pays instead of the profile's (VaultClientOptions.sandboxMerchants). */
246
+ readonly sandboxDeclaration?: Readonly<{
247
+ endpoint: string;
248
+ clientKey: string;
249
+ }>;
250
+ }
251
+ export declare class CheckoutPreparationError extends Error {
252
+ preparationId: string | null;
253
+ reason: string;
254
+ constructor(preparationId: string | null, reason: string);
255
+ }
256
+ export interface AuthorizeInput extends ExecutionMetadata {
257
+ /** Native Checkout defaults to TEST; LIVE requires this explicit opt-in. */
258
+ stripeCheckoutEnvironment?: 'test' | 'production';
259
+ /** Observed top-level HTTPS merchant origin; a routing hint, never payment authority. */
260
+ merchantOrigin?: string;
261
+ /** Your identifier for the person whose card should pay. */
262
+ user: string;
263
+ /** Shown to the user on the approval screen. Judged by nothing: the merchant comes from the checkout page. */
264
+ merchant: string;
265
+ /**
266
+ * Your hint at the amount: an integer in the currency's smallest unit (2306
267
+ * for $23.06), or a decimal string in normal units ("23.06"), with its ISO
268
+ * 4217 code ("usd"). Optional: the processor's own amount is the higher
269
+ * authority, read from the paused request or from the Stripe intent it
270
+ * names right before the cardholder's device replays, and the company's
271
+ * caps are judged on it. A hint lets a bad purchase be refused the moment
272
+ * you open it, and a hint that disagrees with the processor beyond one
273
+ * smallest unit is refused with nothing charged (an AmountMismatchError;
274
+ * `stage` says which check). Agentcard derives the display string; you
275
+ * never send one. Both or neither: one without the other is refused.
276
+ */
277
+ amount?: number | string;
278
+ currency?: string;
279
+ /**
280
+ * The total read off the checkout page, the lowest authority: used only
281
+ * when neither the processor's request nor your hint names an amount. The
282
+ * adapters fill it from `[data-agentcard-amount]` when a page carries one.
283
+ */
284
+ pageAmount?: {
285
+ amount: number;
286
+ currency: string;
287
+ };
288
+ /** Milliseconds from the caller's pay click until the SDK caught the card request, measured on one clock. */
289
+ payToInterceptMs?: number;
290
+ /**
291
+ * WHICH stored card should pay — a vault card id from
292
+ * GET /api/v2/vault_cards. The approval page preselects it (the human can
293
+ * still override). Omitted: the page defaults to the most recently added
294
+ * card. An id that isn't in this user's vault fails the create with a 404
295
+ * `card_not_found`.
296
+ */
297
+ cardId?: string;
298
+ /**
299
+ * The origin of the checkout page the payment form was on
300
+ * (https://shop.example.com). The adapters read it from the page; pass it
301
+ * yourself when you run your own interception. With the processor identity
302
+ * in the paused request this is what names the merchant for the company's
303
+ * presets; `merchant` above is shown to the person and judged by nothing.
304
+ */
305
+ pageOrigin?: string;
306
+ request: PausedRequest;
307
+ /** Abort if the user has not approved within this many ms. Default 15 min. */
308
+ timeoutMs?: number;
309
+ /** Stops local polling; it does not revoke a pending approval or undo a payment. */
310
+ signal?: AbortSignal;
311
+ /** Adapter-owned merchant request lifetime. A failed request retires a pending approval before replay when possible. */
312
+ merchantSignal?: AbortSignal;
313
+ /** Called before onApprovalUrl; lets a runtime reconcile an interrupted authorization. */
314
+ onAuthorizationCreated?: (authorizationId: string) => void;
315
+ /** Called once with the URL to surface to the user, if you deliver it yourself. */
316
+ onApprovalUrl?: (url: string) => void;
317
+ /** One-use preparation returned by this client. Never resumes an older request. */
318
+ preparation?: PreparedCheckout;
319
+ /**
320
+ * For a reviewed merchant profile priced by the merchant's own total: when the card
321
+ * request paused and the merchant responses this browser recorded (see
322
+ * merchant-total.ts). The adapters pass it; a runtime that intercepts on its own builds
323
+ * one from its network events, or the payment is refused before any create.
324
+ */
325
+ merchantTotal?: MerchantTotalCapture;
326
+ }
327
+ export declare class CardEncryptedError extends Error {
328
+ psp: string;
329
+ constructor(psp: string);
330
+ }
331
+ /**
332
+ * The registry requests a mode this SDK build cannot finish, before creation.
333
+ * A response in an unexpected mode after creation has an unknown payment
334
+ * outcome instead and raises PaymentOutcomeUnknownError.
335
+ */
336
+ export declare class UnsupportedModeError extends Error {
337
+ mode: string;
338
+ constructor(mode: string);
339
+ }
340
+ /**
341
+ * The recognizer says this processor is preparation-required, and no preparation
342
+ * was passed. Its card may be sent only after the cardholder approved a
343
+ * prepare(): call prepareCheckout() (or the adapters' preparation gate) before
344
+ * this request is intercepted. Thrown locally before any create or prompt, and
345
+ * terminal (retrying the same paused request without preparing fails the same
346
+ * way). The API answers 409 preparation_required for the same case.
347
+ */
348
+ export declare class PreparationRequiredError extends Error {
349
+ psp: string;
350
+ constructor(psp: string);
351
+ }
352
+ export declare class ApprovalTimeoutError extends Error {
353
+ constructor(ms: number);
354
+ }
355
+ export declare class CheckoutCancelledError extends Error {
356
+ constructor();
357
+ }
358
+ /** The reasons an org runtime may stamp when it retires an authorization; see VaultClient.cancelAuthorization. */
359
+ export type RuntimeCancelReason = 'merchant_request_aborted' | 'merchant_never_retried';
360
+ export declare const RUNTIME_CANCEL_REASONS: readonly RuntimeCancelReason[];
361
+ /** The payment may have reached the processor. Reconcile the merchant order before any new attempt. */
362
+ export declare class PaymentOutcomeUnknownError extends Error {
363
+ authorizationId: string | null;
364
+ reason: string;
365
+ constructor(authorizationId: string | null, reason: string);
366
+ }
367
+ export declare class ApprovalDeclinedError extends Error {
368
+ constructor(reason: string);
369
+ }
370
+ /**
371
+ * Agentcard refused the payment because the processor's amount did not match
372
+ * the amount the user was (or would have been) asked to approve. Nothing was
373
+ * charged. Two stages:
374
+ * - 'create': the intent already disagreed when the request was parked. No
375
+ * authorization exists (`authorizationId` is null). Per request, not per
376
+ * page: the merchant can still update the intent before confirmation, so
377
+ * the adapters keep intercepting and the next attempt is judged afresh.
378
+ * - 'pre_replay': the intent moved between create and the moment the
379
+ * cardholder's device would have sent the card. The authorization is
380
+ * `declined` with reason `amount_mismatch`.
381
+ *
382
+ * A decline in every structural sense (the adapters abort the paused request
383
+ * and quiet the page's retry exactly as for a person's "no"), so it extends
384
+ * ApprovalDeclinedError: code that already handles declines keeps working,
385
+ * and code that wants the numbers reads them here or branches on `code`.
386
+ *
387
+ * A merchant-hosted checkout (an Adyen merchant whose own server charges the card)
388
+ * has no processor read-back: its agent amount is held to the merchant's own
389
+ * checkout total, as the agent's browser read it, at stage 'create'. The SDK refuses
390
+ * that before any create, and the API refuses the same with 409 `amount_mismatch`, so a
391
+ * caller catches this one class either way; `amountSource` says whose number
392
+ * `actualCents` is, and the message names it.
393
+ */
394
+ export declare class AmountMismatchError extends ApprovalDeclinedError {
395
+ /** The declined authorization, or null for a create-time refusal (no row exists). */
396
+ authorizationId: string | null;
397
+ /** What the user was asked to approve, smallest currency unit. */
398
+ expectedCents: number;
399
+ /** What the processor (or the merchant, see `amountSource`) reported at the last check. */
400
+ actualCents: number;
401
+ /** ISO 4217 of the approved amount. */
402
+ currency: string;
403
+ /** ISO 4217 the processor reported (differs only on a currency change). */
404
+ actualCurrency: string;
405
+ /** Which check refused it. */
406
+ stage: 'create' | 'pre_replay';
407
+ /**
408
+ * Whose number `actualCents` is: the processor's ('processor'), a merchant-hosted
409
+ * merchant's own checkout total ('merchant_total'), or the amount its card request
410
+ * names ('merchant_request').
411
+ */
412
+ readonly amountSource: 'processor' | 'merchant_total' | 'merchant_request';
413
+ readonly code: "amount_mismatch";
414
+ constructor(
415
+ /** The declined authorization, or null for a create-time refusal (no row exists). */
416
+ authorizationId: string | null,
417
+ /** What the user was asked to approve, smallest currency unit. */
418
+ expectedCents: number,
419
+ /** What the processor (or the merchant, see `amountSource`) reported at the last check. */
420
+ actualCents: number,
421
+ /** ISO 4217 of the approved amount. */
422
+ currency: string,
423
+ /** ISO 4217 the processor reported (differs only on a currency change). */
424
+ actualCurrency?: string,
425
+ /** Which check refused it. */
426
+ stage?: 'create' | 'pre_replay',
427
+ /**
428
+ * Whose number `actualCents` is: the processor's ('processor'), a merchant-hosted
429
+ * merchant's own checkout total ('merchant_total'), or the amount its card request
430
+ * names ('merchant_request').
431
+ */
432
+ amountSource?: 'processor' | 'merchant_total' | 'merchant_request');
433
+ }
434
+ /**
435
+ * The PaymentIntent behind this checkout can no longer be confirmed: it was
436
+ * already charged (succeeded), is being charged (processing), is authorized
437
+ * and on hold for the merchant to capture (requires_capture), or was
438
+ * canceled. Agentcard refused rather than replay a confirm at it; the
439
+ * authorization is `declined` with reason `intent_not_confirmable`.
440
+ * Deliberately NOT "nothing was charged": for three of those four, money has
441
+ * moved or is moving. Check the intent at Stripe before retrying.
442
+ */
443
+ export declare class IntentNotConfirmableError extends ApprovalDeclinedError {
444
+ authorizationId: string;
445
+ readonly code: "intent_not_confirmable";
446
+ constructor(authorizationId: string);
447
+ }
448
+ /** Bounded processor identifiers, never a raw response or free-form description. */
449
+ export interface RazorpayProcessorError {
450
+ reason?: string;
451
+ source?: string;
452
+ step?: string;
453
+ payment_id?: string;
454
+ order_id?: string;
455
+ }
456
+ /**
457
+ * The device reported a processor request rejection. A generic processor
458
+ * code does not establish an issuer decline or prove no money moved. Read
459
+ * the bounded processor evidence and reconcile the merchant before retrying.
460
+ * The authorization remains `declined` with reason `processor_refused` for
461
+ * compatibility; no successful processor response is handed to the merchant.
462
+ */
463
+ export declare class ProcessorRefusedError extends ApprovalDeclinedError {
464
+ authorizationId: string;
465
+ pspErrorCode: string | null;
466
+ readonly code: "processor_refused";
467
+ readonly processorError: RazorpayProcessorError | null;
468
+ constructor(authorizationId: string, pspErrorCode: string | null, processorError?: RazorpayProcessorError | null);
469
+ }
470
+ /** Why Agentcard refused a payment on Adyen's TEST platform; see AdyenTestPlatformRefusedError. */
471
+ export type AdyenTestPlatformRefusal = 'adyen_test_environment_refused' | 'adyen_test_platform_requires_documented_test_card';
472
+ /**
473
+ * Agentcard refused a payment on Adyen's TEST platform, where a test account can
474
+ * read whatever is encrypted under its key. Nothing was encrypted and nothing was
475
+ * charged. `code` says which rule:
476
+ * - 'adyen_test_environment_refused': a live checkout names Adyen's test host or
477
+ * a `test_` client key. Stage 'create': the API refused it before anyone was
478
+ * asked (`authorizationId` is null) and the page's next request is refused the
479
+ * same way, so the adapters stop intercepting. Stage 'pre_replay': the
480
+ * authorization was declined right before the card would have been encrypted.
481
+ * - 'adyen_test_platform_requires_documented_test_card': a test-mode checkout on
482
+ * Adyen's test platform, where the approval page encrypts only Adyen's
483
+ * documented test cards and the cardholder's card is not one.
484
+ * A decline in every structural sense, so it extends ApprovalDeclinedError.
485
+ */
486
+ export declare class AdyenTestPlatformRefusedError extends ApprovalDeclinedError {
487
+ readonly authorizationId: string | null;
488
+ readonly code: AdyenTestPlatformRefusal;
489
+ readonly stage: 'create' | 'pre_replay';
490
+ constructor(authorizationId: string | null, code: AdyenTestPlatformRefusal, stage: 'create' | 'pre_replay');
491
+ }
492
+ /** Why a merchant-hosted payment priced by the merchant's own total was refused; see MerchantTotalError. */
493
+ export type MerchantTotalRefusal = 'merchant_total_required' | 'merchant_total_refused' | 'merchant_total_changed' | 'merchant_total_stale';
494
+ /**
495
+ * A reviewed merchant's own checkout total could not stand behind this payment, so the
496
+ * card request was held and nothing was charged. The merchant's server picks what it
497
+ * charges, so a merchant-hosted payment is priced by the total the merchant's own
498
+ * checkout responses named in this browser (the profile's amount source), never by the
499
+ * agent's number alone. `code`:
500
+ * - 'merchant_total_required': no total was sent (stage 'sdk': this runtime recorded no
501
+ * merchant responses; stage 'create': the API got none);
502
+ * - 'merchant_total_refused': the responses do not confirm one total for this order
503
+ * (`reasonCode`: no_source when none was seen, stale, refused, unreadable,
504
+ * mismatch, unbound, invalid); stage 'sdk' before any create, 'create' by the API;
505
+ * - 'merchant_total_changed': stage 'release': between the approval and the moment the
506
+ * card would have gone out, the merchant's total moved, or a request that could move
507
+ * it had not answered. The approval is retired; the card never left this browser;
508
+ * - 'merchant_total_stale': stage 'runtime': the approval came after the total was too
509
+ * old for its profile, so the API withheld the card.
510
+ * A decline in every structural sense, so it extends ApprovalDeclinedError.
511
+ */
512
+ export declare class MerchantTotalError extends ApprovalDeclinedError {
513
+ readonly authorizationId: string | null;
514
+ readonly code: MerchantTotalRefusal;
515
+ readonly stage: 'sdk' | 'create' | 'release' | 'runtime';
516
+ readonly reasonCode: string | null;
517
+ constructor(authorizationId: string | null, code: MerchantTotalRefusal, stage: 'sdk' | 'create' | 'release' | 'runtime', reasonCode: string | null, reason: string);
518
+ }
519
+ /**
520
+ * A non-2xx from the Agentcard API, carrying the status so callers can tell a
521
+ * misconfiguration from a blip. The adapters use this to decide whether
522
+ * retrying is worth anything: a 404 `connection_not_found` will answer the same
523
+ * way forever, while a 429 or a 502 will not.
524
+ */
525
+ /**
526
+ * The company's preset refused the purchase. The company that runs this
527
+ * integration put rules on its users' Vault purchases (a merchant list, a
528
+ * currency, a spend cap, a time window); this purchase is outside them.
529
+ * Nothing was charged. Two stages:
530
+ * - 'create': refused before any authorization existed (`authorizationId`
531
+ * is null); nobody was asked to approve. Per purchase, not per page: the
532
+ * next request on the same page is judged afresh.
533
+ * - 'pre_replay': refused right before the cardholder's device would have
534
+ * sent the card; the authorization is `declined` with `code` as reason.
535
+ * `code` is the rule's reason (merchant_denied, currency_denied,
536
+ * spend_rate_exceeded, time_window_denied, ...), `message` the rule's own
537
+ * statement with the company's next step, `preset` the version that judged
538
+ * it. When several presets refused the same purchase, `code`, `preset`,
539
+ * `rule` and `attachment` are the first, and `refusals` names every one. A
540
+ * decline in every structural sense (the adapters quiet the page's retry as
541
+ * for a person's "no"), so it extends ApprovalDeclinedError.
542
+ */
543
+ export declare class PresetRefusedError extends ApprovalDeclinedError {
544
+ readonly authorizationId: string | null;
545
+ readonly code: string;
546
+ readonly detail: string | null;
547
+ readonly preset: {
548
+ id: string;
549
+ version: number;
550
+ name: string;
551
+ } | null;
552
+ readonly rule: string | null;
553
+ readonly stage: 'create' | 'pre_replay';
554
+ /** The stored card the preset that refused is attached to, with its last four digits. */
555
+ readonly attachment: PresetAttachment | null;
556
+ /** The preset's name. */
557
+ readonly presetName: string | null;
558
+ /** Every preset that refused, each with its attachment, rule, code and statement; one entry when one refused. */
559
+ readonly refusals: readonly PresetRefusal[];
560
+ constructor(authorizationId: string | null, code: string, detail: string | null, preset: {
561
+ id: string;
562
+ version: number;
563
+ name: string;
564
+ } | null, rule: string | null, stage: 'create' | 'pre_replay',
565
+ /** The stored card the preset that refused is attached to, with its last four digits. */
566
+ attachment?: PresetAttachment | null, refusals?: readonly PresetRefusal[]);
567
+ }
568
+ /** The stored card a preset is attached to, with its last four digits. */
569
+ export interface PresetAttachment {
570
+ kind: 'card';
571
+ targetId: string | null;
572
+ last4: string | null;
573
+ }
574
+ /** One preset's refusal of a purchase. */
575
+ export interface PresetRefusal {
576
+ preset: {
577
+ id: string;
578
+ version: number;
579
+ name: string;
580
+ };
581
+ attachment: PresetAttachment | null;
582
+ rule: string | null;
583
+ code: string;
584
+ detail: string | null;
585
+ }
586
+ /** A decline reason only the company presets stamp (see PresetRefusedError). */
587
+ export declare const PRESET_REFUSAL_REASONS: ReadonlySet<string>;
588
+ export declare class CheckoutApiError extends Error {
589
+ status: number;
590
+ path: string;
591
+ bodyText: string;
592
+ /** The API's stable error code (`{ error: { code } }`), or null when the body carried none. */
593
+ readonly code: string | null;
594
+ /**
595
+ * The rest of the error envelope. A 409 `amount_mismatch` from create
596
+ * carries `expected_cents`, `actual_cents`, `currency`, `actual_currency`;
597
+ * an `amount_unverifiable` carries `reason`; an `intent_not_confirmable`
598
+ * carries `intent_status`.
599
+ */
600
+ readonly details: Record<string, unknown>;
601
+ constructor(status: number, path: string, bodyText: string);
602
+ /**
603
+ * True when repeating this exact call cannot succeed: a misconfiguration
604
+ * (4xx other than 429). NOT a 409 `amount_mismatch`: Stripe lets a merchant
605
+ * update an intent's amount until it is confirmed, so the next request on
606
+ * the same page may well agree. That one is a per-request failure, and
607
+ * authorize() surfaces it as AmountMismatchError before an adapter ever
608
+ * sees it here. NOT a 409 `duplicate_submission` either: the household
609
+ * already has, or already answered, the prompt for this submission, and
610
+ * once that prior authorization is declined or expired the same form is a
611
+ * new question. The adapters quiet the page's re-post the way they quiet a
612
+ * decline instead of latching the attachment.
613
+ */
614
+ get permanent(): boolean;
615
+ }
616
+ /** The client-credentials exchange was refused: the RFC 6749 error, with the status the token endpoint answered. */
617
+ export declare class CheckoutAuthError extends Error {
618
+ status: number;
619
+ code: string | null;
620
+ constructor(status: number, code: string | null, description: string | null);
621
+ }
622
+ /**
623
+ * A URL as it may appear in an error message: origin + path only. A paused
624
+ * request's URL can carry a client secret in its query string, and error
625
+ * messages travel further than anyone intends (onEvent, logs, crash reports).
626
+ */
627
+ export declare function redactUrl(raw: string): string;
628
+ export interface VaultClientOptions {
629
+ /**
630
+ * Your Agentcard OAuth client credentials. The SDK exchanges them for a
631
+ * short-lived access token and refreshes it when it expires.
632
+ *
633
+ * NOT an `sk_` API key: those are retired, and the checkout endpoints reject
634
+ * them with `client_credentials_required` because an authorization has to be
635
+ * bound to the confidential client that created it.
636
+ */
637
+ clientId: string;
638
+ clientSecret: string;
639
+ baseUrl?: string;
640
+ /**
641
+ * The credentials are a sandbox client's. Sandbox and live share one base URL, and the
642
+ * client's mode lives on Agentcard's side, so name it here when you want the sandbox recogniser: a
643
+ * fixture store on `http://127.0.0.1[:port]` or `http://localhost[:port]` is then recognised by its path
644
+ * against each processor's endpoints and paused as the processor's request would be. An `sk_test_`
645
+ * credential reads as sandbox on its own. Production never admits loopback, whatever this says about a
646
+ * production client: Agentcard refuses the create.
647
+ */
648
+ sandbox?: boolean;
649
+ /** Override the PSP registry (tests, or pinning). Defaults to the hosted list. */
650
+ registry?: Recognizer[];
651
+ fetchImpl?: typeof fetch;
652
+ /** Receives contained reporting failures that do not change checkout behavior. */
653
+ onEvent?: (event: {
654
+ type: string;
655
+ detail?: unknown;
656
+ }) => void;
657
+ pollIntervalMs?: number;
658
+ /**
659
+ * Waits before retrying a create the API answered 502 `amount_unverifiable`
660
+ * (Stripe did not answer the amount read-back) or 502 `cse_key_unavailable`
661
+ * (Adyen did not answer the public-key fetch). One retry per entry, then
662
+ * the error is thrown. Default [500, 1500]; [] disables retries.
663
+ */
664
+ unverifiableRetryDelaysMs?: number[];
665
+ /**
666
+ * The voice module: how this product approves purchases by voice, named
667
+ * once per business, with the Vault return link and the verifier address
668
+ * beside it. Leave it out for a client that approves no purchase by voice;
669
+ * `agentcard.voice.*` then throws `missing_approval_posture`. See `VoiceOptions`.
670
+ */
671
+ voice?: VoiceOptions;
672
+ /**
673
+ * Test mode only: run a merchant-hosted checkout against your own Adyen TEST
674
+ * account. Each entry arms your own endpoint as taking the card request of a
675
+ * profile Agentcard reviewed (its body rules), encrypted under your own Adyen
676
+ * TEST client key; prepare({ psp: 'adyen', environment: 'sandbox',
677
+ * merchantProfile: <that profile> }) then pays it. Declare them here, before any
678
+ * attach, so every adapter pauses the endpoint. The API accepts a declaration
679
+ * only from a test-mode client of an org Agentcard turned declarations on for,
680
+ * and the Vault encrypts only Adyen's documented test cards under a test_ key.
681
+ * Throws a TypeError at construction for a profile this build did not review, an
682
+ * endpoint the API would refuse (see declareSandboxMerchant) or a non-test key.
683
+ *
684
+ * On this client a declared profile id takes the place of the reviewed profile
685
+ * with that id: merchantProfile(id) and prepare({ merchantProfile: id }) name
686
+ * the declaration, so this client never prepares the reviewed merchant's own
687
+ * checkout. Nothing is lost on a test-mode client, which can never pay a
688
+ * reviewed profile on Adyen's live platform; use a separate client for that.
689
+ */
690
+ sandboxMerchants?: SandboxMerchantDeclaration[];
691
+ }
692
+ /** The options `new Agentcard({ … })` takes; `VaultClientOptions` is the same type under its older name. */
693
+ export type AgentcardOptions = VaultClientOptions;
694
+ export declare class VaultClient {
695
+ private readonly opts;
696
+ private readonly baseUrl;
697
+ private readonly fetch;
698
+ private readonly pollIntervalMs;
699
+ private readonly unverifiableRetryDelaysMs;
700
+ /** The recognisers the API serves (or the built-in list), before yours are merged in. */
701
+ private registry;
702
+ /** The recognisers you registered at runtime; they win over the served list on the same processor. */
703
+ private extraRecognizers;
704
+ /**
705
+ * The reviewed merchant profiles this client arms: every one this build reviewed,
706
+ * in 'observe' until a sync reads that the API enabled it (armServedProfiles).
707
+ */
708
+ private merchantProfiles;
709
+ /** This client's own sandbox declarations (sandboxMerchants), armed at construction, one per profile. */
710
+ private readonly declaredProfiles;
711
+ private readonly preparations;
712
+ private readonly usedPreparations;
713
+ /** Named at construction, or read off an `sk_test_` credential. */
714
+ private readonly sandboxNamed;
715
+ /** What the token exchange said about the client's mode, when it said anything (`livemode` or `sandbox` on the answer). */
716
+ private sandboxLearned;
717
+ /**
718
+ * The credentials are a sandbox client's: named at construction (`sandbox: true`), read off an `sk_test_`
719
+ * credential, or learned from the token exchange on an API that says the client's mode. Until one of those,
720
+ * false: a live client.
721
+ */
722
+ get sandbox(): boolean;
723
+ /** What every module shares: the token, the HTTP path, the poll settings and the language list. */
724
+ protected readonly transport: ApiTransport;
725
+ /**
726
+ * Approve purchases by voice inside your own product: connect a person once,
727
+ * create the purchase, ask for the key word, read the result. Same
728
+ * credentials, same token as the checkout calls. Needs `voice: { approval }`
729
+ * at construction; without it every verb throws `missing_approval_posture`.
730
+ */
731
+ readonly voice: VoiceModule;
732
+ /**
733
+ * The Purchase API from the same client: ask for a cart on behalf of a
734
+ * person you connected, confirm it by its hash, and name an approval the
735
+ * person already gave by voice so the API places against it and asks for
736
+ * nothing a second time. Same credentials, same token as the voice calls.
737
+ */
738
+ readonly buy: BuyModule;
739
+ /**
740
+ * The request builders: the processor requests a purchase pauses on, the
741
+ * shipped ones and yours (`requests.register`, `requests.build`).
742
+ */
743
+ readonly requests: RequestRegistry;
744
+ constructor(opts: VaultClientOptions);
745
+ /**
746
+ * The browser recognisers: the list the API serves (after `syncRegistry`)
747
+ * or the built-in one, plus the entries you register at runtime, so a store
748
+ * or a processor Agentcard does not know yet needs no release. `find(url)`
749
+ * reads the merged list, as every pause does.
750
+ */
751
+ readonly recognizers: {
752
+ /** Adds a recogniser, or replaces yours with the same `psp`. Refused (`invalid_recognizer`) without `psp`, `match`, `hosts` and `encoding`. */
753
+ register: (entry: Recognizer) => void;
754
+ /** Every recogniser a pause is judged against: yours first, then the served or built-in list. */
755
+ list: () => Recognizer[];
756
+ /** The recogniser that claims a URL, or null. */
757
+ find: (url: string) => Recognizer | null;
758
+ };
759
+ private mergedRegistry;
760
+ /** The recogniser that claims a card request (`POST` to a recognised endpoint), or null; what a paused request names as `recognizer`. */
761
+ recognizerOf(url: string, method?: string): Recognizer | null;
762
+ /** Refresh recognizers from the API so new PSPs work without a redeploy. */
763
+ syncRegistry(): Promise<void>;
764
+ /**
765
+ * The reviewed Adyen merchant profile whose card endpoint (or a sibling of it,
766
+ * the same path under another query) this URL is, with its status on this
767
+ * client; null for any other URL. Every profile this build reviewed is armed,
768
+ * in 'observe' until a sync reads that the API enabled it. The adapters pause
769
+ * these requests and judge them with classifyMerchantRequest. A raw runtime
770
+ * that pauses one must never continue a card body there unless authorize()
771
+ * paid it.
772
+ */
773
+ merchantProfileOf(url: string): MerchantProfile | null;
774
+ /** The armed profile with this id, or null. A profile id this client declared (sandboxMerchants) names its declaration, in place of the reviewed profile. */
775
+ merchantProfile(id: string): MerchantProfile | null;
776
+ /**
777
+ * Fetch.enable globs for every armed merchant profile's endpoint and its
778
+ * siblings, for a raw CDP runtime to arm beside cardUrlPatterns(). Every profile
779
+ * this build reviewed is armed from the start, so these are the same before and
780
+ * after syncRegistry; a sync changes only a profile's status.
781
+ */
782
+ merchantProfileUrlPatterns(): string[];
783
+ /** True when this request is a card tokenization we can take over. */
784
+ isCardRequest(url: string, method?: string): boolean;
785
+ /**
786
+ * What happens to a card request (by URL) whose body carries no card: null
787
+ * when it carries one, so it is a card request as usual; 'continue' when the
788
+ * recognizer marks the endpoint as one where such requests are routine and
789
+ * never ours; 'refuse' otherwise, such as a Stripe confirmation paying with
790
+ * a method this checkout never approved. The adapters ask only after their
791
+ * holds, so a request that would reuse an approved token is refused there
792
+ * first. A body that could not be read is not judged here.
793
+ */
794
+ withoutCard(url: string, body: string | null | undefined): 'continue' | 'refuse' | null;
795
+ /**
796
+ * How the card would reach the processor on this request (`token`, `cse`
797
+ * or `hosted_form`; absent on the entry means `token`), or null when the
798
+ * registry does not recognize it. The adapters read it to decide whether an
799
+ * approval outlives the page's own request: a hosted form is a navigation
800
+ * and cannot.
801
+ */
802
+ checkoutModeOf(url: string, method?: string): CheckoutMode | null;
803
+ /**
804
+ * Glob url patterns covering every host the CURRENT registry can send a card
805
+ * to — what a raw CDP connection has to hand `Fetch.enable` before any card
806
+ * request can be paused. attachToCdp calls this for you.
807
+ *
808
+ * Call syncRegistry() FIRST: without it these cover only the built-in PSPs,
809
+ * and a request the API knows about is never paused at all. Deliberately
810
+ * WIDER than the recognizers themselves (a glob cannot express an anchored
811
+ * host regex); isCardRequest is the exact check and runs on every request
812
+ * these patterns pause.
813
+ */
814
+ cardUrlPatterns(): string[];
815
+ /** Wait for real device approval before the caller starts native tokenization. */
816
+ prepareCheckout(input: PrepareCheckoutInput): Promise<PreparedCheckout>;
817
+ /** Cancel only an unconsumed preparation; a bound request is reconciled separately. */
818
+ cancelPreparation(id: string): Promise<void>;
819
+ observePreparation(id: string, guidance: 'presented_not_filled' | 'not_presented', reason?: string): Promise<void>;
820
+ reportDuplicateGuard(authorizationId: string): Promise<void>;
821
+ /**
822
+ * Hand us a paused tokenization request. We ask the cardholder to approve,
823
+ * their device supplies the card and calls the merchant, and you get back the
824
+ * response to replay into the browser. Your process never sees a card.
825
+ */
826
+ authorize(input: AuthorizeInput): Promise<ReplayResponse>;
827
+ /** A lost bind acknowledgement must never resume the request. Recover metadata only for safe cleanup. */
828
+ private retireUncertainPreparation;
829
+ /**
830
+ * Retire an authorization the runtime is done with. A 409 or missing
831
+ * response remains unknown.
832
+ *
833
+ * `merchant_request_aborted` (the default): the merchant request is gone
834
+ * and the row must still be awaiting the person with no replay started; the
835
+ * acknowledgement carries `processor_request_started: false`.
836
+ *
837
+ * `merchant_never_retried`: the page abandoned its request while the person
838
+ * decided, the adapter kept the approval for the page's retry, and none
839
+ * came. The row may already be `approved` (a token or ciphertext minted on
840
+ * the device that this runtime handed to no request), so
841
+ * `processor_request_started` says whether the processor was asked; the API
842
+ * stamps this reason only where no charge can have been made and answers
843
+ * 409 otherwise. The acknowledgement echoes the reason the row actually
844
+ * carries: a row retired earlier under the other runtime reason answers
845
+ * with that one.
846
+ */
847
+ cancelAuthorization(authorizationId: string, reason?: RuntimeCancelReason): Promise<{
848
+ /** `cancelled`, the API's own status for a withdrawn purchase since 2026-09-25; `declined` from an API before that date. */
849
+ id: string;
850
+ status: 'cancelled' | 'declined';
851
+ reason: RuntimeCancelReason;
852
+ cancelled: true;
853
+ processor_request_started: boolean;
854
+ }>;
855
+ /**
856
+ * Ask whether the page may pay with the Stripe card token an approval
857
+ * produced: a PaymentIntent confirm that carries no card and pays with
858
+ * exactly the approved payment method, card token, confirmation token or
859
+ * source. The API reads the payment from Stripe and answers only for the
860
+ * approved amount and currency on the same Stripe account; any other answer
861
+ * rejects with a CheckoutApiError whose code says why (for example
862
+ * `continuation_not_bound`, `amount_mismatch`). Nothing is charged here:
863
+ * the adapters continue the page's own request once this resolves.
864
+ */
865
+ checkStripeContinuation(authorizationId: string, request: {
866
+ url: string;
867
+ method: string;
868
+ headers: Record<string, string>;
869
+ body: string;
870
+ }): Promise<{
871
+ paymentIntentId: string;
872
+ amount: number;
873
+ currency: string;
874
+ }>;
875
+ /**
876
+ * After a merchant-hosted payment priced by the merchant's own total: what the merchant's
877
+ * confirmation says it charged (merchant-total.ts merchantChargeReport builds `report`
878
+ * from the responses this browser recorded after the card request). The API compares it
879
+ * with the approved amount and alerts Agentcard once when the merchant charged more, or
880
+ * in another currency. The adapters send it on their own; the verdict is 'equal',
881
+ * 'lower', 'higher', 'currency_mismatch', or 'unread' when no response read.
882
+ */
883
+ reportMerchantCharge(authorizationId: string, report: {
884
+ request: {
885
+ url: string;
886
+ method: string;
887
+ body: string;
888
+ };
889
+ responses: unknown[];
890
+ }): Promise<{
891
+ verdict: 'equal' | 'lower' | 'higher' | 'currency_mismatch' | 'unread';
892
+ alerted: boolean;
893
+ }>;
894
+ /**
895
+ * The merchant's own total for a paused card request whose reviewed profile is priced by
896
+ * one: the exchanges the adapter recorded (once every request that can move the total has
897
+ * answered), cut to what the profile's rules read, and the same reading the API makes.
898
+ * Refused with a MerchantTotalError before any create when nothing recorded them, one is
899
+ * still unanswered, or they do not confirm one total for this order.
900
+ */
901
+ private readMerchantTotal;
902
+ /**
903
+ * POST the create, with two typed twists: a 502 `amount_unverifiable`
904
+ * (Stripe did not answer the read-back) is retried on a short backoff
905
+ * instead of being left to the page's own retry loop, and a 409
906
+ * `amount_mismatch` becomes an AmountMismatchError at stage 'create' so the
907
+ * adapters treat it as an answered request, not a dead page.
908
+ */
909
+ private createAuthorization;
910
+ private token;
911
+ private inflight;
912
+ /**
913
+ * Exchange client credentials for an access token, reusing the cached one
914
+ * until it is nearly expired. Concurrent callers share a single in-flight
915
+ * exchange rather than each minting their own token.
916
+ */
917
+ private accessToken;
918
+ /**
919
+ * A preparation status read may retry two known connection failures, after
920
+ * 250ms and 500ms, while keeping its original approval deadline and signal.
921
+ * Only fetch and a successful response's body read belong to that retry:
922
+ * OAuth, HTTP errors, invalid JSON and every mutation remain outside it.
923
+ * The existing one-time 401 refresh carries the remaining read budget.
924
+ */
925
+ private call;
926
+ private post;
927
+ private get;
928
+ private readPreparation;
929
+ }