squarefi-bff-api-module 1.36.51 → 1.36.52

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.
@@ -12,7 +12,7 @@ export interface paths {
12
12
  };
13
13
  /**
14
14
  * List API keys
15
- * @description Returns a list of all API keys for the authenticated user.
15
+ * @description Returns the API keys of every wallet where the caller is `owner` or `admin` (other memberships are skipped).
16
16
  *
17
17
  * **Authentication**: Bearer token and x-tenant-id header required
18
18
  *
@@ -63,7 +63,7 @@ export interface paths {
63
63
  put?: never;
64
64
  /**
65
65
  * Create API key
66
- * @description Creates a new API key for the authenticated user.
66
+ * @description Creates a new API key for `wallet_id`. The caller must be `owner` or `admin` of that wallet.
67
67
  *
68
68
  * **Authentication**: Bearer token and x-tenant-id header required
69
69
  *
@@ -138,6 +138,13 @@ export interface paths {
138
138
  };
139
139
  content?: never;
140
140
  };
141
+ /** @description Caller is not owner/admin of the wallet */
142
+ 403: {
143
+ headers: {
144
+ [name: string]: unknown;
145
+ };
146
+ content?: never;
147
+ };
141
148
  };
142
149
  };
143
150
  delete?: never;
@@ -299,7 +306,7 @@ export interface paths {
299
306
  };
300
307
  /**
301
308
  * List webhooks
302
- * @description Returns a list of all webhook URLs configured for the user's wallets.
309
+ * @description Returns the webhooks of every wallet where the caller is `owner` or `admin`; a `wallet_id` filter outside that set answers 403.
303
310
  *
304
311
  * Webhook URLs receive notifications about card transactions (authorizations, clearings, OTP).
305
312
  *
@@ -409,10 +416,10 @@ export interface paths {
409
416
  * "otp": null,
410
417
  * "cardholder": {
411
418
  * "id": "uuid",
412
- * "first_name": "Paul",
413
- * "last_name": "Kashuba",
419
+ * "first_name": "Jane",
420
+ * "last_name": "Doe",
414
421
  * "phone": "+15551234567",
415
- * "email": "p.kashuba@gmail.com",
422
+ * "email": "jane.doe@example.com",
416
423
  * "kyc_level": "basic"
417
424
  * },
418
425
  * "sub_account": {
@@ -577,7 +584,7 @@ export interface paths {
577
584
  /** Format: uuid */
578
585
  id?: string;
579
586
  /** @enum {string} */
580
- status?: "completed" | "failed";
587
+ status?: "pending" | "processing" | "completed" | "failed";
581
588
  error_message?: string | null;
582
589
  /** Format: date-time */
583
590
  created_at?: string;
@@ -765,8 +772,8 @@ export interface paths {
765
772
  "application/json": {
766
773
  /** @example true */
767
774
  success?: boolean;
768
- /** @example Webhook deleted successfully */
769
- message?: string;
775
+ /** @example null */
776
+ data?: Record<string, never> | null;
770
777
  };
771
778
  };
772
779
  };
@@ -1136,6 +1143,15 @@ export interface paths {
1136
1143
  };
1137
1144
  };
1138
1145
  };
1146
+ /** @description Validation error (missing name/type, invalid fields) or wallet not found */
1147
+ 400: {
1148
+ headers: {
1149
+ [name: string]: unknown;
1150
+ };
1151
+ content: {
1152
+ "application/json": components["schemas"]["ErrorResponse"];
1153
+ };
1154
+ };
1139
1155
  /** @description Access denied */
1140
1156
  403: {
1141
1157
  headers: {
@@ -1330,7 +1346,7 @@ export interface paths {
1330
1346
  parameters: {
1331
1347
  query?: {
1332
1348
  counterparty_account_id?: string;
1333
- type?: "ACH" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE";
1349
+ type?: "ACH" | "RTP" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "INTERNAL";
1334
1350
  offset?: number;
1335
1351
  limit?: number;
1336
1352
  };
@@ -1621,7 +1637,7 @@ export interface paths {
1621
1637
  put?: never;
1622
1638
  /**
1623
1639
  * Create destination
1624
- * @description counterparty_account_id in body. User must have access to the account's wallet.
1640
+ * @description counterparty_account_id in body. Caller must be owner or admin of the account's wallet and the wallet's KYC must be APPROVED; other members receive 403.
1625
1641
  *
1626
1642
  * **Banking types**: banking_data required
1627
1643
  * **Crypto types**: crypto_data required
@@ -1641,7 +1657,7 @@ export interface paths {
1641
1657
  /** Format: uuid */
1642
1658
  counterparty_account_id: string;
1643
1659
  /** @enum {string} */
1644
- type: "ACH" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "INTERNAL";
1660
+ type: "ACH" | "RTP" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "INTERNAL";
1645
1661
  nickname?: string;
1646
1662
  banking_data?: Record<string, never>;
1647
1663
  crypto_data?: Record<string, never>;
@@ -1676,6 +1692,15 @@ export interface paths {
1676
1692
  };
1677
1693
  };
1678
1694
  };
1695
+ /** @description Validation error (type-specific payload missing or invalid, target wallet inactive, or the address country contradicts the bank code country — error code BANK_COUNTRY_MISMATCH) */
1696
+ 400: {
1697
+ headers: {
1698
+ [name: string]: unknown;
1699
+ };
1700
+ content: {
1701
+ "application/json": components["schemas"]["ErrorResponse"];
1702
+ };
1703
+ };
1679
1704
  /** @description Access denied */
1680
1705
  403: {
1681
1706
  headers: {
@@ -2037,7 +2062,7 @@ export interface paths {
2037
2062
  patch?: never;
2038
2063
  trace?: never;
2039
2064
  };
2040
- "/frontend/issuing/cards": {
2065
+ "/frontend/invoices/{wallet_id}": {
2041
2066
  parameters: {
2042
2067
  query?: never;
2043
2068
  header?: never;
@@ -2045,41 +2070,33 @@ export interface paths {
2045
2070
  cookie?: never;
2046
2071
  };
2047
2072
  /**
2048
- * List cards
2049
- * @description Retrieves a paginated list of cards for the authenticated user.
2050
- *
2051
- * **Authentication**: Bearer token with x-tenant-id header required
2052
- *
2073
+ * List invoices of a wallet
2074
+ * @description Newest first. `status` also accepts the derived OVERDUE; SENT and PARTIALLY_PAID then exclude their overdue rows, so the filterable statuses partition the list.
2053
2075
  */
2054
2076
  get: {
2055
2077
  parameters: {
2056
2078
  query?: {
2057
- /** @description Filter cards by wallet ID */
2058
- wallet_id?: string;
2059
- /** @description Filter cards by program ID */
2060
- program_id?: string;
2061
- /** @description Only cards drawing from this sub-account. */
2062
- sub_account_id?: string;
2063
- /** @description Filter cards by program sub-account type (prepaid or balance) */
2064
- sub_account_type?: "prepaid" | "balance";
2065
- /** @description Filter cards by status (matches issuing_cards.card_status).
2066
- * Accepts a single value or a comma-separated list, e.g. `status=ACTIVE,FROZEN`.
2067
- * */
2068
- status?: ("ACTIVE" | "INACTIVE" | "FROZEN" | "CANCELED" | "CLOSED" | "BLOCKED" | "FAILED" | "PENDING")[];
2069
- /** @description Filter cards by last 4 digits of the card number (partial, case-insensitive match) */
2070
- last4?: string;
2071
- /** @description Number of items to skip */
2072
- offset?: number;
2073
- /** @description Number of items to return */
2079
+ status?: "DRAFT" | "SENT" | "PARTIALLY_PAID" | "PAID" | "OVERDUE";
2080
+ counterparty_account_id?: string;
2081
+ /** @description Creation date lower bound (inclusive) */
2082
+ from_date?: string;
2083
+ /** @description Creation date upper bound (inclusive) */
2084
+ to_date?: string;
2085
+ /** @description Matches the invoice number, recipient name or notes */
2086
+ search?: string;
2074
2087
  limit?: number;
2088
+ offset?: number;
2075
2089
  };
2076
2090
  header?: never;
2077
- path?: never;
2091
+ path: {
2092
+ /** @description Wallet the invoices belong to */
2093
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2094
+ };
2078
2095
  cookie?: never;
2079
2096
  };
2080
2097
  requestBody?: never;
2081
2098
  responses: {
2082
- /** @description List of cards retrieved successfully */
2099
+ /** @description Page of invoices */
2083
2100
  200: {
2084
2101
  headers: {
2085
2102
  [name: string]: unknown;
@@ -2088,168 +2105,54 @@ export interface paths {
2088
2105
  "application/json": {
2089
2106
  /** @example true */
2090
2107
  success?: boolean;
2091
- data?: components["schemas"]["IssuingCard"][];
2092
- pagination?: {
2093
- offset?: number;
2094
- limit?: number;
2095
- total?: number;
2096
- };
2108
+ data?: components["schemas"]["Invoice"][];
2109
+ pagination?: components["schemas"]["PaginationResponse"];
2097
2110
  };
2098
2111
  };
2099
2112
  };
2100
- /** @description User not authenticated */
2101
- 403: {
2102
- headers: {
2103
- [name: string]: unknown;
2104
- };
2105
- content?: never;
2106
- };
2107
- /** @description Server error */
2108
- 500: {
2109
- headers: {
2110
- [name: string]: unknown;
2111
- };
2112
- content?: never;
2113
- };
2114
2113
  };
2115
2114
  };
2116
2115
  put?: never;
2117
2116
  /**
2118
- * Create card
2119
- * @description Creates a new card. The card account type is automatically determined based on the program configuration:
2120
- * - **Account Card**: If program.sub_account_type = 'balance', requires `sub_account_id`
2121
- * - **Standalone Card**: If program.sub_account_type = 'prepaid', creates standalone card
2122
- *
2123
- * **Authentication**: Bearer token with Authorization header and x-tenant-id header required
2124
- *
2125
- * **Important**:
2126
- * - program_id is always required
2127
- * - The program's sub_account_type determines which additional fields are required
2128
- * - For Account cards: wallet_id is automatically retrieved from the sub-account
2129
- * - For Standalone cards: wallet_id must be provided explicitly
2130
- *
2131
- * **Cardholder is required**: Every card must be associated with a cardholder.
2132
- * Create a cardholder first via `POST /frontend/issuing/cardholders`, then pass the returned `cardholder_id` here.
2117
+ * Create an invoice draft
2118
+ * @description Creates a draft invoice: currency, line items and optionally the
2119
+ * recipient (a counterparty account), a manual invoice number, a due
2120
+ * date and free-form notes. When the number is omitted the backend
2121
+ * generates <prefix>-<n>: the prefix is the first two vowels of the
2122
+ * tenant name, n continues the tenant-wide invoice sequence. The total
2123
+ * is computed from the items. Nothing is emailed until the invoice is
2124
+ * sent. Requires an
2125
+ * administrative role on the wallet.
2133
2126
  *
2134
2127
  */
2135
2128
  post: {
2136
2129
  parameters: {
2137
2130
  query?: never;
2138
2131
  header?: never;
2139
- path?: never;
2132
+ path: {
2133
+ /** @description Wallet the invoices belong to */
2134
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2135
+ };
2140
2136
  cookie?: never;
2141
2137
  };
2142
2138
  requestBody: {
2143
2139
  content: {
2144
2140
  "application/json": {
2145
- /**
2146
- * Format: uuid
2147
- * @description ID of the issuing program (determines card type)
2148
- * @example 987fcdeb-51a2-43d1-9012-345678901234
2149
- */
2150
- program_id: string;
2151
- /**
2152
- * Format: uuid
2153
- * @description ID of the sub-account (required if program.sub_account_type = 'balance')
2154
- * @example ef7f01df-b433-46cc-8d8c-3c318f1711be
2155
- */
2156
- sub_account_id?: string;
2157
- /**
2158
- * Format: uuid
2159
- * @description ID of the wallet (required for prepaid cards)
2160
- * @example 123e4567-e89b-12d3-a456-426614174000
2161
- */
2162
- wallet_id?: string;
2163
- /**
2164
- * Format: uuid
2165
- * @description ID of the cardholder to associate with this card.
2166
- * **Required.** Must be a valid cardholder ID retrieved from `GET /frontend/issuing/cardholders`
2167
- * or created via `POST /frontend/issuing/cardholders`.
2168
- * The cardholder will be automatically registered at the vendor if not already present.
2169
- *
2170
- * @example a1b2c3d4-e5f6-7890-abcd-ef1234567890
2171
- */
2172
- cardholder_id: string;
2173
- /**
2174
- * @description Name for the card
2175
- * @example My Card
2176
- */
2177
- card_name: string;
2178
- /**
2179
- * Format: uuid
2180
- * @description Optional. Binds the card to a wallet member so a scoped `user` role can
2181
- * access ONLY this card (view, sensitive data, transactions, freeze/unfreeze),
2182
- * and nothing else in the wallet. Must be the `user_data.uuid` of an
2183
- * active member of the target wallet; resolved server-side to the card's owner.
2184
- *
2185
- * @example a1b2c3d4-e5f6-7890-abcd-ef1234567890
2186
- */
2187
- assigned_user_data_uuid?: string;
2188
- /**
2189
- * Format: email
2190
- * @deprecated
2191
- * @description **Deprecated.** Use `cardholder_id` instead.
2192
- * Still accepted for backward compatibility but will be removed in a future version.
2193
- *
2194
- * @example user@example.com
2195
- */
2196
- email?: string;
2197
- /**
2198
- * @deprecated
2199
- * @description **Deprecated.** Use `cardholder_id` instead.
2200
- * Still accepted for backward compatibility but will be removed in a future version.
2201
- *
2202
- * @example +1234567890
2203
- */
2204
- mobile?: string;
2205
- /**
2206
- * @deprecated
2207
- * @description **Deprecated.** Use `cardholder_id` instead.
2208
- * Still accepted for backward compatibility but will be removed in a future version.
2209
- *
2210
- */
2211
- vendor_user_id?: string;
2212
- /**
2213
- * @description TOTAL wallet debit asked for at issuance: the issuing fee is subtracted and
2214
- * the remainder lands on the card's sub-account. Accepted only on group tariffs
2215
- * that already mandate an initial top-up (`initial_topup_usd > 0`); otherwise the
2216
- * group amount stands. Requires `currency_id`.
2217
- *
2218
- * @example 100
2219
- */
2220
- initial_topup?: number;
2221
- /**
2222
- * Format: uuid
2223
- * @description Wallet currency to debit for the issuing fee / initial top-up.
2224
- * **Required whenever the group tariff carries a fee or a top-up** — the request
2225
- * is refused with 400 otherwise.
2226
- *
2227
- */
2228
- currency_id?: string;
2229
- /**
2230
- * Format: uuid
2231
- * @description Client-generated idempotency key. A replay with the same value returns the
2232
- * already-created card (same wallet) instead of issuing/charging again; a value
2233
- * already used by another request is refused with 409. Globally unique.
2234
- *
2235
- */
2236
- request_id?: string;
2141
+ /** Format: uuid */
2142
+ counterparty_account_id?: string;
2143
+ invoice_number?: string;
2144
+ /** Format: uuid */
2145
+ currency_id: string;
2146
+ /** Format: date */
2147
+ due_date?: string;
2148
+ description?: string;
2149
+ items: components["schemas"]["InvoiceItemInput"][];
2237
2150
  };
2238
2151
  };
2239
2152
  };
2240
2153
  responses: {
2241
- /** @description Card created successfully. `data` is the same fully-decorated card shape as
2242
- * `GET /frontend/issuing/cards/{card_id}` — including `data.id` and
2243
- * `data.sub_account_id` (the sub-account the card spends from; for prepaid cards it
2244
- * is provisioned by this call).
2245
- *
2246
- * When the group tariff carried an issuing fee / initial top-up, `data` additionally
2247
- * reports the money outcome: `initial_topup_status` is `completed` when the top-up
2248
- * landed (or there was none to land), `topup_skipped` when no sub-account could
2249
- * receive it (nothing debited), and `topup_failed` when the top-up transfer failed —
2250
- * the card exists either way; `initial_topup_error` carries the failure reason.
2251
- * */
2252
- 201: {
2154
+ /** @description Draft created */
2155
+ 200: {
2253
2156
  headers: {
2254
2157
  [name: string]: unknown;
2255
2158
  };
@@ -2257,81 +2160,37 @@ export interface paths {
2257
2160
  "application/json": {
2258
2161
  /** @example true */
2259
2162
  success?: boolean;
2260
- data?: components["schemas"]["IssuingCard"] & {
2261
- /**
2262
- * @description Outcome of the issuance-time initial top-up. Present only when the tariff charged at issuance.
2263
- * @enum {string}
2264
- */
2265
- initial_topup_status?: "completed" | "topup_failed" | "topup_skipped";
2266
- /** @description Reason the initial top-up was skipped or failed. Present only when initial_topup_status is not `completed`. */
2267
- initial_topup_error?: string;
2163
+ data?: components["schemas"]["Invoice"] & {
2164
+ items?: components["schemas"]["InvoiceItem"][];
2268
2165
  };
2269
- /** @example Card created successfully */
2270
- message?: string;
2271
2166
  };
2272
2167
  };
2273
2168
  };
2274
- /** @description Bad Request - One of the following:
2275
- * - Missing program_id
2276
- * - Missing required fields based on program type
2277
- * - Unsupported program type
2278
- * */
2169
+ /** @description Validation error */
2279
2170
  400: {
2280
2171
  headers: {
2281
2172
  [name: string]: unknown;
2282
2173
  };
2283
2174
  content: {
2284
- "application/json": {
2285
- /** @example false */
2286
- success?: boolean;
2287
- error?: string;
2288
- };
2289
- };
2290
- };
2291
- /** @description Forbidden - One of the following:
2292
- * - Sub-account not found
2293
- * - Wallet not found or access denied
2294
- * - Program not available for this tenant
2295
- * - Program vendor ID is not configured
2296
- * */
2297
- 403: {
2298
- headers: {
2299
- [name: string]: unknown;
2300
- };
2301
- content: {
2302
- "application/json": {
2303
- /** @example false */
2304
- success?: boolean;
2305
- error?: string;
2306
- };
2175
+ "application/json": components["schemas"]["ErrorResponse"];
2307
2176
  };
2308
2177
  };
2309
- /** @description Program not found */
2310
- 404: {
2178
+ /** @description Invoice number is already taken in this wallet */
2179
+ 409: {
2311
2180
  headers: {
2312
2181
  [name: string]: unknown;
2313
2182
  };
2314
2183
  content: {
2315
- "application/json": {
2316
- /** @example false */
2317
- success?: boolean;
2318
- /** @example Program not found */
2319
- error?: string;
2320
- };
2184
+ "application/json": components["schemas"]["ErrorResponse"];
2321
2185
  };
2322
2186
  };
2323
- /** @description Internal Server Error */
2324
- 500: {
2187
+ /** @description Rate limit exceeded */
2188
+ 429: {
2325
2189
  headers: {
2326
2190
  [name: string]: unknown;
2327
2191
  };
2328
2192
  content: {
2329
- "application/json": {
2330
- /** @example false */
2331
- success?: boolean;
2332
- /** @example Failed to create card */
2333
- error?: string;
2334
- };
2193
+ "application/json": components["schemas"]["ErrorResponse"];
2335
2194
  };
2336
2195
  };
2337
2196
  };
@@ -2342,7 +2201,7 @@ export interface paths {
2342
2201
  patch?: never;
2343
2202
  trace?: never;
2344
2203
  };
2345
- "/frontend/issuing/cards/{card_id}": {
2204
+ "/frontend/invoices/{wallet_id}/{id}": {
2346
2205
  parameters: {
2347
2206
  query?: never;
2348
2207
  header?: never;
@@ -2350,9 +2209,774 @@ export interface paths {
2350
2209
  cookie?: never;
2351
2210
  };
2352
2211
  /**
2353
- * Get card
2354
- * @description Retrieves detailed information about a specific card.
2355
- *
2212
+ * Get an invoice
2213
+ * @description Invoice details with its line items and linked payments.
2214
+ */
2215
+ get: {
2216
+ parameters: {
2217
+ query?: never;
2218
+ header?: never;
2219
+ path: {
2220
+ /** @description Wallet the invoices belong to */
2221
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2222
+ id: components["parameters"]["InvoiceId"];
2223
+ };
2224
+ cookie?: never;
2225
+ };
2226
+ requestBody?: never;
2227
+ responses: {
2228
+ /** @description Invoice with items and payments */
2229
+ 200: {
2230
+ headers: {
2231
+ [name: string]: unknown;
2232
+ };
2233
+ content: {
2234
+ "application/json": {
2235
+ /** @example true */
2236
+ success?: boolean;
2237
+ data?: components["schemas"]["Invoice"] & {
2238
+ items?: components["schemas"]["InvoiceItem"][];
2239
+ payments?: components["schemas"]["InvoicePayment"][];
2240
+ };
2241
+ };
2242
+ };
2243
+ };
2244
+ /** @description Invoice not found */
2245
+ 404: {
2246
+ headers: {
2247
+ [name: string]: unknown;
2248
+ };
2249
+ content: {
2250
+ "application/json": components["schemas"]["ErrorResponse"];
2251
+ };
2252
+ };
2253
+ };
2254
+ };
2255
+ put?: never;
2256
+ post?: never;
2257
+ /**
2258
+ * Delete an invoice draft
2259
+ * @description Draft-only. A sent invoice cannot be deleted.
2260
+ */
2261
+ delete: {
2262
+ parameters: {
2263
+ query?: never;
2264
+ header?: never;
2265
+ path: {
2266
+ /** @description Wallet the invoices belong to */
2267
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2268
+ id: components["parameters"]["InvoiceId"];
2269
+ };
2270
+ cookie?: never;
2271
+ };
2272
+ requestBody?: never;
2273
+ responses: {
2274
+ /** @description Draft deleted */
2275
+ 200: {
2276
+ headers: {
2277
+ [name: string]: unknown;
2278
+ };
2279
+ content: {
2280
+ "application/json": {
2281
+ /** @example true */
2282
+ success?: boolean;
2283
+ data?: {
2284
+ /** Format: uuid */
2285
+ id?: string;
2286
+ /** @example true */
2287
+ deleted?: boolean;
2288
+ };
2289
+ };
2290
+ };
2291
+ };
2292
+ /** @description Invoice is not a draft anymore */
2293
+ 409: {
2294
+ headers: {
2295
+ [name: string]: unknown;
2296
+ };
2297
+ content: {
2298
+ "application/json": components["schemas"]["ErrorResponse"];
2299
+ };
2300
+ };
2301
+ };
2302
+ };
2303
+ options?: never;
2304
+ head?: never;
2305
+ /**
2306
+ * Edit an invoice draft
2307
+ * @description Draft-only. `items` fully replaces the line list; explicit null clears `counterparty_account_id`, `due_date` or `description`.
2308
+ */
2309
+ patch: {
2310
+ parameters: {
2311
+ query?: never;
2312
+ header?: never;
2313
+ path: {
2314
+ /** @description Wallet the invoices belong to */
2315
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2316
+ id: components["parameters"]["InvoiceId"];
2317
+ };
2318
+ cookie?: never;
2319
+ };
2320
+ requestBody: {
2321
+ content: {
2322
+ "application/json": {
2323
+ /** Format: uuid */
2324
+ counterparty_account_id?: string | null;
2325
+ invoice_number?: string;
2326
+ /** Format: uuid */
2327
+ currency_id?: string;
2328
+ /** Format: date */
2329
+ due_date?: string | null;
2330
+ description?: string | null;
2331
+ items?: components["schemas"]["InvoiceItemInput"][];
2332
+ };
2333
+ };
2334
+ };
2335
+ responses: {
2336
+ /** @description Updated draft */
2337
+ 200: {
2338
+ headers: {
2339
+ [name: string]: unknown;
2340
+ };
2341
+ content: {
2342
+ "application/json": {
2343
+ /** @example true */
2344
+ success?: boolean;
2345
+ data?: components["schemas"]["Invoice"] & {
2346
+ items?: components["schemas"]["InvoiceItem"][];
2347
+ };
2348
+ };
2349
+ };
2350
+ };
2351
+ /** @description Invoice is not editable anymore (already sent) */
2352
+ 409: {
2353
+ headers: {
2354
+ [name: string]: unknown;
2355
+ };
2356
+ content: {
2357
+ "application/json": components["schemas"]["ErrorResponse"];
2358
+ };
2359
+ };
2360
+ };
2361
+ };
2362
+ trace?: never;
2363
+ };
2364
+ "/frontend/invoices/{wallet_id}/{id}/send": {
2365
+ parameters: {
2366
+ query?: never;
2367
+ header?: never;
2368
+ path?: never;
2369
+ cookie?: never;
2370
+ };
2371
+ get?: never;
2372
+ put?: never;
2373
+ /**
2374
+ * Send an invoice
2375
+ * @description Emails the invoice (PDF attached) to the recipient and marks it SENT.
2376
+ * The recipient is the supplied `recipient_email`, or the counterparty
2377
+ * account's email; without either the send is refused. Requires a due
2378
+ * date and at least one line item. Recipient details are snapshotted
2379
+ * onto the invoice — later counterparty edits do not change the issued
2380
+ * document. Re-sending a SENT invoice re-emails it without any state
2381
+ * change.
2382
+ *
2383
+ */
2384
+ post: {
2385
+ parameters: {
2386
+ query?: never;
2387
+ header?: never;
2388
+ path: {
2389
+ /** @description Wallet the invoices belong to */
2390
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2391
+ id: components["parameters"]["InvoiceId"];
2392
+ };
2393
+ cookie?: never;
2394
+ };
2395
+ requestBody?: {
2396
+ content: {
2397
+ "application/json": {
2398
+ /** Format: email */
2399
+ recipient_email?: string;
2400
+ };
2401
+ };
2402
+ };
2403
+ responses: {
2404
+ /** @description Invoice sent */
2405
+ 200: {
2406
+ headers: {
2407
+ [name: string]: unknown;
2408
+ };
2409
+ content: {
2410
+ "application/json": {
2411
+ /** @example true */
2412
+ success?: boolean;
2413
+ data?: components["schemas"]["Invoice"];
2414
+ };
2415
+ };
2416
+ };
2417
+ /** @description Missing recipient email, due date or line items */
2418
+ 400: {
2419
+ headers: {
2420
+ [name: string]: unknown;
2421
+ };
2422
+ content: {
2423
+ "application/json": components["schemas"]["ErrorResponse"];
2424
+ };
2425
+ };
2426
+ /** @description Invoice cannot be sent in its current status */
2427
+ 409: {
2428
+ headers: {
2429
+ [name: string]: unknown;
2430
+ };
2431
+ content: {
2432
+ "application/json": components["schemas"]["ErrorResponse"];
2433
+ };
2434
+ };
2435
+ /** @description The invoice email could not be delivered */
2436
+ 503: {
2437
+ headers: {
2438
+ [name: string]: unknown;
2439
+ };
2440
+ content: {
2441
+ "application/json": components["schemas"]["ErrorResponse"];
2442
+ };
2443
+ };
2444
+ };
2445
+ };
2446
+ delete?: never;
2447
+ options?: never;
2448
+ head?: never;
2449
+ patch?: never;
2450
+ trace?: never;
2451
+ };
2452
+ "/frontend/invoices/{wallet_id}/{id}/pdf": {
2453
+ parameters: {
2454
+ query?: never;
2455
+ header?: never;
2456
+ path?: never;
2457
+ cookie?: never;
2458
+ };
2459
+ /**
2460
+ * Download the invoice PDF
2461
+ * @description Generated on the fly and streamed; nothing is persisted.
2462
+ */
2463
+ get: {
2464
+ parameters: {
2465
+ query?: never;
2466
+ header?: never;
2467
+ path: {
2468
+ /** @description Wallet the invoices belong to */
2469
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2470
+ id: components["parameters"]["InvoiceId"];
2471
+ };
2472
+ cookie?: never;
2473
+ };
2474
+ requestBody?: never;
2475
+ responses: {
2476
+ /** @description PDF file */
2477
+ 200: {
2478
+ headers: {
2479
+ [name: string]: unknown;
2480
+ };
2481
+ content: {
2482
+ "application/pdf": string;
2483
+ };
2484
+ };
2485
+ /** @description Invoice not found */
2486
+ 404: {
2487
+ headers: {
2488
+ [name: string]: unknown;
2489
+ };
2490
+ content: {
2491
+ "application/json": components["schemas"]["ErrorResponse"];
2492
+ };
2493
+ };
2494
+ };
2495
+ };
2496
+ put?: never;
2497
+ post?: never;
2498
+ delete?: never;
2499
+ options?: never;
2500
+ head?: never;
2501
+ patch?: never;
2502
+ trace?: never;
2503
+ };
2504
+ "/frontend/invoices/{wallet_id}/{id}/payments": {
2505
+ parameters: {
2506
+ query?: never;
2507
+ header?: never;
2508
+ path?: never;
2509
+ cookie?: never;
2510
+ };
2511
+ get?: never;
2512
+ put?: never;
2513
+ /**
2514
+ * Link an incoming order as a payment
2515
+ * @description Manually links a settled incoming (deposit) order of the wallet to the
2516
+ * invoice. The order must have credited the invoice currency and must
2517
+ * not be linked to any other invoice; it always counts with its full
2518
+ * credited amount. The invoice moves to PARTIALLY_PAID or PAID depending
2519
+ * on the covered total.
2520
+ *
2521
+ */
2522
+ post: {
2523
+ parameters: {
2524
+ query?: never;
2525
+ header?: never;
2526
+ path: {
2527
+ /** @description Wallet the invoices belong to */
2528
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2529
+ id: components["parameters"]["InvoiceId"];
2530
+ };
2531
+ cookie?: never;
2532
+ };
2533
+ requestBody: {
2534
+ content: {
2535
+ "application/json": {
2536
+ /**
2537
+ * Format: uuid
2538
+ * @description Order id (the `id` field of the order endpoints)
2539
+ */
2540
+ order_id: string;
2541
+ };
2542
+ };
2543
+ };
2544
+ responses: {
2545
+ /** @description Payment linked; the updated invoice is returned */
2546
+ 200: {
2547
+ headers: {
2548
+ [name: string]: unknown;
2549
+ };
2550
+ content: {
2551
+ "application/json": {
2552
+ /** @example true */
2553
+ success?: boolean;
2554
+ data?: components["schemas"]["Invoice"] & {
2555
+ payment?: components["schemas"]["InvoicePayment"];
2556
+ };
2557
+ };
2558
+ };
2559
+ };
2560
+ /** @description The order cannot be linked (not found, not incoming, not settled, wrong currency, already linked) */
2561
+ 400: {
2562
+ headers: {
2563
+ [name: string]: unknown;
2564
+ };
2565
+ content: {
2566
+ "application/json": components["schemas"]["ErrorResponse"];
2567
+ };
2568
+ };
2569
+ /** @description The invoice is not in a payable status */
2570
+ 409: {
2571
+ headers: {
2572
+ [name: string]: unknown;
2573
+ };
2574
+ content: {
2575
+ "application/json": components["schemas"]["ErrorResponse"];
2576
+ };
2577
+ };
2578
+ };
2579
+ };
2580
+ delete?: never;
2581
+ options?: never;
2582
+ head?: never;
2583
+ patch?: never;
2584
+ trace?: never;
2585
+ };
2586
+ "/frontend/invoices/{wallet_id}/{id}/payments/{payment_id}": {
2587
+ parameters: {
2588
+ query?: never;
2589
+ header?: never;
2590
+ path?: never;
2591
+ cookie?: never;
2592
+ };
2593
+ get?: never;
2594
+ put?: never;
2595
+ post?: never;
2596
+ /**
2597
+ * Unlink a payment from an invoice
2598
+ * @description Removes a manually linked payment (wrong order, wrong invoice). The
2599
+ * order becomes linkable again and the invoice totals are recomputed:
2600
+ * a fully paid invoice moves back to PARTIALLY_PAID, or to SENT once no
2601
+ * payments remain. Requires an administrative role on the wallet.
2602
+ *
2603
+ */
2604
+ delete: {
2605
+ parameters: {
2606
+ query?: never;
2607
+ header?: never;
2608
+ path: {
2609
+ /** @description Wallet the invoices belong to */
2610
+ wallet_id: components["parameters"]["InvoiceWalletId"];
2611
+ id: components["parameters"]["InvoiceId"];
2612
+ /** @description Id of the linked payment (from the invoice details `payments` list) */
2613
+ payment_id: components["parameters"]["InvoicePaymentId"];
2614
+ };
2615
+ cookie?: never;
2616
+ };
2617
+ requestBody?: never;
2618
+ responses: {
2619
+ /** @description Payment unlinked; the updated invoice is returned */
2620
+ 200: {
2621
+ headers: {
2622
+ [name: string]: unknown;
2623
+ };
2624
+ content: {
2625
+ "application/json": {
2626
+ /** @example true */
2627
+ success?: boolean;
2628
+ data?: components["schemas"]["Invoice"];
2629
+ };
2630
+ };
2631
+ };
2632
+ /** @description Invoice or payment not found */
2633
+ 404: {
2634
+ headers: {
2635
+ [name: string]: unknown;
2636
+ };
2637
+ content: {
2638
+ "application/json": components["schemas"]["ErrorResponse"];
2639
+ };
2640
+ };
2641
+ /** @description Another payment operation on this invoice is in progress */
2642
+ 409: {
2643
+ headers: {
2644
+ [name: string]: unknown;
2645
+ };
2646
+ content: {
2647
+ "application/json": components["schemas"]["ErrorResponse"];
2648
+ };
2649
+ };
2650
+ };
2651
+ };
2652
+ options?: never;
2653
+ head?: never;
2654
+ patch?: never;
2655
+ trace?: never;
2656
+ };
2657
+ "/frontend/issuing/cards": {
2658
+ parameters: {
2659
+ query?: never;
2660
+ header?: never;
2661
+ path?: never;
2662
+ cookie?: never;
2663
+ };
2664
+ /**
2665
+ * List cards
2666
+ * @description Retrieves a paginated list of cards for the authenticated user.
2667
+ *
2668
+ * **Authentication**: Bearer token with x-tenant-id header required
2669
+ *
2670
+ */
2671
+ get: {
2672
+ parameters: {
2673
+ query: {
2674
+ /** @description Wallet ID (required) — cards are scoped to this wallet */
2675
+ wallet_id: string;
2676
+ /** @description Filter cards by program ID */
2677
+ program_id?: string;
2678
+ /** @description Only cards drawing from this sub-account. */
2679
+ sub_account_id?: string;
2680
+ /** @description Filter cards by program sub-account type (prepaid or balance) */
2681
+ sub_account_type?: "prepaid" | "balance";
2682
+ /** @description Filter cards by status (matches issuing_cards.card_status).
2683
+ * Accepts a single value or a comma-separated list, e.g. `status=ACTIVE,FROZEN`.
2684
+ * */
2685
+ status?: ("ACTIVE" | "INACTIVE" | "FROZEN" | "CANCELED" | "CLOSED" | "BLOCKED" | "FAILED" | "PENDING")[];
2686
+ /** @description Filter cards by last 4 digits of the card number (partial, case-insensitive match) */
2687
+ last4?: string;
2688
+ /** @description Number of items to skip */
2689
+ offset?: number;
2690
+ /** @description Number of items to return */
2691
+ limit?: number;
2692
+ };
2693
+ header?: never;
2694
+ path?: never;
2695
+ cookie?: never;
2696
+ };
2697
+ requestBody?: never;
2698
+ responses: {
2699
+ /** @description List of cards retrieved successfully */
2700
+ 200: {
2701
+ headers: {
2702
+ [name: string]: unknown;
2703
+ };
2704
+ content: {
2705
+ "application/json": {
2706
+ /** @example true */
2707
+ success?: boolean;
2708
+ data?: components["schemas"]["IssuingCard"][];
2709
+ pagination?: {
2710
+ offset?: number;
2711
+ limit?: number;
2712
+ total?: number;
2713
+ };
2714
+ };
2715
+ };
2716
+ };
2717
+ /** @description User not authenticated */
2718
+ 403: {
2719
+ headers: {
2720
+ [name: string]: unknown;
2721
+ };
2722
+ content?: never;
2723
+ };
2724
+ /** @description Server error */
2725
+ 500: {
2726
+ headers: {
2727
+ [name: string]: unknown;
2728
+ };
2729
+ content?: never;
2730
+ };
2731
+ };
2732
+ };
2733
+ put?: never;
2734
+ /**
2735
+ * Create card
2736
+ * @description Creates a new card. The card account type is automatically determined based on the program configuration:
2737
+ * - **Account Card**: If program.sub_account_type = 'balance', requires `sub_account_id`
2738
+ * - **Standalone Card**: If program.sub_account_type = 'prepaid', creates standalone card
2739
+ *
2740
+ * **Authentication**: Bearer token with Authorization header and x-tenant-id header required
2741
+ *
2742
+ * **Important**:
2743
+ * - program_id is always required
2744
+ * - The program's sub_account_type determines which additional fields are required
2745
+ * - `wallet_id` is always required in the body — the caller must be owner/admin of that wallet;
2746
+ * for balance cards it is additionally re-checked against the sub-account's wallet
2747
+ *
2748
+ * **Cardholder**: every card is issued to an ACTIVE (submitted) cardholder. Pass `cardholder_id`,
2749
+ * or omit it to use the cardholder linked to `assigned_user_data_uuid` (else to the caller) —
2750
+ * 400 `CARDHOLDER_NOT_LINKED` when none is linked. Card creation never registers anyone at the vendor.
2751
+ *
2752
+ */
2753
+ post: {
2754
+ parameters: {
2755
+ query?: never;
2756
+ header?: never;
2757
+ path?: never;
2758
+ cookie?: never;
2759
+ };
2760
+ requestBody: {
2761
+ content: {
2762
+ "application/json": {
2763
+ /**
2764
+ * Format: uuid
2765
+ * @description ID of the issuing program (determines card type)
2766
+ * @example 987fcdeb-51a2-43d1-9012-345678901234
2767
+ */
2768
+ program_id: string;
2769
+ /**
2770
+ * Format: uuid
2771
+ * @description ID of the sub-account (required if program.sub_account_type = 'balance')
2772
+ * @example ef7f01df-b433-46cc-8d8c-3c318f1711be
2773
+ */
2774
+ sub_account_id?: string;
2775
+ /**
2776
+ * Format: uuid
2777
+ * @description ID of the wallet (required)
2778
+ * @example 123e4567-e89b-12d3-a456-426614174000
2779
+ */
2780
+ wallet_id?: string;
2781
+ /**
2782
+ * Format: uuid
2783
+ * @description ID of the cardholder to associate with this card. Optional — when omitted the
2784
+ * cardholder linked to `assigned_user_data_uuid` (else to the caller) is used.
2785
+ * The cardholder must already be ACTIVE (submitted via `POST /frontend/issuing/cardholders/{id}/submit`).
2786
+ *
2787
+ * @example a1b2c3d4-e5f6-7890-abcd-ef1234567890
2788
+ */
2789
+ cardholder_id?: string;
2790
+ /**
2791
+ * @description Name for the card
2792
+ * @example My Card
2793
+ */
2794
+ card_name: string;
2795
+ /**
2796
+ * Format: uuid
2797
+ * @description Optional. Binds the card to a wallet member so a scoped `user` role can
2798
+ * access ONLY this card (view, sensitive data, transactions, freeze/unfreeze),
2799
+ * and nothing else in the wallet. Must be the `user_data.uuid` of an
2800
+ * active member of the target wallet; resolved server-side to the card's owner.
2801
+ *
2802
+ * @example a1b2c3d4-e5f6-7890-abcd-ef1234567890
2803
+ */
2804
+ assigned_user_data_uuid?: string;
2805
+ /**
2806
+ * Format: email
2807
+ * @deprecated
2808
+ * @description **Deprecated.** Use `cardholder_id` instead.
2809
+ * Ignored (a deprecation warning is logged) — contact data comes from the cardholder record.
2810
+ *
2811
+ * @example user@example.com
2812
+ */
2813
+ email?: string;
2814
+ /**
2815
+ * @deprecated
2816
+ * @description **Deprecated.** Use `cardholder_id` instead.
2817
+ * Ignored (a deprecation warning is logged) — contact data comes from the cardholder record.
2818
+ *
2819
+ * @example +1234567890
2820
+ */
2821
+ mobile?: string;
2822
+ /**
2823
+ * @deprecated
2824
+ * @description **Deprecated.** Use `cardholder_id` instead.
2825
+ * Ignored (a deprecation warning is logged) — contact data comes from the cardholder record.
2826
+ *
2827
+ */
2828
+ vendor_user_id?: string;
2829
+ /**
2830
+ * @description TOTAL wallet debit asked for at issuance: the issuing fee is subtracted and
2831
+ * the remainder lands on the card's sub-account. Accepted only on group tariffs
2832
+ * that already mandate an initial top-up (`initial_topup_usd > 0`); otherwise the
2833
+ * group amount stands. Requires `currency_id`.
2834
+ *
2835
+ * @example 100
2836
+ */
2837
+ initial_topup?: number;
2838
+ /**
2839
+ * Format: uuid
2840
+ * @description Wallet currency to debit for the issuing fee / initial top-up.
2841
+ * **Required whenever the group tariff carries a fee or a top-up** — the request
2842
+ * is refused with 400 otherwise.
2843
+ *
2844
+ */
2845
+ currency_id?: string;
2846
+ /**
2847
+ * Format: uuid
2848
+ * @description Client-generated idempotency key. A replay with the same value returns the
2849
+ * already-created card (same wallet) instead of issuing/charging again; a value
2850
+ * already used by another request is refused with 409. Globally unique.
2851
+ *
2852
+ */
2853
+ request_id?: string;
2854
+ };
2855
+ };
2856
+ };
2857
+ responses: {
2858
+ /** @description Card created successfully. `data` is the same fully-decorated card shape as
2859
+ * `GET /frontend/issuing/cards/{card_id}` — including `data.id` and
2860
+ * `data.sub_account_id` (the sub-account the card spends from; for prepaid cards it
2861
+ * is provisioned by this call).
2862
+ *
2863
+ * When the group tariff carried an issuing fee / initial top-up, `data` additionally
2864
+ * reports the money outcome: `initial_topup_status` is `completed` when the top-up
2865
+ * landed (or there was none to land), `topup_skipped` when no sub-account could
2866
+ * receive it (nothing debited), and `topup_failed` when the top-up transfer failed —
2867
+ * the card exists either way; `initial_topup_error` carries the failure reason.
2868
+ * */
2869
+ 201: {
2870
+ headers: {
2871
+ [name: string]: unknown;
2872
+ };
2873
+ content: {
2874
+ "application/json": {
2875
+ /** @example true */
2876
+ success?: boolean;
2877
+ data?: components["schemas"]["IssuingCard"] & {
2878
+ /**
2879
+ * @description Outcome of the issuance-time initial top-up. Present only when the tariff charged at issuance.
2880
+ * @enum {string}
2881
+ */
2882
+ initial_topup_status?: "completed" | "topup_failed" | "topup_skipped";
2883
+ /** @description Reason the initial top-up was skipped or failed. Present only when initial_topup_status is not `completed`. */
2884
+ initial_topup_error?: string;
2885
+ };
2886
+ /** @example Card created successfully */
2887
+ message?: string;
2888
+ };
2889
+ };
2890
+ };
2891
+ /** @description Bad Request - One of the following:
2892
+ * - Missing program_id
2893
+ * - Missing required fields based on program type
2894
+ * - Unsupported program type
2895
+ * */
2896
+ 400: {
2897
+ headers: {
2898
+ [name: string]: unknown;
2899
+ };
2900
+ content: {
2901
+ "application/json": {
2902
+ /** @example false */
2903
+ success?: boolean;
2904
+ error?: string;
2905
+ };
2906
+ };
2907
+ };
2908
+ /** @description Forbidden - One of the following:
2909
+ * - Sub-account not found
2910
+ * - Wallet not found or access denied
2911
+ * - Program not available for this tenant
2912
+ * - Program vendor ID is not configured
2913
+ * */
2914
+ 403: {
2915
+ headers: {
2916
+ [name: string]: unknown;
2917
+ };
2918
+ content: {
2919
+ "application/json": {
2920
+ /** @example false */
2921
+ success?: boolean;
2922
+ error?: string;
2923
+ };
2924
+ };
2925
+ };
2926
+ /** @description Program not found */
2927
+ 404: {
2928
+ headers: {
2929
+ [name: string]: unknown;
2930
+ };
2931
+ content: {
2932
+ "application/json": {
2933
+ /** @example false */
2934
+ success?: boolean;
2935
+ /** @example Program not found */
2936
+ error?: string;
2937
+ };
2938
+ };
2939
+ };
2940
+ /** @description `request_id` was already used by another card request (replay refused) */
2941
+ 409: {
2942
+ headers: {
2943
+ [name: string]: unknown;
2944
+ };
2945
+ content?: never;
2946
+ };
2947
+ /** @description Internal Server Error */
2948
+ 500: {
2949
+ headers: {
2950
+ [name: string]: unknown;
2951
+ };
2952
+ content: {
2953
+ "application/json": {
2954
+ /** @example false */
2955
+ success?: boolean;
2956
+ /** @example Failed to create card */
2957
+ error?: string;
2958
+ };
2959
+ };
2960
+ };
2961
+ };
2962
+ };
2963
+ delete?: never;
2964
+ options?: never;
2965
+ head?: never;
2966
+ patch?: never;
2967
+ trace?: never;
2968
+ };
2969
+ "/frontend/issuing/cards/{card_id}": {
2970
+ parameters: {
2971
+ query?: never;
2972
+ header?: never;
2973
+ path?: never;
2974
+ cookie?: never;
2975
+ };
2976
+ /**
2977
+ * Get card
2978
+ * @description Retrieves detailed information about a specific card.
2979
+ *
2356
2980
  * **Authentication**: Bearer token with x-tenant-id header required
2357
2981
  *
2358
2982
  * **Access Control**: User must have access to the card
@@ -2383,31 +3007,24 @@ export interface paths {
2383
3007
  };
2384
3008
  };
2385
3009
  };
2386
- /** @description Access denied to this card */
3010
+ /** @description Access denied — also returned when the card does not exist or is not visible to the caller */
2387
3011
  403: {
2388
3012
  headers: {
2389
3013
  [name: string]: unknown;
2390
3014
  };
2391
3015
  content?: never;
2392
3016
  };
2393
- /** @description Card not found */
2394
- 404: {
2395
- headers: {
2396
- [name: string]: unknown;
2397
- };
2398
- content?: never;
2399
- };
2400
3017
  };
2401
3018
  };
2402
3019
  put?: never;
2403
3020
  post?: never;
2404
3021
  /**
2405
3022
  * Delete card
2406
- * @description Permanently deletes a card. This action cannot be undone.
3023
+ * @description Closes the card at the vendor and sets its status to `CANCELED`. The record is retained (still listable), the action cannot be undone, and a second call answers 400 (`already deleted`).
2407
3024
  *
2408
3025
  * **Authentication**: Bearer token with x-tenant-id header required
2409
3026
  *
2410
- * **Access Control**: User must have access to the card
3027
+ * **Access Control**: Wallet owner or admin of the card's wallet
2411
3028
  *
2412
3029
  */
2413
3030
  delete: {
@@ -2436,20 +3053,13 @@ export interface paths {
2436
3053
  };
2437
3054
  };
2438
3055
  };
2439
- /** @description Access denied to this card */
3056
+ /** @description Access denied — also returned when the card does not exist or is not visible to the caller */
2440
3057
  403: {
2441
3058
  headers: {
2442
3059
  [name: string]: unknown;
2443
3060
  };
2444
3061
  content?: never;
2445
3062
  };
2446
- /** @description Card not found */
2447
- 404: {
2448
- headers: {
2449
- [name: string]: unknown;
2450
- };
2451
- content?: never;
2452
- };
2453
3063
  };
2454
3064
  };
2455
3065
  options?: never;
@@ -2460,7 +3070,7 @@ export interface paths {
2460
3070
  *
2461
3071
  * **Authentication**: Bearer token with x-tenant-id header required
2462
3072
  *
2463
- * **Access Control**: User must have access to the card
3073
+ * **Access Control**: Wallet owner or admin of the card's wallet
2464
3074
  *
2465
3075
  */
2466
3076
  patch: {
@@ -2482,7 +3092,7 @@ export interface paths {
2482
3092
  */
2483
3093
  card_name?: string;
2484
3094
  /**
2485
- * @description New title/display name
3095
+ * @description Alias of `card_name` (first non-empty of `card_name`, `nick_name`, `title` wins). The card name is the only editable field; an empty body returns the card unchanged
2486
3096
  * @example JOHN DOE
2487
3097
  */
2488
3098
  title?: string;
@@ -2490,7 +3100,7 @@ export interface paths {
2490
3100
  };
2491
3101
  };
2492
3102
  responses: {
2493
- /** @description Card updated successfully */
3103
+ /** @description Card updated — the response carries the bare vendor card wire, not the decorated list shape */
2494
3104
  200: {
2495
3105
  headers: {
2496
3106
  [name: string]: unknown;
@@ -2535,7 +3145,7 @@ export interface paths {
2535
3145
  *
2536
3146
  * **Authentication**: Bearer token with x-tenant-id header required
2537
3147
  *
2538
- * **Access Control**: User must have access to the card
3148
+ * **Access Control**: Wallet owner or admin of the card's wallet, or the scoped `user` role on its own card
2539
3149
  *
2540
3150
  * **Security Notice**: This endpoint returns sensitive card data. Ensure proper security measures are in place.
2541
3151
  *
@@ -2566,28 +3176,21 @@ export interface paths {
2566
3176
  card_number?: string;
2567
3177
  /** @description Card security code */
2568
3178
  cvv?: string;
2569
- /** @description Card expiration month (MM) */
2570
- expiry_month?: string;
2571
- /** @description Card expiration year (YYYY) */
2572
- expiry_year?: string;
3179
+ /** @description Card expiration date (MM/YY) */
3180
+ expiry_date?: string;
3181
+ /** @description Additional security code when the vendor provides one */
3182
+ security_code?: string | null;
2573
3183
  };
2574
3184
  };
2575
3185
  };
2576
3186
  };
2577
- /** @description Access denied to this card */
3187
+ /** @description Access denied — also returned when the card does not exist or is not visible to the caller */
2578
3188
  403: {
2579
3189
  headers: {
2580
3190
  [name: string]: unknown;
2581
3191
  };
2582
3192
  content?: never;
2583
3193
  };
2584
- /** @description Card not found */
2585
- 404: {
2586
- headers: {
2587
- [name: string]: unknown;
2588
- };
2589
- content?: never;
2590
- };
2591
3194
  };
2592
3195
  };
2593
3196
  put?: never;
@@ -2695,7 +3298,7 @@ export interface paths {
2695
3298
  *
2696
3299
  * **Authentication**: Bearer token with x-tenant-id header required
2697
3300
  *
2698
- * **Access Control**: User must have access to the card
3301
+ * **Access Control**: Wallet owner or admin of the card's wallet, or the scoped `user` role on its own card
2699
3302
  *
2700
3303
  */
2701
3304
  put: {
@@ -2724,20 +3327,13 @@ export interface paths {
2724
3327
  };
2725
3328
  };
2726
3329
  };
2727
- /** @description Access denied to this card */
3330
+ /** @description Access denied — also returned when the card does not exist or is not visible to the caller */
2728
3331
  403: {
2729
3332
  headers: {
2730
3333
  [name: string]: unknown;
2731
3334
  };
2732
3335
  content?: never;
2733
3336
  };
2734
- /** @description Card not found */
2735
- 404: {
2736
- headers: {
2737
- [name: string]: unknown;
2738
- };
2739
- content?: never;
2740
- };
2741
3337
  };
2742
3338
  };
2743
3339
  post?: never;
@@ -2761,7 +3357,7 @@ export interface paths {
2761
3357
  *
2762
3358
  * **Authentication**: Bearer token with x-tenant-id header required
2763
3359
  *
2764
- * **Access Control**: User must have access to the card
3360
+ * **Access Control**: Wallet owner or admin of the card's wallet, or the scoped `user` role on its own card
2765
3361
  *
2766
3362
  */
2767
3363
  put: {
@@ -2790,20 +3386,13 @@ export interface paths {
2790
3386
  };
2791
3387
  };
2792
3388
  };
2793
- /** @description Access denied to this card */
3389
+ /** @description Access denied — also returned when the card does not exist or is not visible to the caller */
2794
3390
  403: {
2795
3391
  headers: {
2796
3392
  [name: string]: unknown;
2797
3393
  };
2798
3394
  content?: never;
2799
3395
  };
2800
- /** @description Card not found */
2801
- 404: {
2802
- headers: {
2803
- [name: string]: unknown;
2804
- };
2805
- content?: never;
2806
- };
2807
3396
  };
2808
3397
  };
2809
3398
  post?: never;
@@ -2842,8 +3431,6 @@ export interface paths {
2842
3431
  from_date?: string;
2843
3432
  /** @description End date for filtering transactions */
2844
3433
  to_date?: string;
2845
- /** @description Include top-up transactions from card provider */
2846
- include_topups?: boolean;
2847
3434
  };
2848
3435
  header?: never;
2849
3436
  path: {
@@ -2903,7 +3490,7 @@ export interface paths {
2903
3490
  *
2904
3491
  * **Authentication**: Bearer token with x-tenant-id header required
2905
3492
  *
2906
- * **Access Control**: User must have access to the card
3493
+ * **Access Control**: Wallet owner or admin of the card's wallet
2907
3494
  *
2908
3495
  */
2909
3496
  put: {
@@ -3075,6 +3662,8 @@ export interface paths {
3075
3662
  /** @description Card provider refused the top-up during the pre-flight allowance check
3076
3663
  * (`TOPUP_NOT_ALLOWED` / `TOPUP_AMOUNT_EXCEEDS_VENDOR_LIMIT`). No order
3077
3664
  * was created and the wallet was not debited.
3665
+ * Also returned when the card, sub-account or program is not active
3666
+ * (`CARD_INACTIVE` / `SUB_ACCOUNT_INACTIVE` / `PROGRAM_INACTIVE`).
3078
3667
  * */
3079
3668
  409: {
3080
3669
  headers: {
@@ -3210,17 +3799,15 @@ export interface paths {
3210
3799
  */
3211
3800
  get: {
3212
3801
  parameters: {
3213
- query?: {
3214
- /** @description Filter sub-accounts by wallet ID */
3215
- wallet_id?: string;
3802
+ query: {
3803
+ /** @description Wallet ID (required) — sub-accounts are scoped to this wallet */
3804
+ wallet_id: string;
3216
3805
  /** @description Filter sub-accounts by program ID */
3217
3806
  program_id?: string;
3218
3807
  /** @description Comma-separated sub-account ids to fetch (targeted read through the list shape) */
3219
3808
  ids?: string;
3220
3809
  /** @description Filter sub-accounts by type */
3221
3810
  type?: "balance" | "prepaid";
3222
- /** @description Filter sub-accounts by status */
3223
- status?: "ACTIVE" | "INACTIVE" | "SUSPENDED";
3224
3811
  /** @description Number of items to skip */
3225
3812
  offset?: number;
3226
3813
  /** @description Number of items to return */
@@ -3442,20 +4029,13 @@ export interface paths {
3442
4029
  };
3443
4030
  };
3444
4031
  };
3445
- /** @description Access denied to this sub-account */
4032
+ /** @description Access denied — also returned when the sub-account does not exist or is not visible to the caller */
3446
4033
  403: {
3447
4034
  headers: {
3448
4035
  [name: string]: unknown;
3449
4036
  };
3450
4037
  content?: never;
3451
4038
  };
3452
- /** @description Sub-account not found */
3453
- 404: {
3454
- headers: {
3455
- [name: string]: unknown;
3456
- };
3457
- content?: never;
3458
- };
3459
4039
  };
3460
4040
  };
3461
4041
  put?: never;
@@ -3503,7 +4083,8 @@ export interface paths {
3503
4083
  "application/json": {
3504
4084
  /** @example true */
3505
4085
  success?: boolean;
3506
- data?: components["schemas"]["IssuingSubAccountResource"];
4086
+ /** @description Updated local sub-account row (id, wallet_id, program_id, account_currency, type, status, balance, nick_name, vendor_sub_account_id, vendor_id, created_at, updated_at) */
4087
+ data?: Record<string, never>;
3507
4088
  /** @example Sub-account updated successfully */
3508
4089
  message?: string;
3509
4090
  };
@@ -3516,20 +4097,13 @@ export interface paths {
3516
4097
  };
3517
4098
  content?: never;
3518
4099
  };
3519
- /** @description Access denied to this sub-account */
4100
+ /** @description Access denied — also returned when the sub-account does not exist or is not visible to the caller */
3520
4101
  403: {
3521
4102
  headers: {
3522
4103
  [name: string]: unknown;
3523
4104
  };
3524
4105
  content?: never;
3525
4106
  };
3526
- /** @description Sub-account not found */
3527
- 404: {
3528
- headers: {
3529
- [name: string]: unknown;
3530
- };
3531
- content?: never;
3532
- };
3533
4107
  };
3534
4108
  };
3535
4109
  trace?: never;
@@ -3557,8 +4131,8 @@ export interface paths {
3557
4131
  offset?: number;
3558
4132
  /** @description Number of items to return */
3559
4133
  limit?: number;
3560
- /** @description Filter by transaction type */
3561
- type?: "DEPOSIT" | "WITHDRAWAL" | "CARD_TRANSACTION" | "FEE";
4134
+ /** @description Exact (case-insensitive) match on the transaction status */
4135
+ status?: string;
3562
4136
  /** @description Start date for filtering transactions */
3563
4137
  from_date?: string;
3564
4138
  /** @description End date for filtering transactions */
@@ -3663,7 +4237,7 @@ export interface paths {
3663
4237
  note?: string;
3664
4238
  /**
3665
4239
  * Format: uuid
3666
- * @description Optional specific card ID. If not provided, will use the first card associated with the sub-account
4240
+ * @description Optional audit metadata stored in `meta.card_id` (defaults to the first card of the sub-account). Funds always move through the sub-account top-up — it never changes where the money goes
3667
4241
  * @example 123e4567-e89b-12d3-a456-426614174000
3668
4242
  */
3669
4243
  card_id?: string;
@@ -3708,6 +4282,7 @@ export interface paths {
3708
4282
  * - Missing required fields
3709
4283
  * - Invalid reference_id format
3710
4284
  * - Invalid amount (must be positive number)
4285
+ * - Insufficient wallet balance (`INSUFFICIENT_BALANCE`)
3711
4286
  * */
3712
4287
  400: {
3713
4288
  headers: {
@@ -3715,12 +4290,7 @@ export interface paths {
3715
4290
  };
3716
4291
  content?: never;
3717
4292
  };
3718
- /** @description Forbidden - One of the following:
3719
- * - Access denied to this sub-account
3720
- * - Insufficient wallet balance
3721
- * - Topup not allowed (limits exceeded)
3722
- * - Sub-account is not active
3723
- * */
4293
+ /** @description Access denied to this sub-account */
3724
4294
  403: {
3725
4295
  headers: {
3726
4296
  [name: string]: unknown;
@@ -3737,6 +4307,7 @@ export interface paths {
3737
4307
  /** @description Conflict - the card provider refused the top-up during the pre-flight
3738
4308
  * allowance check (no order was created, the wallet was not debited):
3739
4309
  * - `TOPUP_NOT_ALLOWED` — provider does not allow a top-up for this account
4310
+ * - `SUB_ACCOUNT_INACTIVE` / `PROGRAM_INACTIVE` — the sub-account or its program is not active
3740
4311
  * - `TOPUP_AMOUNT_EXCEEDS_VENDOR_LIMIT` — amount is above the provider's cap
3741
4312
  * */
3742
4313
  409: {
@@ -3858,8 +4429,9 @@ export interface paths {
3858
4429
  /** @description Bad Request - One of the following:
3859
4430
  * - Missing required fields
3860
4431
  * - Invalid amount (must be positive number)
3861
- * - Sub-account not found
3862
- * - Card service withdrawal failed
4432
+ * - Sub-account does not belong to the specified wallet
4433
+ * - Insufficient funds (`INSUFFICIENT_FUNDS`)
4434
+ * - Program has no withdrawal order type configured (`OPERATION_NOT_ALLOWED`)
3863
4435
  * */
3864
4436
  400: {
3865
4437
  headers: {
@@ -3867,11 +4439,7 @@ export interface paths {
3867
4439
  };
3868
4440
  content?: never;
3869
4441
  };
3870
- /** @description Forbidden - One of the following:
3871
- * - Access denied to this sub-account
3872
- * - Sub-account does not belong to the specified wallet
3873
- * - Wallet not found
3874
- * */
4442
+ /** @description Access denied to this sub-account */
3875
4443
  403: {
3876
4444
  headers: {
3877
4445
  [name: string]: unknown;
@@ -3885,10 +4453,17 @@ export interface paths {
3885
4453
  };
3886
4454
  content?: never;
3887
4455
  };
3888
- /** @description Internal Server Error or CRITICAL ERROR
4456
+ /** @description Another operation on this sub-account is in progress (`OPERATION_IN_PROGRESS`) */
4457
+ 409: {
4458
+ headers: {
4459
+ [name: string]: unknown;
4460
+ };
4461
+ content?: never;
4462
+ };
4463
+ /** @description Internal Server Error (including a vendor-side withdrawal failure) or CRITICAL ERROR
3889
4464
  *
3890
4465
  * **CRITICAL**: If the card service withdrawal succeeded but deposit to wallet failed,
3891
- * manual reconciliation is required. The error message will contain "CRITICAL" and the order_uuid.
4466
+ * manual reconciliation is required. The error message starts with "CRITICAL"; the order id is recorded on the order's `info`.
3892
4467
  * */
3893
4468
  500: {
3894
4469
  headers: {
@@ -4089,8 +4664,6 @@ export interface paths {
4089
4664
  * filter would hide it from the listing.
4090
4665
  * */
4091
4666
  wallet_id?: string;
4092
- /** @description Include extra UI fields (icon, card_design, consent_text, etc.) */
4093
- detailed?: boolean;
4094
4667
  };
4095
4668
  header?: never;
4096
4669
  path: {
@@ -4255,9 +4828,9 @@ export interface paths {
4255
4828
  */
4256
4829
  get: {
4257
4830
  parameters: {
4258
- query?: {
4259
- /** @description Filter cardholders by wallet ID */
4260
- wallet_id?: string;
4831
+ query: {
4832
+ /** @description Wallet ID (required) — cardholders are scoped to this wallet */
4833
+ wallet_id: string;
4261
4834
  /** @description Filter cardholders by issuing program ID */
4262
4835
  issuing_program_id?: string;
4263
4836
  /** @description Only cardholders LINKED to this CORE user (`user_data.uuid`, via the link
@@ -4335,7 +4908,7 @@ export interface paths {
4335
4908
  *
4336
4909
  * **Two modes**:
4337
4910
  * - `user_data_id` mode: personal data + KYC documents are seeded from an existing
4338
- * verified user (approved identity/face verification + Sumsub applicant required).
4911
+ * verified user. An approved identity/face verification plus a KYC applicant are required only when the program's KYC level needs document photos; otherwise any active member without a final rejection can be seeded (documents are then uploaded by hand).
4339
4912
  * Manual fields only fill gaps. The Sumsub files are attached to the draft
4340
4913
  * immediately, so step 2 is usually unnecessary in this mode.
4341
4914
  * - Manual mode: `first_name`, `last_name`, `email`, `phone` are required.
@@ -4484,7 +5057,8 @@ export interface paths {
4484
5057
  };
4485
5058
  };
4486
5059
  };
4487
- /** @description Bad Request - Missing required fields */
5060
+ /** @description Bad Request — missing/invalid fields, or a `user_data_id` precondition not met (user not verified, no KYC applicant, or the applicant is unknown to the KYC provider). Code `INVALID_REQUEST`; the message names the failed precondition.
5061
+ * */
4488
5062
  400: {
4489
5063
  headers: {
4490
5064
  [name: string]: unknown;
@@ -4498,7 +5072,7 @@ export interface paths {
4498
5072
  };
4499
5073
  content?: never;
4500
5074
  };
4501
- /** @description Vendor or sub-account not found */
5075
+ /** @description `user_data_id` does not resolve to a user */
4502
5076
  404: {
4503
5077
  headers: {
4504
5078
  [name: string]: unknown;
@@ -4538,6 +5112,14 @@ export interface paths {
4538
5112
  };
4539
5113
  content?: never;
4540
5114
  };
5115
+ /** @description The KYC provider failed while the dossier was being pulled for `user_data_id` (code `EXTERNAL_SERVICE_ERROR`). Retry later; the draft was not created.
5116
+ * */
5117
+ 502: {
5118
+ headers: {
5119
+ [name: string]: unknown;
5120
+ };
5121
+ content?: never;
5122
+ };
4541
5123
  };
4542
5124
  };
4543
5125
  delete?: never;
@@ -4564,9 +5146,9 @@ export interface paths {
4564
5146
  */
4565
5147
  get: {
4566
5148
  parameters: {
4567
- query?: {
4568
- /** @description Wallet ID for access validation */
4569
- wallet_id?: string;
5149
+ query: {
5150
+ /** @description Wallet ID for access validation (required) */
5151
+ wallet_id: string;
4570
5152
  };
4571
5153
  header?: never;
4572
5154
  path: {
@@ -4614,14 +5196,14 @@ export interface paths {
4614
5196
  *
4615
5197
  * **Authentication**: Bearer token with x-tenant-id header required
4616
5198
  *
4617
- * **Access Control**: Cardholder must belong to the user's wallet
5199
+ * **Access Control**: Cardholder must belong to the user's wallet; caller must be owner or admin of that wallet
4618
5200
  *
4619
5201
  */
4620
5202
  delete: {
4621
5203
  parameters: {
4622
- query?: {
4623
- /** @description Wallet ID for access validation */
4624
- wallet_id?: string;
5204
+ query: {
5205
+ /** @description Wallet ID for access validation (required) */
5206
+ wallet_id: string;
4625
5207
  };
4626
5208
  header?: never;
4627
5209
  path: {
@@ -4677,14 +5259,14 @@ export interface paths {
4677
5259
  *
4678
5260
  * **Authentication**: Bearer token with x-tenant-id header required
4679
5261
  *
4680
- * **Access Control**: Cardholder must belong to the user's wallet
5262
+ * **Access Control**: Cardholder must belong to the user's wallet; caller must be owner or admin of that wallet
4681
5263
  *
4682
5264
  */
4683
5265
  patch: {
4684
5266
  parameters: {
4685
- query?: {
4686
- /** @description Wallet ID for access validation */
4687
- wallet_id?: string;
5267
+ query: {
5268
+ /** @description Wallet ID for access validation (required) */
5269
+ wallet_id: string;
4688
5270
  };
4689
5271
  header?: never;
4690
5272
  path: {
@@ -4800,7 +5382,7 @@ export interface paths {
4800
5382
  * - `READY` — an ACTIVE cardholder is linked (`cardholder_id`); create the card directly.
4801
5383
  * - `DRAFT` — a draft is linked (`cardholder_id`); complete `will_require` and submit it.
4802
5384
  * - `CAN_CREATE` — no cardholder yet, but the member clears the `user_data_id`-mode
4803
- * creation gates (approved identity/face verification + KYC applicant).
5385
+ * creation gates (approved identity/face verification + KYC applicant), or the program's KYC level needs no document dossier and the member has no final rejection.
4804
5386
  * - `PENDING` — a verification review is in flight; wait.
4805
5387
  * - `NEEDS_VERIFICATION` — no approved verification or no KYC applicant; the member has
4806
5388
  * to (re)run identity verification.
@@ -4813,13 +5395,17 @@ export interface paths {
4813
5395
  * `PATCH` the field, or re-upload and re-attach the document — then call
4814
5396
  * `POST /cardholders/{cardholder_id}/submit` again. The review restarts on the vendor
4815
5397
  * account the person already has; a fresh cardholder is NOT the way to retry.
5398
+ * - `ISSUER_REVIEW_PENDING` — the cardholder is submitted (`cardholder_id` is set) and the
5399
+ * ISSUER is still reviewing the person. Nothing is wrong and nothing can be done but
5400
+ * wait: re-submitting would only spend another review (the submit endpoint refuses it
5401
+ * with `409 CARDHOLDER_NOT_DRAFT`), and creating a card now is refused with
5402
+ * `400 INVALID_REQUEST` — `KYC review status is "PENDING"`. Show the member as pending
5403
+ * and poll. Only programs whose vendor reviews the person before issuance ever return
5404
+ * this; vendors that issue inline go straight to `READY`.
4816
5405
  * - `REJECTED` — a verification came back with a FINAL rejection; re-running it from the
4817
5406
  * app is not possible (support resets it), so never render a "verify now" action.
4818
5407
  * - `NOT_MEMBER` — the uuid is not an active member of this wallet.
4819
5408
  *
4820
- * A cardholder whose review is still running stays `READY`: re-submitting would only spend
4821
- * another review, and the submit endpoint refuses it with `409 CARDHOLDER_NOT_DRAFT`.
4822
- *
4823
5409
  * **`will_require`**: fields the client should expect to collect BY HAND (same vocabulary
4824
5410
  * as the submit 400 `missing` list, e.g. `address.line1`, `tax_identification_number`,
4825
5411
  * `email or phone`). For `DRAFT` it is the draft's actual leftovers; for `CAN_CREATE` it
@@ -4868,10 +5454,11 @@ export interface paths {
4868
5454
  /** Format: uuid */
4869
5455
  user_data_id: string;
4870
5456
  /** @enum {string} */
4871
- verdict: "READY" | "DRAFT" | "CAN_CREATE" | "PENDING" | "NEEDS_VERIFICATION" | "NEEDS_VERIFICATION_UPGRADE" | "NEEDS_RESUBMIT" | "REJECTED" | "NOT_MEMBER";
5457
+ verdict: "READY" | "DRAFT" | "CAN_CREATE" | "PENDING" | "NEEDS_VERIFICATION" | "NEEDS_VERIFICATION_UPGRADE" | "NEEDS_RESUBMIT" | "ISSUER_REVIEW_PENDING" | "REJECTED" | "NOT_MEMBER";
4872
5458
  /**
4873
5459
  * Format: uuid
4874
- * @description The linked cardholder for READY / DRAFT / NEEDS_RESUBMIT verdicts
5460
+ * @description The linked cardholder for READY / DRAFT / NEEDS_RESUBMIT / ISSUER_REVIEW_PENDING verdicts
5461
+ *
4875
5462
  */
4876
5463
  cardholder_id: string | null;
4877
5464
  /** @description Fields to collect by hand (submit `missing` vocabulary) */
@@ -5337,6 +5924,7 @@ export interface paths {
5337
5924
  };
5338
5925
  /**
5339
5926
  * Initialize Persona KYC session for a wallet
5927
+ * @deprecated
5340
5928
  * @description Creates a Persona inquiry via the Auth API for the specified wallet and
5341
5929
  * returns the hosted Persona URL. The caller's Bearer token is forwarded to
5342
5930
  * the Auth API; access requires the caller to be a member of the wallet
@@ -5463,6 +6051,7 @@ export interface paths {
5463
6051
  };
5464
6052
  /**
5465
6053
  * Resume Persona KYC session for a wallet
6054
+ * @deprecated
5466
6055
  * @description Resumes an existing Persona inquiry via the Auth API for the specified
5467
6056
  * wallet and returns the hosted Persona URL. The caller's Bearer token is
5468
6057
  * forwarded to the Auth API; access requires the caller to be a member of
@@ -5790,8 +6379,200 @@ export interface paths {
5790
6379
  };
5791
6380
  };
5792
6381
  };
5793
- /** @description Validation error (`verification_ref` missing or empty) */
5794
- 400: {
6382
+ /** @description Validation error (`verification_ref` missing or empty) */
6383
+ 400: {
6384
+ headers: {
6385
+ [name: string]: unknown;
6386
+ };
6387
+ content: {
6388
+ "application/json": components["schemas"]["ErrorResponse"];
6389
+ };
6390
+ };
6391
+ /** @description Missing or invalid Bearer token */
6392
+ 401: {
6393
+ headers: {
6394
+ [name: string]: unknown;
6395
+ };
6396
+ content: {
6397
+ "application/json": components["schemas"]["ErrorResponse"];
6398
+ };
6399
+ };
6400
+ /** @description Caller has no access to this wallet */
6401
+ 403: {
6402
+ headers: {
6403
+ [name: string]: unknown;
6404
+ };
6405
+ content: {
6406
+ "application/json": components["schemas"]["ErrorResponse"];
6407
+ };
6408
+ };
6409
+ /** @description No such verification to resume upstream */
6410
+ 404: {
6411
+ headers: {
6412
+ [name: string]: unknown;
6413
+ };
6414
+ content: {
6415
+ "application/json": components["schemas"]["ErrorResponse"];
6416
+ };
6417
+ };
6418
+ /** @description Auth API unavailable, timed out, or returned a malformed payload */
6419
+ 502: {
6420
+ headers: {
6421
+ [name: string]: unknown;
6422
+ };
6423
+ content: {
6424
+ "application/json": components["schemas"]["ErrorResponse"];
6425
+ };
6426
+ };
6427
+ };
6428
+ };
6429
+ delete?: never;
6430
+ options?: never;
6431
+ head?: never;
6432
+ patch?: never;
6433
+ trace?: never;
6434
+ };
6435
+ "/frontend/mass-payouts/{wallet_id}/templates": {
6436
+ parameters: {
6437
+ query?: never;
6438
+ header?: never;
6439
+ path?: never;
6440
+ cookie?: never;
6441
+ };
6442
+ /** List mass payout templates of a wallet */
6443
+ get: {
6444
+ parameters: {
6445
+ query?: {
6446
+ limit?: number;
6447
+ offset?: number;
6448
+ };
6449
+ header?: never;
6450
+ path: {
6451
+ /** @description Source wallet the batches belong to */
6452
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
6453
+ };
6454
+ cookie?: never;
6455
+ };
6456
+ requestBody?: never;
6457
+ responses: {
6458
+ /** @description Page of templates, newest first */
6459
+ 200: {
6460
+ headers: {
6461
+ [name: string]: unknown;
6462
+ };
6463
+ content: {
6464
+ "application/json": {
6465
+ /** @example true */
6466
+ success?: boolean;
6467
+ data?: {
6468
+ items?: components["schemas"]["MassPayoutTemplate"][];
6469
+ total?: number;
6470
+ limit?: number;
6471
+ offset?: number;
6472
+ };
6473
+ };
6474
+ };
6475
+ };
6476
+ };
6477
+ };
6478
+ put?: never;
6479
+ /**
6480
+ * Create a mass payout template
6481
+ * @description Saves a reusable recipient list (name, source currency/virtual account
6482
+ * and rows with amounts, payout currencies and references). Supporting
6483
+ * documents are per-payment and are not part of a template. To start a
6484
+ * batch from a template, read it and create a draft from its rows.
6485
+ *
6486
+ */
6487
+ post: {
6488
+ parameters: {
6489
+ query?: never;
6490
+ header?: never;
6491
+ path: {
6492
+ /** @description Source wallet the batches belong to */
6493
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
6494
+ };
6495
+ cookie?: never;
6496
+ };
6497
+ requestBody: {
6498
+ content: {
6499
+ "application/json": {
6500
+ name: string;
6501
+ /** Format: uuid */
6502
+ currency_id: string;
6503
+ /** Format: uuid */
6504
+ virtual_account_id?: string;
6505
+ items: components["schemas"]["MassPayoutTemplateItemInput"][];
6506
+ };
6507
+ };
6508
+ };
6509
+ responses: {
6510
+ /** @description Template created */
6511
+ 200: {
6512
+ headers: {
6513
+ [name: string]: unknown;
6514
+ };
6515
+ content: {
6516
+ "application/json": {
6517
+ /** @example true */
6518
+ success?: boolean;
6519
+ data?: components["schemas"]["MassPayoutTemplateWithItems"];
6520
+ };
6521
+ };
6522
+ };
6523
+ /** @description Validation error (including the item and template caps) */
6524
+ 400: {
6525
+ headers: {
6526
+ [name: string]: unknown;
6527
+ };
6528
+ content: {
6529
+ "application/json": components["schemas"]["ErrorResponse"];
6530
+ };
6531
+ };
6532
+ };
6533
+ };
6534
+ delete?: never;
6535
+ options?: never;
6536
+ head?: never;
6537
+ patch?: never;
6538
+ trace?: never;
6539
+ };
6540
+ "/frontend/mass-payouts/{wallet_id}/templates/{template_id}": {
6541
+ parameters: {
6542
+ query?: never;
6543
+ header?: never;
6544
+ path?: never;
6545
+ cookie?: never;
6546
+ };
6547
+ /** Get a mass payout template with its rows */
6548
+ get: {
6549
+ parameters: {
6550
+ query?: never;
6551
+ header?: never;
6552
+ path: {
6553
+ /** @description Source wallet the batches belong to */
6554
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
6555
+ template_id: components["parameters"]["MassPayoutTemplateId"];
6556
+ };
6557
+ cookie?: never;
6558
+ };
6559
+ requestBody?: never;
6560
+ responses: {
6561
+ /** @description Template with its recipient rows */
6562
+ 200: {
6563
+ headers: {
6564
+ [name: string]: unknown;
6565
+ };
6566
+ content: {
6567
+ "application/json": {
6568
+ /** @example true */
6569
+ success?: boolean;
6570
+ data?: components["schemas"]["MassPayoutTemplateWithItems"];
6571
+ };
6572
+ };
6573
+ };
6574
+ /** @description Template not found */
6575
+ 404: {
5795
6576
  headers: {
5796
6577
  [name: string]: unknown;
5797
6578
  };
@@ -5799,17 +6580,51 @@ export interface paths {
5799
6580
  "application/json": components["schemas"]["ErrorResponse"];
5800
6581
  };
5801
6582
  };
5802
- /** @description Missing or invalid Bearer token */
5803
- 401: {
6583
+ };
6584
+ };
6585
+ /**
6586
+ * Edit a mass payout template
6587
+ * @description `items` fully replaces the row list; `virtual_account_id: null` clears the template's source account.
6588
+ */
6589
+ put: {
6590
+ parameters: {
6591
+ query?: never;
6592
+ header?: never;
6593
+ path: {
6594
+ /** @description Source wallet the batches belong to */
6595
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
6596
+ template_id: components["parameters"]["MassPayoutTemplateId"];
6597
+ };
6598
+ cookie?: never;
6599
+ };
6600
+ requestBody: {
6601
+ content: {
6602
+ "application/json": {
6603
+ name?: string;
6604
+ /** Format: uuid */
6605
+ currency_id?: string;
6606
+ /** Format: uuid */
6607
+ virtual_account_id?: string | null;
6608
+ items?: components["schemas"]["MassPayoutTemplateItemInput"][];
6609
+ };
6610
+ };
6611
+ };
6612
+ responses: {
6613
+ /** @description Updated template with its rows */
6614
+ 200: {
5804
6615
  headers: {
5805
6616
  [name: string]: unknown;
5806
6617
  };
5807
6618
  content: {
5808
- "application/json": components["schemas"]["ErrorResponse"];
6619
+ "application/json": {
6620
+ /** @example true */
6621
+ success?: boolean;
6622
+ data?: components["schemas"]["MassPayoutTemplateWithItems"];
6623
+ };
5809
6624
  };
5810
6625
  };
5811
- /** @description Caller has no access to this wallet */
5812
- 403: {
6626
+ /** @description Template not found */
6627
+ 404: {
5813
6628
  headers: {
5814
6629
  [name: string]: unknown;
5815
6630
  };
@@ -5817,17 +6632,41 @@ export interface paths {
5817
6632
  "application/json": components["schemas"]["ErrorResponse"];
5818
6633
  };
5819
6634
  };
5820
- /** @description No such verification to resume upstream */
5821
- 404: {
6635
+ };
6636
+ };
6637
+ post?: never;
6638
+ /** Delete a mass payout template */
6639
+ delete: {
6640
+ parameters: {
6641
+ query?: never;
6642
+ header?: never;
6643
+ path: {
6644
+ /** @description Source wallet the batches belong to */
6645
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
6646
+ template_id: components["parameters"]["MassPayoutTemplateId"];
6647
+ };
6648
+ cookie?: never;
6649
+ };
6650
+ requestBody?: never;
6651
+ responses: {
6652
+ /** @description Template deleted */
6653
+ 200: {
5822
6654
  headers: {
5823
6655
  [name: string]: unknown;
5824
6656
  };
5825
6657
  content: {
5826
- "application/json": components["schemas"]["ErrorResponse"];
6658
+ "application/json": {
6659
+ /** @example true */
6660
+ success?: boolean;
6661
+ data?: {
6662
+ /** @example true */
6663
+ deleted?: boolean;
6664
+ };
6665
+ };
5827
6666
  };
5828
6667
  };
5829
- /** @description Auth API unavailable, timed out, or returned a malformed payload */
5830
- 502: {
6668
+ /** @description Template not found */
6669
+ 404: {
5831
6670
  headers: {
5832
6671
  [name: string]: unknown;
5833
6672
  };
@@ -5837,7 +6676,6 @@ export interface paths {
5837
6676
  };
5838
6677
  };
5839
6678
  };
5840
- delete?: never;
5841
6679
  options?: never;
5842
6680
  head?: never;
5843
6681
  patch?: never;
@@ -5854,7 +6692,13 @@ export interface paths {
5854
6692
  get: {
5855
6693
  parameters: {
5856
6694
  query?: {
5857
- status?: "DRAFT" | "PENDING_APPROVAL" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
6695
+ status?: "DRAFT" | "PENDING_APPROVAL" | "SCHEDULED" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
6696
+ /** @description Case-insensitive substring match against the batch name */
6697
+ name?: string;
6698
+ /** @description Only batches created at or after this moment */
6699
+ date_from?: string;
6700
+ /** @description Only batches created at or before this moment */
6701
+ date_to?: string;
5858
6702
  limit?: number;
5859
6703
  offset?: number;
5860
6704
  };
@@ -5891,11 +6735,16 @@ export interface paths {
5891
6735
  /**
5892
6736
  * Create a mass payout draft
5893
6737
  * @description Creates a batch of payouts to existing counterparty destinations: one
5894
- * source wallet, one currency, up to the tenant's batch-size limit of
5895
- * recipients (default 100). The draft can be freely edited and
5896
- * previewed; nothing moves until it is submitted and approved.
5897
- * `virtual_account_id` is required only when the list contains banking
5898
- * recipients. Requires an administrative role on the source wallet.
6738
+ * source wallet and funding currency, up to the tenant's batch-size limit
6739
+ * of recipients (default 100). Every row states the amount the recipient
6740
+ * receives; a row with a different `to_currency_id` is paid as a
6741
+ * cross-currency transfer converted at execution time. An optional
6742
+ * `scheduled_at` (at least 1 hour and at most 90 days ahead) makes the
6743
+ * batch execute at that moment once approved. The draft can be freely
6744
+ * edited and previewed; nothing moves until it is submitted and
6745
+ * approved. `virtual_account_id` is required only when the list contains
6746
+ * banking recipients. Requires an administrative role on the source
6747
+ * wallet.
5899
6748
  *
5900
6749
  */
5901
6750
  post: {
@@ -5916,6 +6765,11 @@ export interface paths {
5916
6765
  /** Format: uuid */
5917
6766
  virtual_account_id?: string;
5918
6767
  name: string;
6768
+ /**
6769
+ * Format: date-time
6770
+ * @description Requested execution time; omit to execute right after approval
6771
+ */
6772
+ scheduled_at?: string;
5919
6773
  items: components["schemas"]["MassPayoutItemInput"][];
5920
6774
  };
5921
6775
  };
@@ -5934,7 +6788,7 @@ export interface paths {
5934
6788
  };
5935
6789
  };
5936
6790
  };
5937
- /** @description Validation error (including the batch-size limit) */
6791
+ /** @description Validation error (including the batch-size limit and the scheduling horizon) */
5938
6792
  400: {
5939
6793
  headers: {
5940
6794
  [name: string]: unknown;
@@ -5990,7 +6844,7 @@ export interface paths {
5990
6844
  };
5991
6845
  requestBody?: never;
5992
6846
  responses: {
5993
- /** @description Batch details with progress counters and total amount */
6847
+ /** @description Batch details with progress counters and totals */
5994
6848
  200: {
5995
6849
  headers: {
5996
6850
  [name: string]: unknown;
@@ -6016,7 +6870,7 @@ export interface paths {
6016
6870
  };
6017
6871
  /**
6018
6872
  * Edit a mass payout draft
6019
- * @description Draft-only. `items` fully replaces the recipient list; `virtual_account_id: null` clears the source VA.
6873
+ * @description Draft-only. `items` fully replaces the recipient list; `virtual_account_id: null` clears the source VA; `scheduled_at: null` makes the batch execute right after approval.
6020
6874
  */
6021
6875
  put: {
6022
6876
  parameters: {
@@ -6035,6 +6889,8 @@ export interface paths {
6035
6889
  name?: string;
6036
6890
  /** Format: uuid */
6037
6891
  virtual_account_id?: string | null;
6892
+ /** Format: date-time */
6893
+ scheduled_at?: string | null;
6038
6894
  items?: components["schemas"]["MassPayoutItemInput"][];
6039
6895
  };
6040
6896
  };
@@ -6080,11 +6936,12 @@ export interface paths {
6080
6936
  };
6081
6937
  /**
6082
6938
  * List items of a mass payout
6083
- * @description Items in upload order, paginated with limit/offset like the batch list.
6939
+ * @description Items in upload order, paginated with limit/offset like the batch list. The optional status filter narrows the tracker view (e.g. failed rows only).
6084
6940
  */
6085
6941
  get: {
6086
6942
  parameters: {
6087
6943
  query?: {
6944
+ status?: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
6088
6945
  limit?: number;
6089
6946
  offset?: number;
6090
6947
  };
@@ -6135,10 +6992,14 @@ export interface paths {
6135
6992
  };
6136
6993
  /**
6137
6994
  * Preview a mass payout
6138
- * @description Dry-run before submitting: validates every recipient, estimates the fee
6139
- * per item through the tenant's pricing, sums the total debit and checks
6140
- * it against the wallet balance. Crypto payouts to on-platform addresses
6141
- * may execute cheaper than estimated (they settle internally).
6995
+ * @description Dry-run before submitting: validates every recipient (the invoice rule
6996
+ * included), estimates the fee per item through the tenant's pricing —
6997
+ * cross-currency rows are quoted at the current rate — and sums the
6998
+ * total debit in the batch source currency against the wallet balance.
6999
+ * Estimates are indicative: execution prices each payout at its own
7000
+ * moment. Crypto payouts always settle on-chain at the estimated fee; to
7001
+ * pay an on-platform wallet without a network fee use an INTERNAL
7002
+ * destination.
6142
7003
  *
6143
7004
  */
6144
7005
  get: {
@@ -6170,12 +7031,15 @@ export interface paths {
6170
7031
  currency_id?: string;
6171
7032
  total_items?: number;
6172
7033
  total_amount?: number;
7034
+ totals_by_currency?: components["schemas"]["MassPayoutCurrencyTotal"][];
6173
7035
  total_fees?: number;
6174
7036
  total_debit?: number;
6175
7037
  balance?: {
6176
7038
  available?: number;
6177
7039
  sufficient?: boolean;
6178
7040
  };
7041
+ /** @description Rows at or above this amount must carry an INVOICE attachment */
7042
+ invoice_threshold?: number;
6179
7043
  valid_count?: number;
6180
7044
  invalid_count?: number;
6181
7045
  items?: {
@@ -6185,7 +7049,14 @@ export interface paths {
6185
7049
  /** Format: uuid */
6186
7050
  destination_id?: string;
6187
7051
  amount?: number;
7052
+ /** Format: uuid */
7053
+ to_currency_id?: string | null;
6188
7054
  fee?: number;
7055
+ /**
7056
+ * Format: uuid
7057
+ * @description Currency the fee is denominated in (cross-currency payouts may be charged in either leg, per the tenant pricing)
7058
+ */
7059
+ fee_currency_id?: string;
6189
7060
  debit_amount?: number;
6190
7061
  result_amount?: number;
6191
7062
  }[];
@@ -6222,8 +7093,12 @@ export interface paths {
6222
7093
  put?: never;
6223
7094
  /**
6224
7095
  * Submit a mass payout for approval
6225
- * @description DRAFT → PENDING_APPROVAL. Refused while any recipient is invalid — the
6226
- * problems are returned in the error details so the rows can be fixed.
7096
+ * @description DRAFT → PENDING_APPROVAL. Refused while any recipient is invalid — a
7097
+ * missing/deleted destination, an unsupported type, a banking row
7098
+ * without a source account, or a row at/above the invoice threshold
7099
+ * without an INVOICE attachment. The problems are returned in the error
7100
+ * details so the rows can be fixed. Wallet members are notified that the
7101
+ * batch awaits approval.
6227
7102
  *
6228
7103
  */
6229
7104
  post: {
@@ -6289,12 +7164,18 @@ export interface paths {
6289
7164
  put?: never;
6290
7165
  /**
6291
7166
  * Approve a mass payout
6292
- * @description PENDING_APPROVAL → PROCESSING and starts the asynchronous execution:
6293
- * every item becomes a regular order (created and approved through the
6294
- * standard order flow, funds are debited per order). Requires an
6295
- * administrative wallet role and a recent second-factor verification — a stale one is rejected
6296
- * with `TWO_FACTOR_REVERIFICATION_REQUIRED`. Execution continues past
6297
- * failed items; progress is visible through the batch counters.
7167
+ * @description PENDING_APPROVAL → PROCESSING (or SCHEDULED for a batch with a future
7168
+ * send date — execution then starts automatically at that moment).
7169
+ * Every item becomes a regular order (created and approved through the
7170
+ * standard order flow, funds are debited per order). The estimated total
7171
+ * debit is checked against the wallet balance first — a batch that
7172
+ * cannot cover all payouts is refused instead of paying only part of the
7173
+ * list. Requires an administrative wallet role. On Clerk-authenticated
7174
+ * tenants a second factor verified within the last 10 minutes is also
7175
+ * required — a stale one is rejected with
7176
+ * `TWO_FACTOR_REVERIFICATION_REQUIRED` (Supabase-authenticated tenants
7177
+ * have no step-up check). Execution continues past failed items;
7178
+ * progress is visible through the batch counters.
6298
7179
  *
6299
7180
  */
6300
7181
  post: {
@@ -6310,7 +7191,7 @@ export interface paths {
6310
7191
  };
6311
7192
  requestBody?: never;
6312
7193
  responses: {
6313
- /** @description Execution started */
7194
+ /** @description Execution started (or scheduled) */
6314
7195
  200: {
6315
7196
  headers: {
6316
7197
  [name: string]: unknown;
@@ -6323,7 +7204,16 @@ export interface paths {
6323
7204
  };
6324
7205
  };
6325
7206
  };
6326
- /** @description Second-factor verification is stale or the caller lacks permission */
7207
+ /** @description Insufficient funds for the estimated total debit, or invalid items */
7208
+ 400: {
7209
+ headers: {
7210
+ [name: string]: unknown;
7211
+ };
7212
+ content: {
7213
+ "application/json": components["schemas"]["ErrorResponse"];
7214
+ };
7215
+ };
7216
+ /** @description Caller lacks an administrative wallet role, or (Clerk tenants) the second-factor verification is stale */
6327
7217
  403: {
6328
7218
  headers: {
6329
7219
  [name: string]: unknown;
@@ -6359,8 +7249,13 @@ export interface paths {
6359
7249
  get?: never;
6360
7250
  put?: never;
6361
7251
  /**
6362
- * Cancel a mass payout
6363
- * @description Allowed from DRAFT and PENDING_APPROVAL. A PROCESSING batch cannot be canceled — payouts are already executing.
7252
+ * Cancel or stop a mass payout
7253
+ * @description Before execution starts (DRAFT, PENDING_APPROVAL, SCHEDULED) the batch
7254
+ * cancels whole — every payment ends CANCELED and nothing moves. A
7255
+ * PROCESSING batch takes a stop request instead: payments already handed
7256
+ * to the payment flow finish, the untouched ones are cancelled, and the
7257
+ * batch finalizes as CANCELED with the paid/failed counters preserved.
7258
+ *
6364
7259
  */
6365
7260
  post: {
6366
7261
  parameters: {
@@ -6375,7 +7270,7 @@ export interface paths {
6375
7270
  };
6376
7271
  requestBody?: never;
6377
7272
  responses: {
6378
- /** @description Batch canceled */
7273
+ /** @description Batch canceled (or the stop was requested) */
6379
7274
  200: {
6380
7275
  headers: {
6381
7276
  [name: string]: unknown;
@@ -6414,8 +7309,9 @@ export interface paths {
6414
7309
  };
6415
7310
  /**
6416
7311
  * Download the mass payout report (CSV)
6417
- * @description Streaming CSV: recipient, amount, item status, the linked order and its
6418
- * current status, and the failure reason for every unsuccessful payout.
7312
+ * @description Streaming CSV: recipient, amount, payout currency, reference, item
7313
+ * status, the linked order and its current status, and the failure
7314
+ * reason for every unsuccessful payout.
6419
7315
  *
6420
7316
  */
6421
7317
  get: {
@@ -6468,7 +7364,7 @@ export interface paths {
6468
7364
  };
6469
7365
  /**
6470
7366
  * Effective notification preferences
6471
- * @description Both dimensions in full with defaults applied — delivery channels (`IN_APP` is always enabled) and notification categories (every category is user-configurable).
7367
+ * @description Both dimensions in full with defaults applied — delivery channels (`IN_APP` is always enabled) and notification categories (every category is user-configurable). The channel list is what exists for the tenant — `TELEGRAM` appears only when the tenant has a Telegram bot configured.
6472
7368
  */
6473
7369
  get: {
6474
7370
  parameters: {
@@ -6500,7 +7396,7 @@ export interface paths {
6500
7396
  };
6501
7397
  /**
6502
7398
  * Update notification preferences
6503
- * @description Bulk upsert of either or both dimensions. Disabling the `IN_APP` channel is rejected with 400 (`INBOX_CHANNEL_LOCKED`). A disabled category mutes push and email for its notifications; the inbox always receives them. Changes apply from the next delivery.
7399
+ * @description Bulk upsert of either or both dimensions. Disabling the `IN_APP` channel is rejected with 400 (`INBOX_CHANNEL_LOCKED`). A disabled category mutes push, email and Telegram for its notifications; the inbox always receives them. Changes apply from the next delivery.
6504
7400
  */
6505
7401
  put: {
6506
7402
  parameters: {
@@ -7019,7 +7915,7 @@ export interface paths {
7019
7915
  };
7020
7916
  };
7021
7917
  };
7022
- /** @description Validation error (insufficient balance, virtual account missing, etc.) */
7918
+ /** @description Validation error — invalid body, pair disabled by the exchange config, or calculated amount too small. Balance is checked only at approve. */
7023
7919
  400: {
7024
7920
  headers: {
7025
7921
  [name: string]: unknown;
@@ -7293,7 +8189,7 @@ export interface paths {
7293
8189
  };
7294
8190
  requestBody: {
7295
8191
  content: {
7296
- "application/json": components["schemas"]["FrontendL2FOrderRequest"];
8192
+ "application/json": components["schemas"]["FrontendFiatWithdrawalRequest"];
7297
8193
  };
7298
8194
  };
7299
8195
  responses: {
@@ -7373,7 +8269,7 @@ export interface paths {
7373
8269
  };
7374
8270
  requestBody: {
7375
8271
  content: {
7376
- "application/json": components["schemas"]["FrontendL2FOrderRequest"];
8272
+ "application/json": components["schemas"]["FrontendFiatWithdrawalRequest"];
7377
8273
  };
7378
8274
  };
7379
8275
  responses: {
@@ -7453,7 +8349,7 @@ export interface paths {
7453
8349
  };
7454
8350
  requestBody: {
7455
8351
  content: {
7456
- "application/json": components["schemas"]["FrontendL2FOrderRequest"];
8352
+ "application/json": components["schemas"]["FrontendFiatWithdrawalRequest"];
7457
8353
  };
7458
8354
  };
7459
8355
  responses: {
@@ -7533,7 +8429,7 @@ export interface paths {
7533
8429
  };
7534
8430
  requestBody: {
7535
8431
  content: {
7536
- "application/json": components["schemas"]["FrontendL2FOrderRequest"];
8432
+ "application/json": components["schemas"]["FrontendFiatWithdrawalRequest"];
7537
8433
  };
7538
8434
  };
7539
8435
  responses: {
@@ -7613,7 +8509,7 @@ export interface paths {
7613
8509
  };
7614
8510
  requestBody: {
7615
8511
  content: {
7616
- "application/json": components["schemas"]["FrontendL2FOrderRequest"];
8512
+ "application/json": components["schemas"]["FrontendFiatWithdrawalRequest"];
7617
8513
  };
7618
8514
  };
7619
8515
  responses: {
@@ -7693,7 +8589,7 @@ export interface paths {
7693
8589
  };
7694
8590
  requestBody: {
7695
8591
  content: {
7696
- "application/json": components["schemas"]["FrontendL2FOrderRequest"];
8592
+ "application/json": components["schemas"]["FrontendFiatWithdrawalRequest"];
7697
8593
  };
7698
8594
  };
7699
8595
  responses: {
@@ -7769,8 +8665,10 @@ export interface paths {
7769
8665
  * (transaction written as `complete`) and triggers its workflow.
7770
8666
  * Exchange orders (EXCHANGE_OMNI) and internal transfers
7771
8667
  * (TRANSFER_INTERNAL / OMNIBUS_INTERNAL_TRANSFER) settle synchronously
7772
- * and land in COMPLETE. An insufficient balance fails the order
7773
- * (FAILED). OTP verification is mandatory and keyed on the order id
8668
+ * and land in COMPLETE. An insufficient balance answers 400
8669
+ * `INSUFFICIENT_FUNDS` and releases the order back to NEW (approve again
8670
+ * after a top-up); FAILED is reached only when a step after the debit
8671
+ * fails. OTP verification is mandatory and keyed on the order id
7774
8672
  * (request the OTP for the order being approved). Orders created with
7775
8673
  * `scheduled_at` move to EXPECTED instead — no funds are debited until
7776
8674
  * execution at the requested time.
@@ -7794,7 +8692,7 @@ export interface paths {
7794
8692
  };
7795
8693
  };
7796
8694
  responses: {
7797
- /** @description Order moved to PROCESSING */
8695
+ /** @description Order approved — PROCESSING for workflow rails, COMPLETE for exchange / internal transfers, EXPECTED for scheduled orders */
7798
8696
  200: {
7799
8697
  headers: {
7800
8698
  [name: string]: unknown;
@@ -7807,7 +8705,34 @@ export interface paths {
7807
8705
  };
7808
8706
  };
7809
8707
  };
7810
- /** @description Order is not in an approvable state */
8708
+ /** @description Insufficient funds (`INSUFFICIENT_FUNDS` — the order is released back to NEW) or validation error */
8709
+ 400: {
8710
+ headers: {
8711
+ [name: string]: unknown;
8712
+ };
8713
+ content: {
8714
+ "application/json": components["schemas"]["ErrorResponse"];
8715
+ };
8716
+ };
8717
+ /** @description Order does not belong to the caller's wallet */
8718
+ 403: {
8719
+ headers: {
8720
+ [name: string]: unknown;
8721
+ };
8722
+ content: {
8723
+ "application/json": components["schemas"]["ErrorResponse"];
8724
+ };
8725
+ };
8726
+ /** @description Order not found */
8727
+ 404: {
8728
+ headers: {
8729
+ [name: string]: unknown;
8730
+ };
8731
+ content: {
8732
+ "application/json": components["schemas"]["ErrorResponse"];
8733
+ };
8734
+ };
8735
+ /** @description Order is not in an approvable state (`INVALID_STATE`), or another lifecycle call holds the order lock (`OPERATION_IN_PROGRESS`) */
7811
8736
  409: {
7812
8737
  headers: {
7813
8738
  [name: string]: unknown;
@@ -7874,7 +8799,25 @@ export interface paths {
7874
8799
  };
7875
8800
  };
7876
8801
  };
7877
- /** @description Order is not in a cancelable state */
8802
+ /** @description Order does not belong to the caller's wallet */
8803
+ 403: {
8804
+ headers: {
8805
+ [name: string]: unknown;
8806
+ };
8807
+ content: {
8808
+ "application/json": components["schemas"]["ErrorResponse"];
8809
+ };
8810
+ };
8811
+ /** @description Order not found */
8812
+ 404: {
8813
+ headers: {
8814
+ [name: string]: unknown;
8815
+ };
8816
+ content: {
8817
+ "application/json": components["schemas"]["ErrorResponse"];
8818
+ };
8819
+ };
8820
+ /** @description Order is not in a cancelable state (`INVALID_STATE`), or another lifecycle call holds the order lock (`OPERATION_IN_PROGRESS`) */
7878
8821
  409: {
7879
8822
  headers: {
7880
8823
  [name: string]: unknown;
@@ -8090,11 +9033,11 @@ export interface paths {
8090
9033
  amount: number;
8091
9034
  from_currency_id: string;
8092
9035
  to_currency_id: string;
8093
- /** @description If `true`, calculates inputs needed to receive the given amount. */
8094
- is_reverse: boolean;
8095
- /** @description If `true`, the network fee is subtracted from `result_amount`. If `false`, the fee is added on top of `from_amount` and the recipient gets the full converted amount. Ignored for reverse calculations. Required so the client always states the fee-allocation mode explicitly — a change of the server-side fallback can never silently alter the calculation.
9036
+ /** @description If `true`, calculates inputs needed to receive the given amount. Defaults to `false`. */
9037
+ is_reverse?: boolean;
9038
+ /** @description If `true`, the network fee is subtracted from `result_amount`. If `false`, the fee is added on top of `from_amount` and the recipient gets the full converted amount. Ignored for reverse calculations. Defaults to `true` when omitted.
8096
9039
  * */
8097
- is_subtract: boolean;
9040
+ is_subtract?: boolean;
8098
9041
  /** @description Destination address (for crypto withdrawals; affects network fee estimation). */
8099
9042
  to_address?: string;
8100
9043
  };
@@ -8283,7 +9226,7 @@ export interface paths {
8283
9226
  };
8284
9227
  /**
8285
9228
  * Get order
8286
- * @description Retrieves a specific order by its numeric ID.
9229
+ * @description Retrieves a specific order by its `id` (UUID; equal to `order_uuid` for orders created by the current flow).
8287
9230
  *
8288
9231
  * **Authentication**: Bearer token with x-tenant-id header required
8289
9232
  *
@@ -8293,7 +9236,7 @@ export interface paths {
8293
9236
  query?: never;
8294
9237
  header?: never;
8295
9238
  path: {
8296
- order_id: number;
9239
+ order_id: string;
8297
9240
  };
8298
9241
  cookie?: never;
8299
9242
  };
@@ -8465,7 +9408,13 @@ export interface paths {
8465
9408
  };
8466
9409
  get?: never;
8467
9410
  put?: never;
8468
- /** Create omnibus crypto transfer */
9411
+ /**
9412
+ * Create omnibus crypto transfer
9413
+ * @description Legacy one-phase alias (frozen). Besides the documented fields the body must
9414
+ * carry `request_id` (idempotency key); `scheduled_at` is ignored.
9415
+ * Prefer `POST /frontend/orders/withdrawal/crypto`.
9416
+ *
9417
+ */
8469
9418
  post: {
8470
9419
  parameters: {
8471
9420
  query?: never;
@@ -8503,7 +9452,13 @@ export interface paths {
8503
9452
  };
8504
9453
  get?: never;
8505
9454
  put?: never;
8506
- /** Create segregated crypto transfer */
9455
+ /**
9456
+ * Create segregated crypto transfer
9457
+ * @description Legacy one-phase alias (frozen). Besides the documented fields the body must
9458
+ * carry `request_id` (idempotency key); `scheduled_at` is ignored.
9459
+ * Prefer `POST /frontend/orders/withdrawal/crypto`.
9460
+ *
9461
+ */
8507
9462
  post: {
8508
9463
  parameters: {
8509
9464
  query?: never;
@@ -8541,8 +9496,9 @@ export interface paths {
8541
9496
  };
8542
9497
  /**
8543
9498
  * List currencies
8544
- * @description Returns currencies (crypto table) with chain relations,
8545
- * filtered by the tenant of the authenticated session.
9499
+ * @description Returns every platform-enabled currency (crypto table) with chain relations,
9500
+ * annotated with `is_tenant_enabled`; pass `enabled_only=true` to keep only
9501
+ * the currencies enabled for the tenant of the authenticated session.
8546
9502
  * Each currency includes an `is_tenant_enabled` flag.
8547
9503
  *
8548
9504
  * **Authentication**: Bearer token + x-tenant-id header
@@ -9164,7 +10120,7 @@ export interface paths {
9164
10120
  };
9165
10121
  /**
9166
10122
  * List virtual accounts
9167
- * @description Retrieves a list of virtual accounts associated with a specific wallet.
10123
+ * @description Retrieves the ACTIVE virtual accounts associated with a specific wallet.
9168
10124
  *
9169
10125
  * **Authentication**: Bearer token with x-tenant-id header required
9170
10126
  *
@@ -9174,7 +10130,7 @@ export interface paths {
9174
10130
  get: {
9175
10131
  parameters: {
9176
10132
  query?: {
9177
- /** @description Number of items to return */
10133
+ /** @description Number of items to return (default 10) */
9178
10134
  limit?: number;
9179
10135
  /** @description Number of items to skip */
9180
10136
  offset?: number;
@@ -9198,11 +10154,7 @@ export interface paths {
9198
10154
  /** @example true */
9199
10155
  success?: boolean;
9200
10156
  data?: components["schemas"]["VirtualAccount"][];
9201
- pagination?: {
9202
- offset?: number;
9203
- limit?: number;
9204
- total?: number;
9205
- };
10157
+ pagination?: components["schemas"]["PaginationResponse"];
9206
10158
  };
9207
10159
  };
9208
10160
  };
@@ -9211,14 +10163,18 @@ export interface paths {
9211
10163
  headers: {
9212
10164
  [name: string]: unknown;
9213
10165
  };
9214
- content?: never;
10166
+ content: {
10167
+ "application/json": components["schemas"]["ErrorResponse"];
10168
+ };
9215
10169
  };
9216
10170
  /** @description Server error */
9217
10171
  500: {
9218
10172
  headers: {
9219
10173
  [name: string]: unknown;
9220
10174
  };
9221
- content?: never;
10175
+ content: {
10176
+ "application/json": components["schemas"]["ErrorResponse"];
10177
+ };
9222
10178
  };
9223
10179
  };
9224
10180
  };
@@ -9264,46 +10220,81 @@ export interface paths {
9264
10220
  "application/json": {
9265
10221
  /** @example true */
9266
10222
  success?: boolean;
9267
- data?: components["schemas"]["VirtualAccount"];
10223
+ data?: components["schemas"]["VirtualAccountCreated"];
9268
10224
  /** @example Virtual account created successfully */
9269
10225
  message?: string;
9270
10226
  };
9271
10227
  };
9272
10228
  };
9273
- /** @description Bad request - missing required parameters */
9274
- 400: {
10229
+ /** @description Accepted — the account is pending activation at the vendor (success envelope, no account yet); re-post the same request to poll */
10230
+ 202: {
9275
10231
  headers: {
9276
10232
  [name: string]: unknown;
9277
10233
  };
9278
10234
  content?: never;
9279
10235
  };
9280
- /** @description Forbidden - KYC verification required or no access */
10236
+ /** @description `INVALID_REQUEST` — missing `va_programs_id` or wallet binding */
10237
+ 400: {
10238
+ headers: {
10239
+ [name: string]: unknown;
10240
+ };
10241
+ content: {
10242
+ "application/json": components["schemas"]["ErrorResponse"];
10243
+ };
10244
+ };
10245
+ /** @description `ACCESS_DENIED` (no access to the wallet or role too low), `FORBIDDEN` (program not allowed for the caller's KYC profile) or `KYC_REQUIREMENTS_NOT_MET` (wallet KYC not approved) */
9281
10246
  403: {
9282
10247
  headers: {
9283
10248
  [name: string]: unknown;
9284
10249
  };
9285
- content?: never;
10250
+ content: {
10251
+ "application/json": components["schemas"]["ErrorResponse"];
10252
+ };
9286
10253
  };
9287
- /** @description Program not found */
10254
+ /** @description `NOT_FOUND` — wallet or program not found */
9288
10255
  404: {
9289
10256
  headers: {
9290
10257
  [name: string]: unknown;
9291
10258
  };
9292
- content?: never;
10259
+ content: {
10260
+ "application/json": components["schemas"]["ErrorResponse"];
10261
+ };
9293
10262
  };
9294
- /** @description Conflict - Virtual account already exists */
10263
+ /** @description `CONFLICT` — an account already occupies this program on the wallet; `error.details` carries the existing `account_id` and `status` */
9295
10264
  409: {
9296
10265
  headers: {
9297
10266
  [name: string]: unknown;
9298
10267
  };
9299
- content?: never;
10268
+ content: {
10269
+ "application/json": components["schemas"]["ErrorResponse"];
10270
+ };
9300
10271
  };
9301
- /** @description Server error */
10272
+ /** @description Rail pre-check failed — `VENDOR_NOT_CONFIGURED`, `RAIL_NOT_CONFIGURED`, `DEPOSITS_DISABLED`, `WALLET_RAIL_NOT_ONBOARDED` or `WALLET_RAIL_NOT_APPROVED` */
10273
+ 422: {
10274
+ headers: {
10275
+ [name: string]: unknown;
10276
+ };
10277
+ content: {
10278
+ "application/json": components["schemas"]["ErrorResponse"];
10279
+ };
10280
+ };
10281
+ /** @description `INTERNAL_ERROR` — generic message; details are only logged server-side */
9302
10282
  500: {
9303
10283
  headers: {
9304
10284
  [name: string]: unknown;
9305
10285
  };
9306
- content?: never;
10286
+ content: {
10287
+ "application/json": components["schemas"]["ErrorResponse"];
10288
+ };
10289
+ };
10290
+ /** @description The program's vendor is retired (Rail.io) or unsupported — no new accounts can be created on it */
10291
+ 501: {
10292
+ headers: {
10293
+ [name: string]: unknown;
10294
+ };
10295
+ content: {
10296
+ "application/json": components["schemas"]["ErrorResponse"];
10297
+ };
9307
10298
  };
9308
10299
  };
9309
10300
  };
@@ -9322,7 +10313,9 @@ export interface paths {
9322
10313
  };
9323
10314
  /**
9324
10315
  * List virtual account programs
9325
- * @description Retrieves a list of available virtual account programs filtered by wallet KYC access.
10316
+ * @description Retrieves the ACTIVE virtual account programs available to the wallet, filtered by
10317
+ * the wallet's KYC rail access (tenants with KYC disabled skip the rail filtering).
10318
+ * Archived and draft programs are never listed.
9326
10319
  *
9327
10320
  * **Authentication**: Bearer token with x-tenant-id header required
9328
10321
  *
@@ -9332,7 +10325,7 @@ export interface paths {
9332
10325
  get: {
9333
10326
  parameters: {
9334
10327
  query?: {
9335
- /** @description Number of items to return */
10328
+ /** @description Number of items to return (default 10) */
9336
10329
  limit?: number;
9337
10330
  /** @description Number of items to skip */
9338
10331
  offset?: number;
@@ -9356,13 +10349,9 @@ export interface paths {
9356
10349
  /** @example true */
9357
10350
  success?: boolean;
9358
10351
  data?: components["schemas"]["VirtualAccountProgram"][];
9359
- pagination?: {
9360
- offset?: number;
9361
- limit?: number;
9362
- total?: number;
9363
- };
10352
+ pagination?: components["schemas"]["PaginationResponse"];
9364
10353
  meta?: {
9365
- /** @description Total programs in database before KYC filtering */
10354
+ /** @description Number of programs visible to this wallet after KYC filtering (equals `pagination.total`) */
9366
10355
  total_count?: number;
9367
10356
  };
9368
10357
  };
@@ -9373,14 +10362,18 @@ export interface paths {
9373
10362
  headers: {
9374
10363
  [name: string]: unknown;
9375
10364
  };
9376
- content?: never;
10365
+ content: {
10366
+ "application/json": components["schemas"]["ErrorResponse"];
10367
+ };
9377
10368
  };
9378
10369
  /** @description Server error */
9379
10370
  500: {
9380
10371
  headers: {
9381
10372
  [name: string]: unknown;
9382
10373
  };
9383
- content?: never;
10374
+ content: {
10375
+ "application/json": components["schemas"]["ErrorResponse"];
10376
+ };
9384
10377
  };
9385
10378
  };
9386
10379
  };
@@ -9402,13 +10395,18 @@ export interface paths {
9402
10395
  /**
9403
10396
  * Get virtual account program
9404
10397
  * @description Retrieves detailed information about a specific virtual account program.
10398
+ * The by-id read is not status-filtered — a non-ACTIVE program is returned
10399
+ * when addressed directly.
9405
10400
  *
9406
10401
  * **Authentication**: Bearer token with x-tenant-id header required
9407
10402
  *
9408
10403
  */
9409
10404
  get: {
9410
10405
  parameters: {
9411
- query?: never;
10406
+ query?: {
10407
+ /** @description Wallet whose KYC entity type decides visibility; without it only universal-rail programs are visible on KYC-enabled tenants */
10408
+ wallet_id?: string;
10409
+ };
9412
10410
  header?: never;
9413
10411
  path: {
9414
10412
  /** @description The program ID */
@@ -9431,7 +10429,7 @@ export interface paths {
9431
10429
  };
9432
10430
  };
9433
10431
  };
9434
- /** @description Program not found */
10432
+ /** @description Program not found, or not allowed for the wallet's KYC rail */
9435
10433
  404: {
9436
10434
  headers: {
9437
10435
  [name: string]: unknown;
@@ -9466,12 +10464,14 @@ export interface paths {
9466
10464
  put?: never;
9467
10465
  /**
9468
10466
  * Sync virtual account
9469
- * @description Fetches the latest bank account details and deposit instructions from the vendor
9470
- * and updates the local record.
10467
+ * @description Refreshes the bank account details and deposit instructions from the vendor
10468
+ * (Brale / Delos / BCB) and updates the local record. Historical Rail.io
10469
+ * (RAIL-B / RAIL-C) accounts cannot be refreshed — their stored requisites are
10470
+ * returned unchanged.
9471
10471
  *
9472
10472
  * **Authentication**: Bearer token with x-tenant-id header required
9473
10473
  *
9474
- * **Access Control**: User must have access to the wallet containing this virtual account
10474
+ * **Access Control**: User must have access to the wallet containing this virtual account; wallet KYC must be APPROVED
9475
10475
  *
9476
10476
  */
9477
10477
  post: {
@@ -9486,7 +10486,7 @@ export interface paths {
9486
10486
  };
9487
10487
  requestBody?: never;
9488
10488
  responses: {
9489
- /** @description Virtual account synced successfully */
10489
+ /** @description Virtual account synced successfully. Same shape as the single-account read, without `crypto_deposit_details` */
9490
10490
  200: {
9491
10491
  headers: {
9492
10492
  [name: string]: unknown;
@@ -9495,7 +10495,7 @@ export interface paths {
9495
10495
  "application/json": {
9496
10496
  /** @example true */
9497
10497
  success?: boolean;
9498
- data?: components["schemas"]["VirtualAccount"];
10498
+ data?: components["schemas"]["VirtualAccountDetail"];
9499
10499
  /** @example Virtual account synced successfully */
9500
10500
  message?: string;
9501
10501
  };
@@ -9508,7 +10508,7 @@ export interface paths {
9508
10508
  };
9509
10509
  content?: never;
9510
10510
  };
9511
- /** @description Access denied */
10511
+ /** @description Access denied, or wallet KYC not approved */
9512
10512
  403: {
9513
10513
  headers: {
9514
10514
  [name: string]: unknown;
@@ -9554,7 +10554,10 @@ export interface paths {
9554
10554
  /**
9555
10555
  * Get virtual account
9556
10556
  * @description Retrieves detailed information about a specific virtual account.
9557
- * Requisites are automatically synced from vendor on every request.
10557
+ * For accounts linked to a vendor (Brale / Delos / BCB) the requisites are refreshed
10558
+ * from the vendor on read unless `skip_sync=true`; a failed refresh falls back to the
10559
+ * cached data (still 200). Accounts without a vendor link and historical Rail.io
10560
+ * accounts return the stored data.
9558
10561
  *
9559
10562
  * **Authentication**: Bearer token with x-tenant-id header required
9560
10563
  *
@@ -9576,7 +10579,7 @@ export interface paths {
9576
10579
  };
9577
10580
  requestBody?: never;
9578
10581
  responses: {
9579
- /** @description Virtual account details retrieved successfully (auto-synced) */
10582
+ /** @description Virtual account details retrieved successfully (requisites refreshed from the vendor when linked) */
9580
10583
  200: {
9581
10584
  headers: {
9582
10585
  [name: string]: unknown;
@@ -9585,7 +10588,7 @@ export interface paths {
9585
10588
  "application/json": {
9586
10589
  /** @example true */
9587
10590
  success?: boolean;
9588
- data?: components["schemas"]["VirtualAccount"];
10591
+ data?: components["schemas"]["VirtualAccountDetail"];
9589
10592
  };
9590
10593
  };
9591
10594
  };
@@ -9594,21 +10597,27 @@ export interface paths {
9594
10597
  headers: {
9595
10598
  [name: string]: unknown;
9596
10599
  };
9597
- content?: never;
10600
+ content: {
10601
+ "application/json": components["schemas"]["ErrorResponse"];
10602
+ };
9598
10603
  };
9599
10604
  /** @description Virtual account not found */
9600
10605
  404: {
9601
10606
  headers: {
9602
10607
  [name: string]: unknown;
9603
10608
  };
9604
- content?: never;
10609
+ content: {
10610
+ "application/json": components["schemas"]["ErrorResponse"];
10611
+ };
9605
10612
  };
9606
10613
  /** @description Server error */
9607
10614
  500: {
9608
10615
  headers: {
9609
10616
  [name: string]: unknown;
9610
10617
  };
9611
- content?: never;
10618
+ content: {
10619
+ "application/json": components["schemas"]["ErrorResponse"];
10620
+ };
9612
10621
  };
9613
10622
  };
9614
10623
  };
@@ -9637,7 +10646,7 @@ export interface paths {
9637
10646
  * - `id` — user_data.id (numeric)
9638
10647
  * - `email` — user_data.email (case-insensitive)
9639
10648
  * - `phone` — user_data.phone
9640
- * - `telegram` — telegram_id from auth_telegram table
10649
+ * - `telegram` — `telegram_user.tg_id`, or a case-insensitive `username` match (leading `@` ignored)
9641
10650
  *
9642
10651
  * **Authentication**: Bearer token with x-tenant-id header required
9643
10652
  *
@@ -9993,6 +11002,9 @@ export interface paths {
9993
11002
  *
9994
11003
  * Each wallet includes `access_role` (owner/admin/user/auditor) and `is_owner` boolean.
9995
11004
  *
11005
+ * Wallets where the caller holds the scoped `user` role are returned as a reduced shell
11006
+ * (`uuid`, `name`, `display_name`, `tenant_id`, `kyc_info`, `created_at` + the role fields) — no `logo_url`.
11007
+ *
9996
11008
  * **Authentication**: Bearer token with x-tenant-id header required
9997
11009
  *
9998
11010
  */
@@ -10038,13 +11050,11 @@ export interface paths {
10038
11050
  */
10039
11051
  display_name?: string;
10040
11052
  /** @description Avatar URL for the wallet */
10041
- logo_url: string | null;
11053
+ logo_url?: string | null;
10042
11054
  /** Format: uuid */
10043
11055
  tenant_id: string;
10044
11056
  /** Format: date-time */
10045
11057
  created_at: string;
10046
- /** Format: date-time */
10047
- updated_at: string;
10048
11058
  /**
10049
11059
  * @description Legacy alias of `access_role`. Kept for backward compatibility —
10050
11060
  * always equals `access_role`. Prefer `access_role` in new code.
@@ -10083,8 +11093,8 @@ export interface paths {
10083
11093
  };
10084
11094
  };
10085
11095
  };
10086
- /** @description User not authenticated */
10087
- 403: {
11096
+ /** @description Missing or invalid bearer token */
11097
+ 401: {
10088
11098
  headers: {
10089
11099
  [name: string]: unknown;
10090
11100
  };
@@ -10174,10 +11184,8 @@ export interface paths {
10174
11184
  tenant_id: string;
10175
11185
  /** Format: date-time */
10176
11186
  created_at: string;
10177
- /** Format: date-time */
10178
- updated_at: string;
10179
- /** @description Mirrors the GET-wallet shape. Always `null` on create
10180
- * (no `kyc_entity` row exists yet).
11187
+ /** @description Mirrors the GET-wallet shape. `null` when the wallet was created
11188
+ * without `kyc_entity_id`; populated with the linked entity otherwise.
10181
11189
  * */
10182
11190
  kyc_info: {
10183
11191
  type: string;
@@ -10240,7 +11248,7 @@ export interface paths {
10240
11248
  *
10241
11249
  * **Authentication**: Bearer token with x-tenant-id header required
10242
11250
  *
10243
- * **Access Control**: Any user with access to the wallet
11251
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403); wallet KYC must be APPROVED or HOLD
10244
11252
  *
10245
11253
  */
10246
11254
  get: {
@@ -10403,7 +11411,9 @@ export interface paths {
10403
11411
  *
10404
11412
  * **Authentication**: Bearer token with x-tenant-id header required
10405
11413
  *
10406
- * **Access Control**: User must own the wallet
11414
+ * **Access Control**: Any active wallet member. The scoped `user` role receives a shell-only
11415
+ * response (`uuid`, `name`, `display_name`, `tenant_id`, `kyc_info`, `created_at` + the role fields) —
11416
+ * `logo_url`, `balance`, `fiat_accounts` and the totals are omitted for that role.
10407
11417
  *
10408
11418
  */
10409
11419
  get: {
@@ -10446,8 +11456,6 @@ export interface paths {
10446
11456
  tenant_id: string;
10447
11457
  /** Format: date-time */
10448
11458
  created_at: string;
10449
- /** Format: date-time */
10450
- updated_at: string;
10451
11459
  kyc_info: {
10452
11460
  type: string;
10453
11461
  status: string;
@@ -10576,8 +11584,6 @@ export interface paths {
10576
11584
  tenant_id: string;
10577
11585
  /** Format: date-time */
10578
11586
  created_at: string;
10579
- /** Format: date-time */
10580
- updated_at: string;
10581
11587
  /** @description KYC entity attached to the wallet (joined from `kyc_entity`).
10582
11588
  * `null` when the wallet has no KYC entity yet.
10583
11589
  * */
@@ -10642,7 +11648,7 @@ export interface paths {
10642
11648
  *
10643
11649
  * **Authentication**: Bearer token with x-tenant-id header required
10644
11650
  *
10645
- * **Access Control**: User must own the wallet
11651
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403); wallet KYC must be APPROVED or HOLD
10646
11652
  *
10647
11653
  * This is a simplified version of the main wallet endpoint that:
10648
11654
  * - Returns raw balance records without aggregation
@@ -10683,8 +11689,6 @@ export interface paths {
10683
11689
  tenant_id: string;
10684
11690
  /** Format: date-time */
10685
11691
  created_at: string;
10686
- /** Format: date-time */
10687
- updated_at: string;
10688
11692
  /** @description Array of balance records */
10689
11693
  balance: {
10690
11694
  /** Format: uuid */
@@ -10763,7 +11767,7 @@ export interface paths {
10763
11767
  *
10764
11768
  * **Authentication**: Bearer token with x-tenant-id header required
10765
11769
  *
10766
- * **Access Control**: User must own the wallet
11770
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403); wallet KYC must be APPROVED or HOLD
10767
11771
  *
10768
11772
  */
10769
11773
  get: {
@@ -10860,7 +11864,7 @@ export interface paths {
10860
11864
  *
10861
11865
  * **Authentication**: Bearer token with x-tenant-id header required
10862
11866
  *
10863
- * **Access Control**: Any user with access to the wallet
11867
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403); wallet KYC must be APPROVED or HOLD
10864
11868
  *
10865
11869
  */
10866
11870
  get: {
@@ -10933,7 +11937,7 @@ export interface paths {
10933
11937
  *
10934
11938
  * **Authentication**: Bearer token with x-tenant-id header required
10935
11939
  *
10936
- * **Access Control**: User must own the wallet
11940
+ * **Access Control**: Owner or admin of the wallet; wallet KYC must be APPROVED
10937
11941
  *
10938
11942
  * **Note**: New addresses are always provisioned via Utila. The legacy Processing (Accepta) provider was decommissioned; existing `processing` addresses remain readable.
10939
11943
  *
@@ -10945,8 +11949,8 @@ export interface paths {
10945
11949
  path: {
10946
11950
  /** @description The ID of the wallet */
10947
11951
  wallet_id: string;
10948
- /** @description The blockchain ID (e.g., 'ethereum', 'bitcoin') */
10949
- chain: string;
11952
+ /** @description Numeric chain ID (see `GET /frontend/reference/chains`) */
11953
+ chain: number;
10950
11954
  };
10951
11955
  cookie?: never;
10952
11956
  };
@@ -10962,7 +11966,7 @@ export interface paths {
10962
11966
  };
10963
11967
  };
10964
11968
  responses: {
10965
- /** @description Crypto address created successfully */
11969
+ /** @description Crypto address created — or the existing address for this chain returned (idempotent, always 201) */
10966
11970
  201: {
10967
11971
  headers: {
10968
11972
  [name: string]: unknown;
@@ -11005,13 +12009,6 @@ export interface paths {
11005
12009
  };
11006
12010
  content?: never;
11007
12011
  };
11008
- /** @description Address for this chain already exists */
11009
- 409: {
11010
- headers: {
11011
- [name: string]: unknown;
11012
- };
11013
- content?: never;
11014
- };
11015
12012
  /** @description Server error */
11016
12013
  500: {
11017
12014
  headers: {
@@ -11040,7 +12037,7 @@ export interface paths {
11040
12037
  *
11041
12038
  * **Authentication**: Bearer token with x-tenant-id header required
11042
12039
  *
11043
- * **Access Control**: User must own the wallet
12040
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403); wallet KYC must be APPROVED or HOLD
11044
12041
  *
11045
12042
  */
11046
12043
  get: {
@@ -11154,7 +12151,7 @@ export interface paths {
11154
12151
  *
11155
12152
  * **Authentication**: Bearer token with x-tenant-id header required
11156
12153
  *
11157
- * **Access Control**: User must own the wallet
12154
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403); wallet KYC must be APPROVED or HOLD
11158
12155
  *
11159
12156
  */
11160
12157
  get: {
@@ -11320,7 +12317,7 @@ export interface paths {
11320
12317
  *
11321
12318
  * **Authentication**: Bearer token with x-tenant-id header required
11322
12319
  *
11323
- * **Access Control**: Any user with access to the wallet can view the user list
12320
+ * **Access Control**: Any owner/admin/auditor member of the wallet (the scoped `user` role is rejected with 403)
11324
12321
  *
11325
12322
  */
11326
12323
  get: {
@@ -11414,14 +12411,14 @@ export interface paths {
11414
12411
  * @description Adds a user to the wallet by their user_data.uuid.
11415
12412
  *
11416
12413
  * **Rules:**
11417
- * - Only the wallet **owner** can add users
12414
+ * - Only the wallet **owner** or an **admin** can add users
11418
12415
  * - Target user must be in the **same tenant**
11419
12416
  * - Target user must **not** be the wallet owner
11420
- * - Allowed roles: `user`, `admin`
12417
+ * - Allowed roles: `auditor`, `user`, `admin`
11421
12418
  *
11422
12419
  * **Authentication**: Bearer token with x-tenant-id header required
11423
12420
  *
11424
- * **Access Control**: Owner only
12421
+ * **Access Control**: Owner or admin of the wallet; wallet KYC must be APPROVED
11425
12422
  *
11426
12423
  */
11427
12424
  post: {
@@ -11476,29 +12473,22 @@ export interface paths {
11476
12473
  };
11477
12474
  };
11478
12475
  };
11479
- /** @description Bad request - missing fields or invalid role */
12476
+ /** @description Bad request - missing fields or invalid role; `CONFLICT` when the user is already a member or is the wallet owner */
11480
12477
  400: {
11481
12478
  headers: {
11482
12479
  [name: string]: unknown;
11483
12480
  };
11484
12481
  content?: never;
11485
12482
  };
11486
- /** @description Only the wallet owner can add users / user not in same tenant */
12483
+ /** @description Caller is not owner/admin of the wallet, wallet KYC not approved, or target user not in the same tenant */
11487
12484
  403: {
11488
12485
  headers: {
11489
12486
  [name: string]: unknown;
11490
12487
  };
11491
12488
  content?: never;
11492
12489
  };
11493
- /** @description Wallet or target user not found */
11494
- 404: {
11495
- headers: {
11496
- [name: string]: unknown;
11497
- };
11498
- content?: never;
11499
- };
11500
- /** @description User is already added to this wallet / cannot add owner */
11501
- 409: {
12490
+ /** @description Wallet or target user not found */
12491
+ 404: {
11502
12492
  headers: {
11503
12493
  [name: string]: unknown;
11504
12494
  };
@@ -11534,11 +12524,11 @@ export interface paths {
11534
12524
  * @description Removes a shared user from the wallet (sets is_active = false).
11535
12525
  *
11536
12526
  * **Rules:**
11537
- * - Only the wallet **owner** can remove users
12527
+ * - Only the wallet **owner** or an **admin** can remove users
11538
12528
  *
11539
12529
  * **Authentication**: Bearer token with x-tenant-id header required
11540
12530
  *
11541
- * **Access Control**: Owner only
12531
+ * **Access Control**: Owner or admin of the wallet; wallet KYC must be APPROVED
11542
12532
  *
11543
12533
  */
11544
12534
  delete: {
@@ -11570,7 +12560,7 @@ export interface paths {
11570
12560
  };
11571
12561
  };
11572
12562
  };
11573
- /** @description Only the wallet owner can remove users */
12563
+ /** @description Caller is not owner/admin of the wallet, or wallet KYC not approved */
11574
12564
  403: {
11575
12565
  headers: {
11576
12566
  [name: string]: unknown;
@@ -11600,12 +12590,12 @@ export interface paths {
11600
12590
  * @description Updates the role of a shared user on this wallet.
11601
12591
  *
11602
12592
  * **Rules:**
11603
- * - Only the wallet **owner** can update roles
11604
- * - Allowed roles: `user`, `admin`
12593
+ * - Only the wallet **owner** or an **admin** can update roles
12594
+ * - Allowed roles: `auditor`, `user`, `admin`
11605
12595
  *
11606
12596
  * **Authentication**: Bearer token with x-tenant-id header required
11607
12597
  *
11608
- * **Access Control**: Owner only
12598
+ * **Access Control**: Owner or admin of the wallet; wallet KYC must be APPROVED
11609
12599
  *
11610
12600
  */
11611
12601
  patch: {
@@ -11647,14 +12637,14 @@ export interface paths {
11647
12637
  };
11648
12638
  };
11649
12639
  };
11650
- /** @description Invalid role */
12640
+ /** @description Invalid role; `CONFLICT` when the target is the wallet owner */
11651
12641
  400: {
11652
12642
  headers: {
11653
12643
  [name: string]: unknown;
11654
12644
  };
11655
12645
  content?: never;
11656
12646
  };
11657
- /** @description Only the wallet owner can update roles */
12647
+ /** @description Caller is not owner/admin of the wallet, or wallet KYC not approved */
11658
12648
  403: {
11659
12649
  headers: {
11660
12650
  [name: string]: unknown;
@@ -11693,12 +12683,12 @@ export interface paths {
11693
12683
  * @description Re-activates a previously deactivated user on this wallet.
11694
12684
  *
11695
12685
  * **Rules:**
11696
- * - Only the wallet **owner** can activate users
12686
+ * - Only the wallet **owner** or an **admin** can activate users
11697
12687
  * - Cannot activate the wallet owner themselves
11698
12688
  *
11699
12689
  * **Authentication**: Bearer token with x-tenant-id header required
11700
12690
  *
11701
- * **Access Control**: Owner only
12691
+ * **Access Control**: Owner or admin of the wallet; wallet KYC must be APPROVED
11702
12692
  *
11703
12693
  */
11704
12694
  post: {
@@ -11730,22 +12720,22 @@ export interface paths {
11730
12720
  };
11731
12721
  };
11732
12722
  };
11733
- /** @description Only the wallet owner can activate users */
11734
- 403: {
12723
+ /** @description Target is the wallet owner (`CONFLICT`) */
12724
+ 400: {
11735
12725
  headers: {
11736
12726
  [name: string]: unknown;
11737
12727
  };
11738
12728
  content?: never;
11739
12729
  };
11740
- /** @description User not found in this wallet */
11741
- 404: {
12730
+ /** @description Caller is not owner/admin of the wallet, or wallet KYC not approved */
12731
+ 403: {
11742
12732
  headers: {
11743
12733
  [name: string]: unknown;
11744
12734
  };
11745
12735
  content?: never;
11746
12736
  };
11747
- /** @description Cannot change active status of the wallet owner */
11748
- 409: {
12737
+ /** @description User not found in this wallet */
12738
+ 404: {
11749
12739
  headers: {
11750
12740
  [name: string]: unknown;
11751
12741
  };
@@ -11781,12 +12771,12 @@ export interface paths {
11781
12771
  * The user record is preserved but the user loses access to the wallet.
11782
12772
  *
11783
12773
  * **Rules:**
11784
- * - Only the wallet **owner** can deactivate users
12774
+ * - Only the wallet **owner** or an **admin** can deactivate users
11785
12775
  * - Cannot deactivate the wallet owner themselves
11786
12776
  *
11787
12777
  * **Authentication**: Bearer token with x-tenant-id header required
11788
12778
  *
11789
- * **Access Control**: Owner only
12779
+ * **Access Control**: Owner or admin of the wallet; wallet KYC must be APPROVED
11790
12780
  *
11791
12781
  */
11792
12782
  post: {
@@ -11818,22 +12808,22 @@ export interface paths {
11818
12808
  };
11819
12809
  };
11820
12810
  };
11821
- /** @description Only the wallet owner can deactivate users */
11822
- 403: {
12811
+ /** @description Target is the wallet owner (`CONFLICT`) */
12812
+ 400: {
11823
12813
  headers: {
11824
12814
  [name: string]: unknown;
11825
12815
  };
11826
12816
  content?: never;
11827
12817
  };
11828
- /** @description User not found in this wallet */
11829
- 404: {
12818
+ /** @description Caller is not owner/admin of the wallet, or wallet KYC not approved */
12819
+ 403: {
11830
12820
  headers: {
11831
12821
  [name: string]: unknown;
11832
12822
  };
11833
12823
  content?: never;
11834
12824
  };
11835
- /** @description Cannot change active status of the wallet owner */
11836
- 409: {
12825
+ /** @description User not found in this wallet */
12826
+ 404: {
11837
12827
  headers: {
11838
12828
  [name: string]: unknown;
11839
12829
  };
@@ -11903,7 +12893,7 @@ export interface paths {
11903
12893
  };
11904
12894
  };
11905
12895
  };
11906
- /** @description Invalid query parameter (offset/limit/is_completed/role) */
12896
+ /** @description Invalid query parameter (non-integer offset/limit, unknown role); any value other than `true`/`1` for `is_completed`/`is_expired` is read as `false` */
11907
12897
  400: {
11908
12898
  headers: {
11909
12899
  [name: string]: unknown;
@@ -12213,7 +13203,7 @@ export type webhooks = Record<string, never>;
12213
13203
  export interface components {
12214
13204
  schemas: {
12215
13205
  /**
12216
- * @description Order type identifier. Must be one of the active values from the `order_types` table. Examples: `EXCHANGE_OMNI` (omnibus exchange), `L2F_SWIFT_OFFRAMP` (SWIFT offramp), `OMNIBUS_CRYPTO_TRANSFER` (crypto withdrawal). Legacy `DEPOSIT_*`, `WITHDRAWAL_*` and `AUTO_CONVERT_CRYPTO` are intentionally excluded.
13206
+ * @description Order type identifier. Must be one of the active values from the `order_types` table. Examples: `EXCHANGE_OMNI` (omnibus exchange), `BRL_WIRE_OFFRAMP` (wire offramp), `OMNIBUS_CRYPTO_TRANSFER` (crypto withdrawal). `L2F_*` ids are historical (rail retired) and cannot be used to create orders. Legacy `DEPOSIT_*`, `WITHDRAWAL_*` and `AUTO_CONVERT_CRYPTO` are intentionally excluded.
12217
13207
  * @example EXCHANGE_OMNI
12218
13208
  * @enum {string}
12219
13209
  */
@@ -12279,9 +13269,13 @@ export interface components {
12279
13269
  ErrorResponse: {
12280
13270
  /** @example false */
12281
13271
  success?: boolean;
13272
+ /** @description Request correlation id — quote it in support requests */
13273
+ correlationId?: string;
12282
13274
  error?: {
12283
13275
  code?: string;
12284
13276
  message?: string;
13277
+ /** @description Structured payload (validation issues, missing fields) when the error carries one */
13278
+ details?: Record<string, never> | null;
12285
13279
  };
12286
13280
  };
12287
13281
  /** @description Counterparty account (beneficiary). Wallet-scoped. */
@@ -12315,7 +13309,7 @@ export interface components {
12315
13309
  /** @description Active destinations belonging to this account. */
12316
13310
  destinations: components["schemas"]["CounterpartyDestination"][];
12317
13311
  };
12318
- /** @description Bank / beneficiary postal address. */
13312
+ /** @description Registered postal address of the BANK (not the beneficiary). On create it is replaced atomically by the bank-directory address when the submitted bank code resolves to a complete one; otherwise the submitted address is kept. */
12319
13313
  CounterpartyBankingAddress: {
12320
13314
  city?: string | null;
12321
13315
  postcode?: string | null;
@@ -12392,7 +13386,7 @@ export interface components {
12392
13386
  * @description Destination / payment rail type
12393
13387
  * @enum {string}
12394
13388
  */
12395
- type: "ACH" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "INTERNAL";
13389
+ type: "ACH" | "RTP" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "INTERNAL";
12396
13390
  /** @description User-friendly alias */
12397
13391
  nickname?: string | null;
12398
13392
  /** Format: date-time */
@@ -12642,8 +13636,17 @@ export interface components {
12642
13636
  vendor_card_id?: string;
12643
13637
  /** Format: uuid */
12644
13638
  cardholder_id?: string | null;
12645
- /** @description Cardholder record, or null */
12646
- cardholder?: components["schemas"]["IssuingCardholder"] | null;
13639
+ /** @description Cardholder summary, or null */
13640
+ cardholder?: {
13641
+ /** Format: uuid */
13642
+ id?: string;
13643
+ first_name?: string | null;
13644
+ last_name?: string | null;
13645
+ email?: string | null;
13646
+ phone?: string | null;
13647
+ birth_date?: string | null;
13648
+ nationality?: string | null;
13649
+ } | null;
12647
13650
  /** @description user_data.id the card is assigned to; omitted (absent) when the card is not assigned to a member */
12648
13651
  user_data_id?: number;
12649
13652
  /** @description Embedded sub-account summary, or null when no sub-account is linked. Present on the normal (vendor-enriched) response; omitted only in the degraded local-only error mode. */
@@ -12767,8 +13770,6 @@ export interface components {
12767
13770
  /** @description Units of billing currency per unit of transaction currency, so `transaction_amount * conversion_rate ≈ billing_amount`. 1 when the currencies match. */
12768
13771
  conversion_rate?: number;
12769
13772
  failure_reason?: string;
12770
- adjustment_type?: string | null;
12771
- review_status?: string | null;
12772
13773
  has_receipt?: boolean;
12773
13774
  merchant?: components["schemas"]["TransactionMerchant"];
12774
13775
  /** Format: date-time */
@@ -12958,16 +13959,234 @@ export interface components {
12958
13959
  /** @description Error code for programmatic handling */
12959
13960
  code?: string;
12960
13961
  };
12961
- /** @description Virtual bank account */
12962
- VirtualAccount: {
13962
+ /** @description Full currency object embedded on virtual-account reads (from the `crypto` table). */
13963
+ VirtualAccountCurrency: components["schemas"]["CurrencyDetails"] & {
13964
+ is_crypto?: boolean;
13965
+ enabled?: boolean;
13966
+ /** @description Currency type discriminator */
13967
+ type?: string;
13968
+ meta?: {
13969
+ [key: string]: unknown;
13970
+ } | null;
13971
+ };
13972
+ /** @description Compact currency reference joined onto program reads (no `decimal`). */
13973
+ CurrencySummary: {
13974
+ /** Format: uuid */
13975
+ uuid?: string;
13976
+ name?: string;
13977
+ symbol?: string;
13978
+ icon?: string | null;
13979
+ type?: string;
13980
+ };
13981
+ /** @description KYC rail attached to a virtual-account program. Program reads embed the full rail; rails embedded inside virtual-account reads omit `is_deposit_enabled` (internal toggle). */
13982
+ KycRail: {
13983
+ /** Format: uuid */
13984
+ id?: string;
13985
+ name?: string;
13986
+ code?: string | null;
13987
+ vendor_code?: string | null;
13988
+ /** Format: uuid */
13989
+ integration_vendors_id?: string | null;
13990
+ type?: string;
13991
+ /** Format: uuid */
13992
+ tenant_id?: string;
13993
+ /** Format: uuid */
13994
+ countries_group_id?: string | null;
13995
+ is_active?: boolean;
13996
+ is_manual?: boolean;
13997
+ is_submit_available?: boolean;
13998
+ /** @description Present on program reads only — stripped from rails embedded in virtual-account responses */
13999
+ is_deposit_enabled?: boolean;
14000
+ };
14001
+ /** @description Raw virtual-account program row. */
14002
+ VirtualAccountProgramBase: {
14003
+ /** Format: uuid */
14004
+ id?: string;
14005
+ name?: string;
14006
+ description?: string | null;
14007
+ /**
14008
+ * @description Program listings return ACTIVE programs only; the by-id read is not status-filtered
14009
+ * @enum {string}
14010
+ */
14011
+ status?: "DRAFT" | "ACTIVE" | "ARCHIVED";
14012
+ icon?: string | null;
14013
+ code?: string | null;
14014
+ /** @description Vendor-side program identifier */
14015
+ vendor_id?: string | null;
14016
+ /** Format: uuid */
14017
+ tenant_id?: string;
14018
+ /** Format: uuid */
14019
+ account_currency_id?: string;
14020
+ /** Format: uuid */
14021
+ destination_currency_id?: string;
14022
+ /** Format: uuid */
14023
+ kyc_rails_id?: string;
14024
+ /** @description Consent text shown before opening an account on this program */
14025
+ consent_text?: string | null;
14026
+ /** Format: uuid */
14027
+ integration_vendors_id?: string;
14028
+ is_hidden?: boolean;
14029
+ };
14030
+ /** @description Program as returned by the program reads (list and by-id): the raw row hydrated with vendor, currency, order-type and KYC-rail joins. */
14031
+ VirtualAccountProgram: components["schemas"]["VirtualAccountProgramBase"] & {
14032
+ integration_vendor?: {
14033
+ /** Format: uuid */
14034
+ id?: string;
14035
+ name?: string;
14036
+ code?: string;
14037
+ type?: string;
14038
+ } | null;
14039
+ account_currency_details?: components["schemas"]["CurrencySummary"] | null;
14040
+ destination_currency_details?: components["schemas"]["CurrencySummary"] | null;
14041
+ /** @description Order types enabled on the program */
14042
+ virtual_accounts_programs_order_types?: {
14043
+ /** Format: uuid */
14044
+ order_type_id?: string;
14045
+ order_type?: {
14046
+ /** Format: uuid */
14047
+ id?: string;
14048
+ description?: string | null;
14049
+ } | null;
14050
+ }[];
14051
+ kyc_rails?: components["schemas"]["KycRail"] | null;
14052
+ };
14053
+ /** @description Fields shared by every virtual-account read shape. */
14054
+ VirtualAccountBase: {
12963
14055
  /** Format: uuid */
12964
14056
  id?: string;
14057
+ /** Format: date-time */
14058
+ created_at?: string;
12965
14059
  /** Format: uuid */
12966
14060
  wallet_id?: string;
12967
14061
  /** Format: uuid */
12968
14062
  va_programs_id?: string;
12969
- /** @enum {string} */
12970
- status?: "ACTIVE" | "INACTIVE" | "PENDING" | "CANCELED";
14063
+ /**
14064
+ * @description PENDING — awaiting upstream provisioning (re-post create to poll); FAILED — rejected upstream, the program can be re-opened
14065
+ * @enum {string}
14066
+ */
14067
+ status?: "ACTIVE" | "CANCELED" | "FROZEN" | "INACTIVE" | "CLOSED" | "BLOCKED" | "PENDING" | "FAILED";
14068
+ /** @description Settlement destination address (when the program settles to crypto) */
14069
+ destination_address?: string | null;
14070
+ /** Format: uuid */
14071
+ integration_vendor_id?: string;
14072
+ vendor_account_id?: string;
14073
+ /** @description Customer name the account is held under */
14074
+ customer_name?: string | null;
14075
+ /** @description Bank requisites summary derived from deposit_instructions. Empty object when the account has no instructions; null when deposits are disabled on the program's KYC rail. */
14076
+ account_details?: {
14077
+ ach?: {
14078
+ accountNumber?: string;
14079
+ routingNumber?: string;
14080
+ } | null;
14081
+ wire?: {
14082
+ accountNumber?: string;
14083
+ routingNumber?: string;
14084
+ } | null;
14085
+ swift?: {
14086
+ swiftCode?: string;
14087
+ accountNumber?: string;
14088
+ } | null;
14089
+ sepa?: {
14090
+ iban?: string;
14091
+ swiftCode?: string;
14092
+ } | null;
14093
+ ukPayments?: {
14094
+ accountNumber?: string;
14095
+ sortCode?: string;
14096
+ } | null;
14097
+ swiftCode?: string | null;
14098
+ bankName?: string | null;
14099
+ bankAddress?: string | null;
14100
+ beneficiary?: {
14101
+ name?: string;
14102
+ address?: string | null;
14103
+ } | null;
14104
+ } | null;
14105
+ /** @description Deposit requisites (source of truth). Emptied to [] (never null) when deposits are disabled on the program's KYC rail. */
14106
+ deposit_instructions?: {
14107
+ [key: string]: unknown;
14108
+ }[] | null;
14109
+ meta?: Record<string, never> | null;
14110
+ };
14111
+ /** @description Virtual bank account as returned by the list read. Currencies come embedded as full objects; the raw uuids are exposed as `account_currency_id` / `destination_currency_id`. Only ACTIVE accounts are listed. */
14112
+ VirtualAccount: components["schemas"]["VirtualAccountBase"] & {
14113
+ /** @description Account currency as a full currency object (list read only — the single read returns a uuid string here) */
14114
+ account_currency?: components["schemas"]["VirtualAccountCurrency"];
14115
+ /** @description Destination currency as a full currency object (list read only — the single read returns a uuid string here) */
14116
+ destination_currency?: components["schemas"]["VirtualAccountCurrency"];
14117
+ /** Format: uuid */
14118
+ account_currency_id?: string;
14119
+ /** Format: uuid */
14120
+ destination_currency_id?: string;
14121
+ /** @description Owning program: the raw row plus its order types and KYC rail (rail without `is_deposit_enabled`) */
14122
+ virtual_accounts_program?: components["schemas"]["VirtualAccountProgramBase"] & {
14123
+ order_types?: {
14124
+ /** Format: uuid */
14125
+ order_type_id?: string;
14126
+ }[];
14127
+ kyc_rails?: components["schemas"]["KycRail"] | null;
14128
+ };
14129
+ };
14130
+ /** @description Virtual account as returned by the single-account read (also by sync, which omits `crypto_deposit_details`). Superset of the stored row: currencies stay uuid strings, hydrated objects arrive in `account_currency_details` / `destination_currency_details`. */
14131
+ VirtualAccountDetail: components["schemas"]["VirtualAccountBase"] & {
14132
+ /** Format: uuid */
14133
+ account_currency?: string;
14134
+ /** Format: uuid */
14135
+ destination_currency?: string;
14136
+ /** Format: uuid */
14137
+ account_currency_id?: string;
14138
+ /** Format: uuid */
14139
+ destination_currency_id?: string;
14140
+ account_currency_details?: components["schemas"]["VirtualAccountCurrency"] | null;
14141
+ destination_currency_details?: components["schemas"]["VirtualAccountCurrency"] | null;
14142
+ /** @description Always 0 — a virtual account carries no balance of its own */
14143
+ balance?: number;
14144
+ /** @description Always 0 — a virtual account carries no balance of its own */
14145
+ total_balance?: number;
14146
+ /** @description Stablecoin deposit addresses resolved from the account meta (single-account read only; empty array when none) */
14147
+ crypto_deposit_details?: {
14148
+ /** Format: uuid */
14149
+ currency_id?: string;
14150
+ deposit_address?: string;
14151
+ chain_id?: number;
14152
+ }[];
14153
+ /** @description Order type ids enabled on the owning program */
14154
+ order_types?: string[];
14155
+ /** @description Owning program: the raw row plus its order types (no rail embed on this read) */
14156
+ virtual_accounts_program?: components["schemas"]["VirtualAccountProgramBase"] & {
14157
+ order_types?: {
14158
+ /** Format: uuid */
14159
+ order_type_id?: string;
14160
+ }[];
14161
+ };
14162
+ };
14163
+ /** @description Create response shape: the stored account row only. Currencies are uuid strings, the hydrated fields of the list/single reads are absent, and `virtual_accounts_program` carries just the program's KYC rail reference. */
14164
+ VirtualAccountCreated: components["schemas"]["VirtualAccountBase"] & {
14165
+ /** Format: uuid */
14166
+ account_currency?: string;
14167
+ /** Format: uuid */
14168
+ destination_currency?: string;
14169
+ virtual_accounts_program?: {
14170
+ kyc_rails?: {
14171
+ /** Format: uuid */
14172
+ id?: string;
14173
+ is_active?: boolean;
14174
+ } | null;
14175
+ };
14176
+ };
14177
+ /** @description Virtual account as embedded in order responses: the stored row hydrated with currency and vendor details. */
14178
+ OrderVirtualAccount: {
14179
+ /** Format: uuid */
14180
+ id?: string;
14181
+ /** Format: uuid */
14182
+ wallet_id?: string;
14183
+ /** Format: uuid */
14184
+ va_programs_id?: string;
14185
+ /**
14186
+ * @description PENDING — awaiting upstream provisioning (re-post create to poll); FAILED — rejected upstream, the program can be re-opened
14187
+ * @enum {string}
14188
+ */
14189
+ status?: "ACTIVE" | "CANCELED" | "FROZEN" | "INACTIVE" | "CLOSED" | "BLOCKED" | "PENDING" | "FAILED";
12971
14190
  /** Format: uuid */
12972
14191
  account_currency?: string;
12973
14192
  /** Format: uuid */
@@ -12976,19 +14195,19 @@ export interface components {
12976
14195
  destination_address?: string | null;
12977
14196
  /** Format: uuid */
12978
14197
  integration_vendor_id?: string;
12979
- vendor_account_id?: string | null;
14198
+ vendor_account_id?: string;
12980
14199
  /** @description Customer name the account is held under */
12981
14200
  customer_name?: string | null;
12982
- /** @description Bank account details for deposits, derived from deposit_instructions. Returned null when deposits are disabled for the account. */
14201
+ /** @description Bank account details for deposits, derived from deposit_instructions. Returned null when deposits are disabled on the program's KYC rail. */
12983
14202
  account_details?: Record<string, never> | null;
12984
- /** @description Deposit requisites (source of truth). Returned null when deposits are disabled for the account. */
12985
- deposit_instructions?: Record<string, never> | null;
14203
+ /** @description Deposit requisites (source of truth). Emptied to [] (never null) when deposits are disabled on the program's KYC rail. */
14204
+ deposit_instructions?: Record<string, never>[];
12986
14205
  meta?: Record<string, never> | null;
12987
- /** @description Account currency details — present on hydrated reads (e.g. embedded in a single-order response) */
14206
+ /** @description Account currency details */
12988
14207
  account_currency_details?: components["schemas"]["CurrencyDetails"] | null;
12989
- /** @description Destination currency details — present on hydrated reads (e.g. embedded in a single-order response) */
14208
+ /** @description Destination currency details */
12990
14209
  destination_currency_details?: components["schemas"]["CurrencyDetails"] | null;
12991
- /** @description Integration vendor details — present on hydrated reads (e.g. embedded in a single-order response) */
14210
+ /** @description Integration vendor details */
12992
14211
  integration_vendor?: {
12993
14212
  /** Format: uuid */
12994
14213
  id?: string;
@@ -12999,21 +14218,6 @@ export interface components {
12999
14218
  /** Format: date-time */
13000
14219
  created_at?: string;
13001
14220
  };
13002
- /** @description Virtual account program configuration */
13003
- VirtualAccountProgram: {
13004
- /** Format: uuid */
13005
- id?: string;
13006
- name?: string;
13007
- description?: string | null;
13008
- /** @enum {string} */
13009
- status?: "ACTIVE" | "INACTIVE";
13010
- icon?: string | null;
13011
- code?: string | null;
13012
- /** Format: uuid */
13013
- account_currency_id?: string;
13014
- /** Format: uuid */
13015
- destination_currency_id?: string;
13016
- };
13017
14221
  /** @description Currency subset joined onto order and virtual-account reads (from the `crypto` table). */
13018
14222
  CurrencyDetails: {
13019
14223
  /** Format: uuid */
@@ -13024,7 +14228,7 @@ export interface components {
13024
14228
  /** @description Number of minor-unit decimals */
13025
14229
  decimal: number;
13026
14230
  };
13027
- /** @description Public order metadata. The stored `meta` JSONB is reduced server-side to a fixed allowlist of public keys — workflow/provider internals never appear. Every field is optional: presence depends on the order type (crypto transfer, fiat off-ramp, exchange, internal transfer, card top-up, deposit). */
14231
+ /** @description Public order metadata. List and single-read responses reduce the stored `meta` JSONB to a fixed allowlist of public keys; create/approve/cancel responses return the stored meta minus scheduler-internal keys. Every field is optional: presence depends on the order type (crypto transfer, fiat off-ramp, exchange, internal transfer, card top-up, deposit). */
13028
14232
  OrderMeta: {
13029
14233
  /** @description Legacy idempotency key — null on orders created by the current flow */
13030
14234
  request_id?: string | null;
@@ -13214,7 +14418,7 @@ export interface components {
13214
14418
  /** @description Destination currency details (resolved from `to_uuid`) */
13215
14419
  to_currency?: components["schemas"]["CurrencyDetails"];
13216
14420
  /** @description Virtual account referenced by the order (fiat off-ramp/on-ramp), hydrated with currency and vendor details. Absent/null when the order has no `meta.virtual_account_id`. */
13217
- virtual_account?: components["schemas"]["VirtualAccount"] | null;
14421
+ virtual_account?: components["schemas"]["OrderVirtualAccount"] | null;
13218
14422
  /** @description Receiver of the order. Present when the order has a `meta.counterparty_destination_id`; absent otherwise. */
13219
14423
  counterparty_destination?: components["schemas"]["OrderCounterpartyDestination"] | null;
13220
14424
  /** @description Documents attached to the order; empty array when none (or when document loading failed). Returned by GET /frontend/orders/id/{order_id} only; absent from the by-uuid read. */
@@ -13341,7 +14545,7 @@ export interface components {
13341
14545
  /** @description Optional supporting documents persisted with the order. */
13342
14546
  documents?: components["schemas"]["OrderDocumentInput"][];
13343
14547
  };
13344
- FrontendL2FOrderRequest: {
14548
+ FrontendFiatWithdrawalRequest: {
13345
14549
  /**
13346
14550
  * Format: uuid
13347
14551
  * @description Source wallet UUID
@@ -13504,12 +14708,108 @@ export interface components {
13504
14708
  /** Format: uuid */
13505
14709
  wallet_id?: string;
13506
14710
  };
13507
- MassPayout: {
14711
+ Invoice: {
13508
14712
  /** Format: uuid */
13509
14713
  id?: string;
13510
14714
  /** Format: uuid */
13511
14715
  wallet_id?: string;
14716
+ /**
14717
+ * Format: uuid
14718
+ * @description Counterparty account the invoice is addressed to
14719
+ */
14720
+ counterparty_account_id?: string | null;
14721
+ /** @description Unique per wallet; user-supplied or generated as <prefix>-<n>, where the prefix is the first two vowels of the tenant name (INV fallback) */
14722
+ invoice_number?: string;
14723
+ /**
14724
+ * @description OVERDUE is derived — a sent or partially paid invoice past its due date
14725
+ * @enum {string}
14726
+ */
14727
+ status?: "DRAFT" | "SENT" | "PARTIALLY_PAID" | "PAID" | "OVERDUE";
14728
+ /** Format: uuid */
14729
+ currency_id?: string;
14730
+ /** @description Gross (net item amounts + tax) */
14731
+ total_amount?: number;
14732
+ /** @description Sum of the linked payments */
14733
+ paid_amount?: number;
14734
+ /** Format: date */
14735
+ due_date?: string | null;
14736
+ /** Format: date-time */
14737
+ sent_at?: string | null;
14738
+ /** @description Recipient snapshot taken when the invoice was sent */
14739
+ recipient_name?: string | null;
14740
+ recipient_email?: string | null;
14741
+ description?: string | null;
14742
+ /** Format: date-time */
14743
+ created_at?: string;
14744
+ /** Format: date-time */
14745
+ updated_at?: string;
14746
+ };
14747
+ InvoiceItem: {
14748
+ /** Format: uuid */
14749
+ id?: string;
14750
+ /** @description Zero-based display order */
14751
+ position?: number;
14752
+ name?: string;
14753
+ description?: string | null;
14754
+ quantity?: number;
14755
+ unit_price?: number;
14756
+ /** @description Sales tax percent; null = no tax */
14757
+ tax_rate?: number | null;
14758
+ /** @description Net line amount (quantity x unit_price, before tax) */
14759
+ amount?: number;
14760
+ /** @description amount x tax_rate / 100; 0 without tax */
14761
+ tax_amount?: number;
14762
+ /** Format: date-time */
14763
+ created_at?: string;
14764
+ };
14765
+ InvoicePayment: {
14766
+ /** Format: uuid */
14767
+ id?: string;
14768
+ /**
14769
+ * Format: uuid
14770
+ * @description Linked incoming order
14771
+ */
14772
+ order_id?: string;
14773
+ /** @description Full credited amount of the linked order */
14774
+ amount?: number;
14775
+ /** Format: date-time */
14776
+ created_at?: string;
14777
+ };
14778
+ InvoiceItemInput: {
14779
+ name: string;
14780
+ description?: string;
14781
+ quantity: number;
14782
+ unit_price: number;
14783
+ /** @description Optional sales tax percent */
14784
+ tax_rate?: number;
14785
+ };
14786
+ MassPayoutDocument: {
14787
+ /**
14788
+ * Format: uri
14789
+ * @description Public http(s) link to the uploaded file (the file itself is uploaded separately)
14790
+ */
14791
+ url: string;
14792
+ /**
14793
+ * @description Kind of the attachment; INVOICE satisfies the invoice rule for large payouts
14794
+ * @enum {string}
14795
+ */
14796
+ type: "INVOICE" | "DOCUMENT";
14797
+ description?: string;
14798
+ };
14799
+ MassPayoutCurrencyTotal: {
14800
+ /** Format: uuid */
14801
+ currency_id?: string;
14802
+ amount?: number;
14803
+ };
14804
+ MassPayout: {
13512
14805
  /** Format: uuid */
14806
+ id?: string;
14807
+ /** Format: uuid */
14808
+ wallet_id?: string;
14809
+ /**
14810
+ * Format: uuid
14811
+ * @description Source currency the batch is funded in
14812
+ */
13513
14813
  currency_id?: string;
13514
14814
  /**
13515
14815
  * Format: uuid
@@ -13517,12 +14817,30 @@ export interface components {
13517
14817
  */
13518
14818
  virtual_account_id?: string | null;
13519
14819
  name?: string;
13520
- /** @enum {string} */
13521
- status?: "DRAFT" | "PENDING_APPROVAL" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
14820
+ /**
14821
+ * @description SCHEDULED = approved with a future send date; execution starts automatically at that moment
14822
+ * @enum {string}
14823
+ */
14824
+ status?: "DRAFT" | "PENDING_APPROVAL" | "SCHEDULED" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
14825
+ /**
14826
+ * Format: date-time
14827
+ * @description Requested execution time; null means the batch executes right after approval
14828
+ */
14829
+ scheduled_at?: string | null;
14830
+ /**
14831
+ * Format: date-time
14832
+ * @description Set when a stop was requested for a running batch; payments not yet started will be cancelled
14833
+ */
14834
+ cancel_requested_at?: string | null;
13522
14835
  total_items?: number;
14836
+ /** @description Sum of payout amounts payable in the batch source currency (cross-currency payouts are listed in totals_by_currency instead) */
13523
14837
  total_amount?: number;
14838
+ /** @description Exact recipient totals per payout currency */
14839
+ totals_by_currency?: components["schemas"]["MassPayoutCurrencyTotal"][];
13524
14840
  completed_count?: number;
13525
14841
  failed_count?: number;
14842
+ /** @description Payments cancelled before being attempted (batch cancelled or stopped) */
14843
+ cancelled_count?: number;
13526
14844
  /**
13527
14845
  * Format: uuid
13528
14846
  * @description User id of the wallet member who approved the batch; null until approved
@@ -13541,9 +14859,21 @@ export interface components {
13541
14859
  id?: string;
13542
14860
  /** Format: uuid */
13543
14861
  destination_id?: string;
14862
+ /** @description The amount the recipient receives, in the item's payout currency */
13544
14863
  amount?: number;
13545
- /** @enum {string} */
13546
- status?: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED";
14864
+ /**
14865
+ * Format: uuid
14866
+ * @description Payout currency of this item; null means the batch source currency
14867
+ */
14868
+ to_currency_id?: string | null;
14869
+ /** @description Payment reference shown on the created order; falls back to the batch name */
14870
+ reference?: string | null;
14871
+ documents?: components["schemas"]["MassPayoutDocument"][];
14872
+ /**
14873
+ * @description CANCELED = never attempted (the batch was cancelled or stopped before this payment)
14874
+ * @enum {string}
14875
+ */
14876
+ status?: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
13547
14877
  /**
13548
14878
  * Format: uuid
13549
14879
  * @description The regular order created for this item at execution
@@ -13562,13 +14892,61 @@ export interface components {
13562
14892
  * @description Existing counterparty destination of the source wallet
13563
14893
  */
13564
14894
  destination_id: string;
14895
+ /** @description The amount the recipient receives, in the payout currency of this row */
14896
+ amount: number;
14897
+ /**
14898
+ * Format: uuid
14899
+ * @description Payout currency of this row; omit for the batch source currency. A differing value makes the payout a cross-currency one (the debit is converted at execution time)
14900
+ */
14901
+ to_currency_id?: string;
14902
+ /** @description Optional payment reference for this row */
14903
+ reference?: string;
14904
+ /** @description Supporting documents; an INVOICE attachment is required for rows at or above the invoice threshold */
14905
+ documents?: components["schemas"]["MassPayoutDocument"][];
14906
+ };
14907
+ MassPayoutTemplateItemInput: {
14908
+ /** Format: uuid */
14909
+ destination_id: string;
13565
14910
  amount: number;
14911
+ /** Format: uuid */
14912
+ to_currency_id?: string;
14913
+ reference?: string;
14914
+ };
14915
+ MassPayoutTemplateItem: {
14916
+ /** Format: uuid */
14917
+ id?: string;
14918
+ /** Format: uuid */
14919
+ destination_id?: string;
14920
+ amount?: number;
14921
+ /** Format: uuid */
14922
+ to_currency_id?: string | null;
14923
+ reference?: string | null;
14924
+ position?: number;
14925
+ };
14926
+ MassPayoutTemplate: {
14927
+ /** Format: uuid */
14928
+ id?: string;
14929
+ /** Format: uuid */
14930
+ wallet_id?: string;
14931
+ name?: string;
14932
+ /** Format: uuid */
14933
+ currency_id?: string;
14934
+ /** Format: uuid */
14935
+ virtual_account_id?: string | null;
14936
+ total_items?: number;
14937
+ /** Format: date-time */
14938
+ created_at?: string;
14939
+ /** Format: date-time */
14940
+ updated_at?: string;
14941
+ };
14942
+ MassPayoutTemplateWithItems: components["schemas"]["MassPayoutTemplate"] & {
14943
+ items?: components["schemas"]["MassPayoutTemplateItem"][];
13566
14944
  };
13567
14945
  NotificationView: {
13568
14946
  /** Format: uuid */
13569
14947
  id: string;
13570
14948
  /** @enum {string} */
13571
- type: "DEPOSIT_RECEIVED" | "TRANSFER_RECEIVED" | "ORDER_STATUS_CHANGED" | "KYC_STATUS_CHANGED";
14949
+ type: "DEPOSIT_RECEIVED" | "TRANSFER_RECEIVED" | "ORDER_STATUS_CHANGED" | "KYC_STATUS_CHANGED" | "ANNOUNCEMENT" | "SYSTEM_MESSAGE";
13572
14950
  /** @description Structured fact snapshot; the client renders the presentation. Shape depends on `type`; evolution is additive-only. */
13573
14951
  payload: Record<string, never>;
13574
14952
  /** Format: uuid */
@@ -13580,12 +14958,12 @@ export interface components {
13580
14958
  };
13581
14959
  NotificationPreference: {
13582
14960
  /** @enum {string} */
13583
- channel: "IN_APP" | "PUSH" | "EMAIL";
14961
+ channel: "IN_APP" | "PUSH" | "EMAIL" | "TELEGRAM";
13584
14962
  enabled: boolean;
13585
14963
  };
13586
14964
  NotificationCategoryPreference: {
13587
14965
  /** @enum {string} */
13588
- category: "TRANSACTIONS" | "COMPLIANCE";
14966
+ category: "TRANSACTIONS" | "COMPLIANCE" | "ANNOUNCEMENTS" | "SYSTEM";
13589
14967
  enabled: boolean;
13590
14968
  };
13591
14969
  };
@@ -13598,9 +14976,9 @@ export interface components {
13598
14976
  content: {
13599
14977
  "application/json": {
13600
14978
  error?: {
13601
- /** @example AUTHENTICATION_REQUIRED */
14979
+ /** @example UNAUTHORIZED */
13602
14980
  code?: string;
13603
- /** @example Please login to continue */
14981
+ /** @example Authorization header is missing */
13604
14982
  message?: string;
13605
14983
  };
13606
14984
  };
@@ -13645,9 +15023,15 @@ export interface components {
13645
15023
  * @example e04c0c85-b031-47d7-8541-207b4e83d91a
13646
15024
  */
13647
15025
  TenantId: string;
15026
+ /** @description Wallet the invoices belong to */
15027
+ InvoiceWalletId: string;
15028
+ InvoiceId: string;
15029
+ /** @description Id of the linked payment (from the invoice details `payments` list) */
15030
+ InvoicePaymentId: string;
13648
15031
  /** @description Source wallet the batches belong to */
13649
15032
  MassPayoutWalletId: string;
13650
15033
  MassPayoutId: string;
15034
+ MassPayoutTemplateId: string;
13651
15035
  };
13652
15036
  requestBodies: never;
13653
15037
  headers: never;