squarefi-bff-api-module 1.36.94 → 1.36.96

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.
@@ -1435,6 +1435,7 @@ export interface paths {
1435
1435
  requestBody: {
1436
1436
  content: {
1437
1437
  "application/json": {
1438
+ /** @description Legal name. Latin characters only (printable ASCII - letters A-Z without diacritics, digits, spaces, punctuation); anything else is refused with `400 VALIDATION_ERROR`. Transliterate other scripts before sending. */
1438
1439
  name: string;
1439
1440
  /** @enum {string} */
1440
1441
  type: "BUSINESS" | "INDIVIDUAL";
@@ -1466,7 +1467,7 @@ export interface paths {
1466
1467
  };
1467
1468
  };
1468
1469
  };
1469
- /** @description Validation error (missing name/type, invalid fields) or wallet not found */
1470
+ /** @description `VALIDATION_ERROR`: missing or invalid `name` / `type`, `name` has characters outside printable ASCII (the message names the field), or wallet not found */
1470
1471
  400: {
1471
1472
  headers: {
1472
1473
  [name: string]: unknown;
@@ -1841,6 +1842,7 @@ export interface paths {
1841
1842
  requestBody: {
1842
1843
  content: {
1843
1844
  "application/json": {
1845
+ /** @description User-friendly alias for this destination. Latin characters only (printable ASCII - letters A-Z without diacritics, digits, spaces, punctuation); anything else is refused with `400 VALIDATION_ERROR`. */
1844
1846
  nickname?: string;
1845
1847
  };
1846
1848
  };
@@ -1861,6 +1863,15 @@ export interface paths {
1861
1863
  };
1862
1864
  };
1863
1865
  };
1866
+ /** @description `VALIDATION_ERROR`: no updatable field, or `nickname` has characters outside printable ASCII */
1867
+ 400: {
1868
+ headers: {
1869
+ [name: string]: unknown;
1870
+ };
1871
+ content: {
1872
+ "application/json": components["schemas"]["ErrorResponse"];
1873
+ };
1874
+ };
1864
1875
  /** @description Access denied, or (Clerk tenants) the second-factor verification is
1865
1876
  * stale — `TWO_FACTOR_REVERIFICATION_REQUIRED`: re-verify and retry.
1866
1877
  * */
@@ -1972,7 +1983,7 @@ export interface paths {
1972
1983
  * Create destination
1973
1984
  * @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.
1974
1985
  *
1975
- * **Banking types**: banking_data required. `banking_data.address` (the bank address) is mandatory; `banking_data.beneficiary_address` (the recipient's own postal address, same shape) is optional — when present it must be complete (city, country_id, postcode, street1; state_id on US rails), is never overwritten by bank-directory enrichment, is exempt from the bank-country check, and payouts use it in place of the bank address.
1986
+ * **Banking types**: banking_data required. `banking_data.address` (the bank address) is mandatory; `banking_data.beneficiary_address` (the recipient's own postal address, same shape) is optional — when present it must be complete (city, country_id, postcode, street1; state_id on US rails), is never overwritten by bank-directory enrichment, is exempt from the bank-country check, and payouts use it in place of the bank address. `banking_data.intermediary_bic` (optional) is the BIC of the intermediary (correspondent) bank, accepted on SWIFT only.
1976
1987
  * **Crypto types**: crypto_data required
1977
1988
  * **Internal type**: internal_data required (target wallet on the same platform)
1978
1989
  *
@@ -1991,6 +2002,7 @@ export interface paths {
1991
2002
  counterparty_account_id: string;
1992
2003
  /** @enum {string} */
1993
2004
  type: "ACH" | "RTP" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "INTERNAL";
2005
+ /** @description User-friendly alias for this destination. Latin characters only (printable ASCII - letters A-Z without diacritics, digits, spaces, punctuation); anything else is refused with `400 VALIDATION_ERROR`. */
1994
2006
  nickname?: string;
1995
2007
  banking_data?: Record<string, never>;
1996
2008
  crypto_data?: Record<string, never>;
@@ -2025,7 +2037,7 @@ export interface paths {
2025
2037
  };
2026
2038
  };
2027
2039
  };
2028
- /** @description Validation error: type-specific payload missing or invalid, target wallet inactive, or the address country contradicts the bank code country (`BANK_COUNTRY_MISMATCH`).
2040
+ /** @description Validation error: type-specific payload missing or invalid, `nickname` has characters outside printable ASCII (`VALIDATION_ERROR`, the message names the field), target wallet inactive, or the address country contradicts the bank code country (`BANK_COUNTRY_MISMATCH`).
2029
2041
  *
2030
2042
  * Bank details are checked per payment method — IBAN (country, length, account format, check digits), SWIFT/BIC, ABA routing number, US/UK account number, sort code, IBAN inside the SEPA zone on SEPA. Every problem is listed in `error.details.issues` (`field`, `code`, `message`, optional `country` / `detected`), so a form can mark each field; `POST /frontend/counterparty/destinations/validate` returns the same list without saving.
2031
2043
  * */
@@ -3326,80 +3338,93 @@ export interface paths {
3326
3338
  };
3327
3339
  };
3328
3340
  };
3329
- /** @description Bad Request - One of the following:
3330
- * - Missing program_id
3331
- * - Missing required fields based on program type
3332
- * - Unsupported program type
3333
- * - `INITIAL_TOPUP_BELOW_OPENING_LOAD` — `initial_topup` less the issuing fee is below the
3334
- * program's mandatory opening balance; the message names the total accepted at the current rate
3335
- * - `OPENING_LOAD_NOT_PAID` — the program's cards open holding a mandatory balance and
3336
- * this issuance charges nothing for it (issuance not billed here, or no issuance tariff
3337
- * for the wallet on the program), or the card spends from a sub-account, whose top-up
3338
- * funds the sub-account rather than the card
3341
+ /** @description The card was refused; `error.code` says why (`CardIssuanceRefusalCode`, one line per code
3342
+ * there). **Nothing is debited from the wallet on a `400`**: either nothing was charged, or the
3343
+ * issuer refused the card after the charge and the charge was returned before this answer.
3344
+ *
3345
+ * A shortage on the top-up after the card is created is not a `400`: the card is issued and
3346
+ * `201` reports `initial_topup_status: topup_failed`.
3339
3347
  * */
3340
3348
  400: {
3341
3349
  headers: {
3342
3350
  [name: string]: unknown;
3343
3351
  };
3344
3352
  content: {
3345
- "application/json": {
3346
- /** @example false */
3347
- success?: boolean;
3348
- error?: string;
3349
- };
3353
+ "application/json": components["schemas"]["CardIssuanceRefusalResponse"];
3350
3354
  };
3351
3355
  };
3352
- /** @description Forbidden - One of the following:
3353
- * - Sub-account not found
3354
- * - Wallet not found or access denied
3355
- * - Program not available for this tenant
3356
- * - Program vendor ID is not configured
3356
+ /** @description `UNAUTHORIZED` — missing or invalid Bearer token, `x-tenant-id` or session */
3357
+ 401: {
3358
+ headers: {
3359
+ [name: string]: unknown;
3360
+ };
3361
+ content: {
3362
+ "application/json": components["schemas"]["ErrorResponse"];
3363
+ };
3364
+ };
3365
+ /** @description Not allowed. `error.code`:
3366
+ * - `ACCESS_DENIED` — not a member of the wallet, or the role is below admin
3367
+ * - `FORBIDDEN` — wallet, sub-account or program not available here, no right to issue cards on the wallet, program not open to the user's group, program vendor not configured
3368
+ * - `LIMIT_EXCEEDED` — the maximum, daily or monthly card limit is reached
3369
+ * - `KYC_REQUIREMENTS_NOT_MET` — the wallet's KYC is not approved
3370
+ * - `RAIL_NOT_CONFIGURED`, `RAIL_NOT_ENABLED`, `WALLET_RAIL_NOT_ONBOARDED`, `WALLET_RAIL_NOT_APPROVED` — the card rail is not open to the wallet
3371
+ * - `USER_NOT_REGISTERED`, `ACCOUNT_BLOCKED` — the user is not registered in the workspace or is blocked
3357
3372
  * */
3358
3373
  403: {
3359
3374
  headers: {
3360
3375
  [name: string]: unknown;
3361
3376
  };
3362
3377
  content: {
3363
- "application/json": {
3364
- /** @example false */
3365
- success?: boolean;
3366
- error?: string;
3367
- };
3378
+ "application/json": components["schemas"]["ErrorResponse"];
3368
3379
  };
3369
3380
  };
3370
- /** @description Program not found */
3381
+ /** @description `NOT_FOUND` — program, sub-account, cardholder or workspace not found */
3371
3382
  404: {
3372
3383
  headers: {
3373
3384
  [name: string]: unknown;
3374
3385
  };
3375
3386
  content: {
3376
- "application/json": {
3377
- /** @example false */
3378
- success?: boolean;
3379
- /** @example Program not found */
3380
- error?: string;
3381
- };
3387
+ "application/json": components["schemas"]["ErrorResponse"];
3382
3388
  };
3383
3389
  };
3384
- /** @description `request_id` was already used by another card request (replay refused) */
3390
+ /** @description `error.code`:
3391
+ * - `CONFLICT` — `request_id` was already used by another card request
3392
+ * - `WALLET_DORMANT` — the wallet is dormant; only support reactivates it
3393
+ * - `REPLAY_CONFLICT` — the same charge was already posted with different content
3394
+ * */
3385
3395
  409: {
3386
3396
  headers: {
3387
3397
  [name: string]: unknown;
3388
3398
  };
3389
- content?: never;
3399
+ content: {
3400
+ "application/json": components["schemas"]["ErrorResponse"];
3401
+ };
3390
3402
  };
3391
- /** @description Internal Server Error */
3403
+ /** @description `CARDHOLDER_REFUSED` — the card issuer refused the cardholder; anything charged was returned */
3404
+ 422: {
3405
+ headers: {
3406
+ [name: string]: unknown;
3407
+ };
3408
+ content: {
3409
+ "application/json": components["schemas"]["ErrorResponse"];
3410
+ };
3411
+ };
3412
+ /** @description `RATE_LIMIT_EXCEEDED` — too many requests */
3413
+ 429: {
3414
+ headers: {
3415
+ [name: string]: unknown;
3416
+ };
3417
+ content: {
3418
+ "application/json": components["schemas"]["ErrorResponse"];
3419
+ };
3420
+ };
3421
+ /** @description `INTERNAL_ERROR` — the card could not be created */
3392
3422
  500: {
3393
3423
  headers: {
3394
3424
  [name: string]: unknown;
3395
3425
  };
3396
3426
  content: {
3397
- "application/json": {
3398
- /** @example false */
3399
- success?: boolean;
3400
- /** @example Failed to create card */
3401
- error?: string;
3402
- };
3427
+ "application/json": components["schemas"]["ErrorResponse"];
3403
3428
  };
3404
3429
  };
3405
3430
  };
@@ -5680,7 +5705,7 @@ export interface paths {
5680
5705
  };
5681
5706
  };
5682
5707
  };
5683
- /** @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.
5708
+ /** @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. On a tenant of the KYC forms flow the member's personal KYC entity is the dossier and the program's card form the gate (`GET /frontend/kyc/entities/{entity_id}/forms?programs=&wallet_id=`): `CARD_REQUIREMENTS_INCOMPLETE` with `details.fields` (the catalog keys still empty), `CARD_VERIFICATION_REQUIRED` (the level needs the verified document and face), `CARD_KYC_REFUSED` (the member's application, or their identity check, was refused for good), `KYC_PERSONAL_ENTITY_MISSING` (the member has no personal entity yet).
5684
5709
  * */
5685
5710
  400: {
5686
5711
  headers: {
@@ -5695,14 +5720,14 @@ export interface paths {
5695
5720
  };
5696
5721
  content?: never;
5697
5722
  };
5698
- /** @description `user_data_id` does not resolve to a user */
5723
+ /** @description `user_data_id` does not resolve to a user, or `issuing_program_id` names no program */
5699
5724
  404: {
5700
5725
  headers: {
5701
5726
  [name: string]: unknown;
5702
5727
  };
5703
5728
  content?: never;
5704
5729
  };
5705
- /** @description A cardholder already exists for this person in this wallet + issuing_program — the member named by `user_data_id` already holds one, or one carries this email. `error.details.cardholder_id` names it (when it could be resolved) so the client can adopt it instead of dead-ending. When `user_data_id` names a member who may adopt the row, the row is first completed from that member's KYC dossier: empty identity fields and document photos of a type it does not hold are filled in, and nothing already on it is changed. Re-read the row for its refreshed `missing_kyc_fields`.
5730
+ /** @description On a tenant of the KYC forms flow, `KYC_INDIVIDUAL_AMBIGUOUS` when the member has several personal KYC entities (compliance untangles them), or `CARD_REQUIREMENTS_PENDING_REVIEW` with `details.fields` when the card form's required fields are answered but wait in a submission compliance has not decided. Otherwise `DUPLICATE_CARDHOLDER`: a cardholder already exists for this person in this wallet + issuing_program — the member named by `user_data_id` already holds one, or one carries this email. `error.details.cardholder_id` names it (when it could be resolved) so the client can adopt it instead of dead-ending. When `user_data_id` names a member who may adopt the row, the row is first completed from that member's KYC dossier: empty identity fields and document photos of a type it does not hold are filled in, and nothing already on it is changed. Re-read the row for its refreshed `missing_kyc_fields`.
5706
5731
  * */
5707
5732
  409: {
5708
5733
  headers: {
@@ -6036,12 +6061,23 @@ export interface paths {
6036
6061
  * app is not possible (support resets it), so never render a "verify now" action.
6037
6062
  * - `NOT_MEMBER` — the uuid is not an active member of this wallet.
6038
6063
  *
6064
+ * **On a tenant of the KYC forms flow** (SFI-2544) the verdict comes from the member's personal
6065
+ * KYC entity and the program's card form, not from the profile statuses: `CAN_CREATE` with
6066
+ * `will_require` = the required fields of the card form still empty in the entity (catalog
6067
+ * keys such as `first_name`, `email`, `phone`), `NEEDS_VERIFICATION` while the level needs the
6068
+ * identity check and it has not passed, `REJECTED` for an application refused for good,
6069
+ * `PENDING` while compliance untangles several personal entities of the member or while every
6070
+ * required field is answered but some wait in a submission under review. A member without a
6071
+ * personal entity is `CAN_CREATE` with every required field of the form in `will_require`.
6072
+ *
6039
6073
  * **`will_require`**: fields the client should expect to collect BY HAND (same vocabulary
6040
6074
  * as the submit 400 `missing` list, e.g. `address.line1`, `tax_identification_number`,
6041
6075
  * `email or phone`). For `DRAFT` it is the draft's actual leftovers; for `NEEDS_COMPLETION`
6042
6076
  * it is what the card create refuses the row over; for `CAN_CREATE` it
6043
6077
  * is a projection that assumes the KYC dossier covers what it usually covers — the created
6044
- * draft's `missing_kyc_fields` is the authoritative version.
6078
+ * draft's `missing_kyc_fields` is the authoritative version. The dossier never carries
6079
+ * contacts, so a `CAN_CREATE` member without a valid `email` or `phone` on their profile
6080
+ * always gets that field listed: send it in the create body.
6045
6081
  *
6046
6082
  * **Authentication**: Bearer token with x-tenant-id header; wallet ADMIN role required.
6047
6083
  *
@@ -6561,6 +6597,10 @@ export interface paths {
6561
6597
  * the Auth API; access requires the caller to be a member of the wallet
6562
6598
  * (ownership/membership is enforced by the standard wallet-access check).
6563
6599
  *
6600
+ * **KYC forms flow**: on a tenant switched to the KYC forms (SFI-2544) this route is closed and
6601
+ * answers `400 KYC_LEGACY_FLOW_DISABLED` before anything else is checked — the client uses
6602
+ * `/frontend/kyc/entities*` instead.
6603
+ *
6564
6604
  * **Authentication**: Bearer token with x-tenant-id header required
6565
6605
  *
6566
6606
  * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
@@ -6616,7 +6656,7 @@ export interface paths {
6616
6656
  };
6617
6657
  };
6618
6658
  };
6619
- /** @description Validation error (`type` missing or not in [individual, business]) */
6659
+ /** @description `VALIDATION_ERROR` — `type` missing or not in [individual, business]; `KYC_LEGACY_FLOW_DISABLED` — the tenant runs the KYC forms flow, this route is closed */
6620
6660
  400: {
6621
6661
  headers: {
6622
6662
  [name: string]: unknown;
@@ -6686,6 +6726,10 @@ export interface paths {
6686
6726
  * forwarded to the Auth API; access requires the caller to be a member of
6687
6727
  * the wallet (ownership/membership is enforced by the standard wallet-access check).
6688
6728
  *
6729
+ * **KYC forms flow**: on a tenant switched to the KYC forms (SFI-2544) this route is closed and
6730
+ * answers `400 KYC_LEGACY_FLOW_DISABLED` before anything else is checked — the client uses
6731
+ * `/frontend/kyc/entities*` instead.
6732
+ *
6689
6733
  * **Authentication**: Bearer token with x-tenant-id header required
6690
6734
  *
6691
6735
  * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
@@ -6741,7 +6785,7 @@ export interface paths {
6741
6785
  };
6742
6786
  };
6743
6787
  };
6744
- /** @description Validation error (`inquiry_id` missing or empty) */
6788
+ /** @description `VALIDATION_ERROR` — `inquiry_id` missing or empty; `KYC_LEGACY_FLOW_DISABLED` — the tenant runs the KYC forms flow, this route is closed */
6745
6789
  400: {
6746
6790
  headers: {
6747
6791
  [name: string]: unknown;
@@ -6817,6 +6861,10 @@ export interface paths {
6817
6861
  * Provider-agnostic replacement for the deprecated
6818
6862
  * `GET /frontend/kyc_persona/{wallet_id}/init`.
6819
6863
  *
6864
+ * **KYC forms flow**: on a tenant switched to the KYC forms (SFI-2544) this route is closed and
6865
+ * answers `400 KYC_LEGACY_FLOW_DISABLED` before anything else is checked — the client uses
6866
+ * `/frontend/kyc/entities*` instead.
6867
+ *
6820
6868
  * **Authentication**: Bearer token with x-tenant-id header required
6821
6869
  *
6822
6870
  * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
@@ -6869,7 +6917,7 @@ export interface paths {
6869
6917
  };
6870
6918
  };
6871
6919
  };
6872
- /** @description Validation error (`type` missing or not in [individual, business]) */
6920
+ /** @description `VALIDATION_ERROR` — `type` missing or not in [individual, business]; `KYC_LEGACY_FLOW_DISABLED` — the tenant runs the KYC forms flow, this route is closed */
6873
6921
  400: {
6874
6922
  headers: {
6875
6923
  [name: string]: unknown;
@@ -6943,6 +6991,10 @@ export interface paths {
6943
6991
  * Provider-agnostic replacement for the deprecated
6944
6992
  * `GET /frontend/kyc_persona/{wallet_id}/resume`.
6945
6993
  *
6994
+ * **KYC forms flow**: on a tenant switched to the KYC forms (SFI-2544) this route is closed and
6995
+ * answers `400 KYC_LEGACY_FLOW_DISABLED` before anything else is checked — the client uses
6996
+ * `/frontend/kyc/entities*` instead.
6997
+ *
6946
6998
  * **Authentication**: Bearer token with x-tenant-id header required
6947
6999
  *
6948
7000
  * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
@@ -6994,7 +7046,7 @@ export interface paths {
6994
7046
  };
6995
7047
  };
6996
7048
  };
6997
- /** @description Validation error (`verification_ref` missing or empty) */
7049
+ /** @description `VALIDATION_ERROR` — `verification_ref` missing or empty; `KYC_LEGACY_FLOW_DISABLED` — the tenant runs the KYC forms flow, this route is closed */
6998
7050
  400: {
6999
7051
  headers: {
7000
7052
  [name: string]: unknown;
@@ -8127,14 +8179,23 @@ export interface paths {
8127
8179
  path?: never;
8128
8180
  cookie?: never;
8129
8181
  };
8130
- /** List the notification inbox (newest first, cursor pagination) */
8182
+ /**
8183
+ * List the notification inbox (newest first, cursor pagination)
8184
+ * @description The caller's own notifications of the current tenant, newest first.
8185
+ * `wallet_id` narrows the list to one wallet (it filters the caller's own
8186
+ * items; it is not a wallet access check). **Authentication**: Bearer token + x-tenant-id header.
8187
+ *
8188
+ */
8131
8189
  get: {
8132
8190
  parameters: {
8133
8191
  query?: {
8134
8192
  /** @description Opaque cursor from a previous page (`next_cursor`). Omit for the first page. */
8135
8193
  cursor?: string;
8194
+ /** @description Page size. */
8136
8195
  limit?: number;
8196
+ /** @description `true` — only unread items; `false` or omitted — all. */
8137
8197
  unread_only?: "true" | "false";
8198
+ /** @description Only notifications scoped to this wallet. */
8138
8199
  wallet_id?: string;
8139
8200
  };
8140
8201
  header?: never;
@@ -8153,8 +8214,8 @@ export interface paths {
8153
8214
  /** @example true */
8154
8215
  success?: boolean;
8155
8216
  data?: {
8156
- items?: components["schemas"]["NotificationView"][];
8157
- next_cursor?: string | null;
8217
+ items: components["schemas"]["NotificationView"][];
8218
+ next_cursor: string | null;
8158
8219
  };
8159
8220
  };
8160
8221
  };
@@ -8164,7 +8225,9 @@ export interface paths {
8164
8225
  headers: {
8165
8226
  [name: string]: unknown;
8166
8227
  };
8167
- content?: never;
8228
+ content: {
8229
+ "application/json": components["schemas"]["ErrorResponse"];
8230
+ };
8168
8231
  };
8169
8232
  401: components["responses"]["UnauthorizedError"];
8170
8233
  };
@@ -8184,7 +8247,11 @@ export interface paths {
8184
8247
  path?: never;
8185
8248
  cookie?: never;
8186
8249
  };
8187
- /** Unread notifications count (badge) */
8250
+ /**
8251
+ * Unread notifications count (badge)
8252
+ * @description Number of the caller's unread notifications in the current tenant, across all wallets. **Authentication**: Bearer token + x-tenant-id header.
8253
+ *
8254
+ */
8188
8255
  get: {
8189
8256
  parameters: {
8190
8257
  query?: never;
@@ -8232,7 +8299,8 @@ export interface paths {
8232
8299
  put?: never;
8233
8300
  /**
8234
8301
  * Mark specific notifications as read
8235
- * @description Idempotent — already-read ids are not counted. Other tabs/devices sync via the realtime `notifications.read` event.
8302
+ * @description Idempotent — already-read ids are not counted; ids of other users' notifications or unknown ids are silently ignored (not an error). Other tabs/devices sync via the realtime `notifications.read` event, which carries only the ids actually transitioned. **Authentication**: Bearer token + x-tenant-id header.
8303
+ *
8236
8304
  */
8237
8305
  post: {
8238
8306
  parameters: {
@@ -8244,6 +8312,7 @@ export interface paths {
8244
8312
  requestBody: {
8245
8313
  content: {
8246
8314
  "application/json": {
8315
+ /** @description Ids of the notifications to mark as read. */
8247
8316
  notification_ids: string[];
8248
8317
  };
8249
8318
  };
@@ -8265,12 +8334,14 @@ export interface paths {
8265
8334
  };
8266
8335
  };
8267
8336
  };
8268
- /** @description Invalid body (`VALIDATION_ERROR`). */
8337
+ /** @description Invalid body (`VALIDATION_ERROR`) — missing, empty or over 100 `notification_ids`, or a non-uuid id. */
8269
8338
  400: {
8270
8339
  headers: {
8271
8340
  [name: string]: unknown;
8272
8341
  };
8273
- content?: never;
8342
+ content: {
8343
+ "application/json": components["schemas"]["ErrorResponse"];
8344
+ };
8274
8345
  };
8275
8346
  401: components["responses"]["UnauthorizedError"];
8276
8347
  };
@@ -8290,7 +8361,11 @@ export interface paths {
8290
8361
  };
8291
8362
  get?: never;
8292
8363
  put?: never;
8293
- /** Mark every unread notification as read */
8364
+ /**
8365
+ * Mark every unread notification as read
8366
+ * @description Idempotent. Marks all the caller's unread notifications of the current tenant as read; the realtime `notifications.read` event (`all: true`) syncs other tabs/devices only when something changed. **Authentication**: Bearer token + x-tenant-id header.
8367
+ *
8368
+ */
8294
8369
  post: {
8295
8370
  parameters: {
8296
8371
  query?: never;
@@ -8338,14 +8413,15 @@ export interface paths {
8338
8413
  * Issue a realtime subscription token
8339
8414
  * @description Token for the realtime SDK (`authCallback`). `channels` lists the exact
8340
8415
  * channel names the token grants — the personal channel plus one per
8341
- * accessible wallet. Every channel is subscribe-only; the personal channel
8416
+ * wallet the user is an active `owner`, `admin` or `auditor` of (the
8417
+ * scoped `user` role gets no wallet channel). Every channel is subscribe-only; the personal channel
8342
8418
  * additionally grants `push-subscribe`, so a mobile client can activate
8343
8419
  * the device for push and subscribe it to that channel (the one native
8344
8420
  * pushes are published on) without any server-side registration step.
8345
8421
  * The token's `clientId` is the user's id — subscribe by client
8346
8422
  * (`subscribeClient`) to cover every device of the user at once, and
8347
8423
  * deactivate push on logout. Tokens expire after ~1 hour; the SDK
8348
- * re-requests through the same endpoint.
8424
+ * re-requests through the same endpoint. **Authentication**: Bearer token + x-tenant-id header.
8349
8425
  *
8350
8426
  */
8351
8427
  post: {
@@ -8367,21 +8443,28 @@ export interface paths {
8367
8443
  /** @example true */
8368
8444
  success?: boolean;
8369
8445
  data?: {
8370
- token?: string;
8371
- /** Format: date-time */
8372
- expires_at?: string;
8373
- channels?: string[];
8446
+ /** @description Subscription token for the realtime SDK. */
8447
+ token: string;
8448
+ /**
8449
+ * Format: date-time
8450
+ * @description Token expiry (~1 hour after issue).
8451
+ */
8452
+ expires_at: string;
8453
+ /** @description Exact channel names the token grants — the personal channel first, then one per accessible wallet. */
8454
+ channels: string[];
8374
8455
  };
8375
8456
  };
8376
8457
  };
8377
8458
  };
8378
8459
  401: components["responses"]["UnauthorizedError"];
8379
- /** @description Realtime delivery is disabled for this deployment (`REALTIME_DISABLED`). */
8460
+ /** @description Realtime delivery is disabled for this deployment (`REALTIME_DISABLED`); retryable, not a client error. */
8380
8461
  503: {
8381
8462
  headers: {
8382
8463
  [name: string]: unknown;
8383
8464
  };
8384
- content?: never;
8465
+ content: {
8466
+ "application/json": components["schemas"]["ErrorResponse"];
8467
+ };
8385
8468
  };
8386
8469
  };
8387
8470
  };
@@ -12050,6 +12133,10 @@ export interface paths {
12050
12133
  * User-scoped: no wallet is involved, unlike
12051
12134
  * `/frontend/kyc_verification/{wallet_id}/init`.
12052
12135
  *
12136
+ * **KYC forms flow**: on a tenant switched to the KYC forms (SFI-2544) this route is closed and
12137
+ * answers `400 KYC_LEGACY_FLOW_DISABLED` before anything else is checked — the client uses
12138
+ * `/frontend/kyc/entities*` instead.
12139
+ *
12053
12140
  * **Authentication**: Bearer token with x-tenant-id header required
12054
12141
  *
12055
12142
  */
@@ -12095,7 +12182,7 @@ export interface paths {
12095
12182
  };
12096
12183
  };
12097
12184
  };
12098
- /** @description Validation error (`flow` missing or not in [data, documents, face]) */
12185
+ /** @description `VALIDATION_ERROR` — `flow` missing or not in [data, documents, face]; `KYC_LEGACY_FLOW_DISABLED` — the tenant runs the KYC forms flow, this route is closed */
12099
12186
  400: {
12100
12187
  headers: {
12101
12188
  [name: string]: unknown;
@@ -12163,6 +12250,10 @@ export interface paths {
12163
12250
  * is already on, for the SDK's token-expiry callback. The caller's
12164
12251
  * Bearer token is forwarded to the Auth API.
12165
12252
  *
12253
+ * **KYC forms flow**: on a tenant switched to the KYC forms (SFI-2544) this route is closed and
12254
+ * answers `400 KYC_LEGACY_FLOW_DISABLED` before anything else is checked — the client uses
12255
+ * `/frontend/kyc/entities*` instead.
12256
+ *
12166
12257
  * **Authentication**: Bearer token with x-tenant-id header required
12167
12258
  *
12168
12259
  */
@@ -12195,6 +12286,15 @@ export interface paths {
12195
12286
  };
12196
12287
  };
12197
12288
  };
12289
+ /** @description `KYC_LEGACY_FLOW_DISABLED` — the tenant runs the KYC forms flow, this route is closed */
12290
+ 400: {
12291
+ headers: {
12292
+ [name: string]: unknown;
12293
+ };
12294
+ content: {
12295
+ "application/json": components["schemas"]["ErrorResponse"];
12296
+ };
12297
+ };
12198
12298
  /** @description Missing or invalid Bearer token */
12199
12299
  401: {
12200
12300
  headers: {
@@ -12858,8 +12958,9 @@ export interface paths {
12858
12958
  * `is_main` wallet, else the oldest one.
12859
12959
  *
12860
12960
  * The selection cannot outlive the access it rides on: the flag sits on
12861
- * the membership row, so revoking membership drops it. A deleted wallet
12862
- * or a deactivated membership falls back to the default.
12961
+ * the membership row, so revoking membership drops it. A deleted wallet,
12962
+ * a deactivated membership or a wallet whose owner deleted their account
12963
+ * falls back to the default.
12863
12964
  *
12864
12965
  * **Authentication**: Bearer token with x-tenant-id header required
12865
12966
  *
@@ -12901,7 +13002,9 @@ export interface paths {
12901
13002
  * The choice is per user, not per wallet: selecting a wallet shared with
12902
13003
  * the caller changes nothing for its owner or for the other members.
12903
13004
  * Any wallet the caller is an **active member** of may be selected —
12904
- * ownership is not required.
13005
+ * ownership is not required. A wallet whose owner has deleted their
13006
+ * account cannot be selected: the request answers `403`, the same as
13007
+ * every other endpoint of that wallet.
12905
13008
  *
12906
13009
  * **Authentication**: Bearer token with x-tenant-id header required
12907
13010
  *
@@ -12940,16 +13043,46 @@ export interface paths {
12940
13043
  };
12941
13044
  };
12942
13045
  };
12943
- /** @description wallet_id missing or blank */
13046
+ /** @description `wallet_id` is missing, blank or not a string —
13047
+ * `{ success: false, error: { code: 'VALIDATION_ERROR', message: 'wallet_id must be a non-empty string' } }`.
13048
+ * */
12944
13049
  400: {
12945
13050
  headers: {
12946
13051
  [name: string]: unknown;
12947
13052
  };
12948
- content?: never;
13053
+ content: {
13054
+ "application/json": components["schemas"]["ErrorResponse"];
13055
+ };
12949
13056
  };
12950
13057
  401: components["responses"]["UnauthorizedError"];
12951
- 403: components["responses"]["ForbiddenError"];
12952
- 404: components["responses"]["NotFoundError"];
13058
+ /** @description `ACCESS_DENIED` (`You do not have access to this wallet`) — the caller is not an active
13059
+ * member of the wallet, or the wallet is closed because its owner deleted their account.
13060
+ * The answer is the same in both cases and does not reveal why. The stored selection is not changed.
13061
+ * */
13062
+ 403: {
13063
+ headers: {
13064
+ [name: string]: unknown;
13065
+ };
13066
+ content: {
13067
+ /** @example {
13068
+ * "success": false,
13069
+ * "error": {
13070
+ * "code": "ACCESS_DENIED",
13071
+ * "message": "You do not have access to this wallet"
13072
+ * }
13073
+ * } */
13074
+ "application/json": components["schemas"]["ErrorResponse"];
13075
+ };
13076
+ };
13077
+ /** @description `NOT_FOUND` — the caller is a member, but the wallet itself is deleted. */
13078
+ 404: {
13079
+ headers: {
13080
+ [name: string]: unknown;
13081
+ };
13082
+ content: {
13083
+ "application/json": components["schemas"]["ErrorResponse"];
13084
+ };
13085
+ };
12953
13086
  };
12954
13087
  };
12955
13088
  post?: never;
@@ -13243,15 +13376,17 @@ export interface paths {
13243
13376
  * Wallets where the caller holds the scoped `user` role are returned as a reduced shell
13244
13377
  * (`uuid`, `name`, `display_name`, `tenant_id`, `kyc_entity_id`, `kyc_info`, `created_at` + the role fields) — no `logo_url`.
13245
13378
  *
13379
+ * A wallet whose owner has deleted their account is closed for every member and is not listed.
13380
+ *
13246
13381
  * **Authentication**: Bearer token with x-tenant-id header required
13247
13382
  *
13248
13383
  */
13249
13384
  get: {
13250
13385
  parameters: {
13251
13386
  query?: {
13252
- /** @description Number of items to skip */
13387
+ /** @description Number of items to skip (negative values are raised to 0) */
13253
13388
  offset?: number;
13254
- /** @description Number of items to return */
13389
+ /** @description Number of items to return (values above 100 are lowered to 100, below 1 raised to 1) */
13255
13390
  limit?: number;
13256
13391
  /** @description Filter wallets by user's access role */
13257
13392
  role?: "owner" | "admin" | "user" | "auditor";
@@ -13309,9 +13444,10 @@ export interface paths {
13309
13444
  is_owner: boolean;
13310
13445
  /**
13311
13446
  * Format: uuid
13312
- * @description KYC entity the wallet was opened for (`GET /kyc/entities`) — group the
13313
- * list by it to see which accounts an entity already has. `null` for a
13314
- * wallet created without one.
13447
+ * @description KYC entity the wallet was opened for (`GET /frontend/kyc/entities` on a
13448
+ * tenant of the KYC forms flow, the BFF `GET /kyc/entities` on the old flow) —
13449
+ * group the list by it to see which accounts an entity already has. `null`
13450
+ * for a wallet created without one.
13315
13451
  *
13316
13452
  */
13317
13453
  kyc_entity_id: string | null;
@@ -13329,6 +13465,17 @@ export interface paths {
13329
13465
  };
13330
13466
  };
13331
13467
  };
13468
+ /** @description `VALIDATION_ERROR` — `offset` or `limit` is not an integer, `sort_by` is not one of
13469
+ * `created_at`, `name`, or `sort_order` is not `ASC`/`DESC`.
13470
+ * */
13471
+ 400: {
13472
+ headers: {
13473
+ [name: string]: unknown;
13474
+ };
13475
+ content: {
13476
+ "application/json": components["schemas"]["ErrorResponse"];
13477
+ };
13478
+ };
13332
13479
  /** @description Missing or invalid bearer token */
13333
13480
  401: {
13334
13481
  headers: {
@@ -13389,8 +13536,9 @@ export interface paths {
13389
13536
  /**
13390
13537
  * Format: uuid
13391
13538
  * @description Optional KYC entity to link (entity-first KYC model). Must be
13392
- * an entity of the current user (`GET /kyc/entities`); its type
13393
- * must be enabled for the tenant. The link is set once at
13539
+ * an entity of the current user (`GET /frontend/kyc/entities` on a
13540
+ * tenant of the KYC forms flow, the BFF `GET /kyc/entities` on the
13541
+ * old flow); its type must be enabled for the tenant. The link is set once at
13394
13542
  * creation and is immutable. Omitted → wallet is created
13395
13543
  * without a linked entity (legacy behaviour).
13396
13544
  *
@@ -14848,7 +14996,7 @@ export interface paths {
14848
14996
  *
14849
14997
  * @enum {string}
14850
14998
  */
14851
- identity_verification_status?: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW";
14999
+ identity_verification_status?: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW" | "EXPIRED" | "OFFBOARDED";
14852
15000
  /** @description The member deleted their account. They keep their row and role in the
14853
15001
  * team, but have no access and receive no notifications.
14854
15002
  * */
@@ -15626,7 +15774,10 @@ export interface paths {
15626
15774
  * KYC rails of the wallet
15627
15775
  * @description The tenant's KYC rails of the wallet's entity type and the universal ones, each with the wallet's
15628
15776
  * application on it. A rail is listed while it is active; an archived rail stays listed only when the
15629
- * wallet is approved on it. `can_submit` tells whether `POST …/kyc-rails/{rail_id}` would be accepted now.
15777
+ * wallet is approved on it. `can_submit` tells whether the rail would take the wallet now; it does not look at
15778
+ * the rail's form — on the KYC forms flow that is `form_state` / `missing_required` of the rail in
15779
+ * `GET /frontend/kyc/entities/{entity_id}/targets`. Offer `POST …/kyc-rails/{rail_id}` when `can_submit` is `true`
15780
+ * and the rail's form is `complete`: a form not complete answers `400 RAIL_REQUIREMENTS_INCOMPLETE`.
15630
15781
  *
15631
15782
  * Replaces the BFF `GET /kyc/{wallet_id}/rails`; items have its shape plus `can_submit`, without the
15632
15783
  * rail's `code` and `name` — match a rail to a program by `id` (`kyc_rails_id`).
@@ -15661,12 +15812,14 @@ export interface paths {
15661
15812
  };
15662
15813
  401: components["responses"]["UnauthorizedError"];
15663
15814
  403: components["responses"]["ForbiddenError"];
15664
- /** @description Wallet not found (NOT_FOUND) */
15815
+ /** @description `NOT_FOUND` — wallet not found */
15665
15816
  404: {
15666
15817
  headers: {
15667
15818
  [name: string]: unknown;
15668
15819
  };
15669
- content?: never;
15820
+ content: {
15821
+ "application/json": components["schemas"]["ErrorResponse"];
15822
+ };
15670
15823
  };
15671
15824
  };
15672
15825
  };
@@ -15716,22 +15869,10 @@ export interface paths {
15716
15869
  "application/json": components["schemas"]["WalletKycRailResponse"];
15717
15870
  };
15718
15871
  };
15719
- /** @description `rail_id` is not a UUID (VALIDATION_ERROR) */
15720
- 400: {
15721
- headers: {
15722
- [name: string]: unknown;
15723
- };
15724
- content?: never;
15725
- };
15872
+ 400: components["responses"]["WalletKycRailBadId"];
15726
15873
  401: components["responses"]["UnauthorizedError"];
15727
15874
  403: components["responses"]["ForbiddenError"];
15728
- /** @description No such rail on the wallet's tenant, or an archived rail the wallet is not approved on (RAIL_NOT_FOUND) */
15729
- 404: {
15730
- headers: {
15731
- [name: string]: unknown;
15732
- };
15733
- content?: never;
15734
- };
15875
+ 404: components["responses"]["WalletKycRailNotFound"];
15735
15876
  };
15736
15877
  };
15737
15878
  put?: never;
@@ -15742,6 +15883,10 @@ export interface paths {
15742
15883
  * compliance (`WAITING_ON_REVIEW`); a universal rail is approved on the spot. An application the vendor
15743
15884
  * sent back (`HOLD`, `SOFT_REJECT`) is resubmitted. No body.
15744
15885
  *
15886
+ * On the KYC forms flow CORE makes this submission itself for a rail the client sent a rail or multi
15887
+ * form for, once the form is accepted and the entity is `APPROVED`, when the form was sent by a wallet `admin` or `owner` and the wallet has no application
15888
+ * on the rail yet; the route stays for a rail CORE could not submit and for a resubmission.
15889
+ *
15745
15890
  * Refused unless the rail has an onboarding implementation (retired rails never do), takes submissions,
15746
15891
  * fits the entity type, and the entity's KYC is `APPROVED` — an entity still under review
15747
15892
  * (`WAITING_ON_REVIEW`) cannot submit. On a tenant without KYC only the tenant's default universal rail
@@ -15774,48 +15919,67 @@ export interface paths {
15774
15919
  "application/json": components["schemas"]["WalletKycRailResponse"];
15775
15920
  };
15776
15921
  };
15777
- /** @description `rail_id` is not a UUID (VALIDATION_ERROR); the rail has no onboarding implementation, or is a universal
15778
- * rail other than the tenant's default on a tenant without KYC (RAIL_NOT_AVAILABLE); the rail takes no
15779
- * submissions (RAIL_SUBMIT_UNAVAILABLE); the rail is of the other entity type (RAIL_TYPE_MISMATCH); the
15780
- * onboarding behind the rail refused the submission (RAIL_SUBMISSION_REJECTED — the vendor's reason is
15781
- * logged, never returned)
15922
+ /** @description `VALIDATION_ERROR` — `rail_id` is not a UUID (a message only); `RAIL_NOT_AVAILABLE` — the rail has no
15923
+ * onboarding implementation, or is a universal rail other than the tenant's default on a tenant without
15924
+ * KYC; `RAIL_SUBMIT_UNAVAILABLE` — the rail takes no submissions; `RAIL_TYPE_MISMATCH` — the rail is of
15925
+ * the other entity type; `RAIL_SUBMISSION_REJECTED` — the onboarding behind the rail refused the
15926
+ * submission (the vendor's reason is logged, never returned); `RAIL_REQUIREMENTS_INCOMPLETE` — on a
15927
+ * tenant of the KYC forms flow, the KYC entity misses saved values of required fields of the rail's form
15928
+ * (a draft does not count): `details.fields` lists their keys, open
15929
+ * `GET /frontend/kyc/entities/{entity_id}/forms?rails={rail_id}` and fill them
15782
15930
  * */
15783
15931
  400: {
15784
15932
  headers: {
15785
15933
  [name: string]: unknown;
15786
15934
  };
15787
- content?: never;
15935
+ content: {
15936
+ "application/json": components["schemas"]["WalletKycRailSubmitErrorResponse"];
15937
+ };
15788
15938
  };
15789
15939
  401: components["responses"]["UnauthorizedError"];
15790
- /** @description Not an admin of the wallet (ACCESS_DENIED), or the entity's KYC is not approved — under review included (KYC_NOT_APPROVED) */
15940
+ /** @description `ACCESS_DENIED` — not an admin or owner of the wallet; `KYC_NOT_APPROVED` — the entity's KYC is not approved, under review included */
15791
15941
  403: {
15792
15942
  headers: {
15793
15943
  [name: string]: unknown;
15794
15944
  };
15795
- content?: never;
15945
+ content: {
15946
+ /** @example {
15947
+ * "success": false,
15948
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
15949
+ * "error": {
15950
+ * "code": "KYC_NOT_APPROVED",
15951
+ * "message": "Your KYC should be approved"
15952
+ * }
15953
+ * } */
15954
+ "application/json": components["schemas"]["ErrorResponse"];
15955
+ };
15796
15956
  };
15797
- /** @description No such rail on the wallet's tenant, or an archived one (RAIL_NOT_FOUND) */
15957
+ /** @description `RAIL_NOT_FOUND` — no such rail on the wallet's tenant, or an archived one */
15798
15958
  404: {
15799
15959
  headers: {
15800
15960
  [name: string]: unknown;
15801
15961
  };
15802
- content?: never;
15962
+ content: {
15963
+ "application/json": components["schemas"]["ErrorResponse"];
15964
+ };
15803
15965
  };
15804
- /** @description Already approved on the rail (RAIL_ALREADY_APPROVED), an application is with the vendor
15805
- * (RAIL_SUBMISSION_IN_PROGRESS), or the same submission is being processed (OPERATION_IN_PROGRESS)
15806
- * */
15966
+ /** @description `RAIL_ALREADY_APPROVED` — already approved on the rail; `RAIL_SUBMISSION_IN_PROGRESS` — an application is with the vendor; `OPERATION_IN_PROGRESS` — the same submission is being processed */
15807
15967
  409: {
15808
15968
  headers: {
15809
15969
  [name: string]: unknown;
15810
15970
  };
15811
- content?: never;
15971
+ content: {
15972
+ "application/json": components["schemas"]["ErrorResponse"];
15973
+ };
15812
15974
  };
15813
- /** @description The onboarding behind the rail failed or is unreachable (RAIL_SUBMISSION_FAILED), or the lock service is down (SERVICE_UNAVAILABLE) */
15975
+ /** @description `RAIL_SUBMISSION_FAILED` — the onboarding behind the rail failed or is unreachable; `SERVICE_UNAVAILABLE` — the lock service is down */
15814
15976
  503: {
15815
15977
  headers: {
15816
15978
  [name: string]: unknown;
15817
15979
  };
15818
- content?: never;
15980
+ content: {
15981
+ "application/json": components["schemas"]["ErrorResponse"];
15982
+ };
15819
15983
  };
15820
15984
  };
15821
15985
  };
@@ -15866,21 +16030,17 @@ export interface paths {
15866
16030
  "application/json": components["schemas"]["WalletKycRailResponse"];
15867
16031
  };
15868
16032
  };
15869
- /** @description `rail_id` is not a UUID (VALIDATION_ERROR) */
15870
- 400: {
15871
- headers: {
15872
- [name: string]: unknown;
15873
- };
15874
- content?: never;
15875
- };
16033
+ 400: components["responses"]["WalletKycRailBadId"];
15876
16034
  401: components["responses"]["UnauthorizedError"];
15877
16035
  403: components["responses"]["ForbiddenError"];
15878
- /** @description No such rail (RAIL_NOT_FOUND), or the wallet never submitted to it (RAIL_NOT_SUBMITTED) */
16036
+ /** @description `RAIL_NOT_FOUND` — no such rail; `RAIL_NOT_SUBMITTED` — the wallet never submitted to it */
15879
16037
  404: {
15880
16038
  headers: {
15881
16039
  [name: string]: unknown;
15882
16040
  };
15883
- content?: never;
16041
+ content: {
16042
+ "application/json": components["schemas"]["ErrorResponse"];
16043
+ };
15884
16044
  };
15885
16045
  };
15886
16046
  };
@@ -15890,39 +16050,27 @@ export interface paths {
15890
16050
  patch?: never;
15891
16051
  trace?: never;
15892
16052
  };
15893
- "/frontend/notifications/test": {
16053
+ "/frontend/kyc/entities": {
15894
16054
  parameters: {
15895
16055
  query?: never;
15896
16056
  header?: never;
15897
16057
  path?: never;
15898
16058
  cookie?: never;
15899
16059
  };
15900
- get?: never;
15901
- put?: never;
15902
16060
  /**
15903
- * Send mock notification events (development only)
15904
- * @description Publishes MOCK events straight to the delivery channels so a client can verify its realtime integration: `notification.created` plus a push carrier on the personal channel, and `data.changed` on the wallet channel when `wallet_id` is passed. The mock events are not stored. Additionally, when the wallet has at least one order, a REAL `ORDER_STATUS_CHANGED` notification is produced through the regular pipeline for the wallet's newest order — it lands in the inbox of every wallet member and is delivered over realtime and push (`inbox_outcome` reports the result; `null` means no order was found). Available only on development deployments.
16061
+ * The caller's KYC entities (forms flow)
16062
+ * @description The caller's own entities, oldest first, as the BFF `GET /kyc/entities` answered them. An entity shared through a wallet is not listed here: an owner or admin of the wallet reaches it by id. Authorization: Bearer token and `x-tenant-id`.
15905
16063
  */
15906
- post: {
16064
+ get: {
15907
16065
  parameters: {
15908
- query?: {
15909
- /** @description Accessible wallet whose channel receives the mock `data.changed` signal */
15910
- wallet_id?: string;
15911
- };
16066
+ query?: never;
15912
16067
  header?: never;
15913
16068
  path?: never;
15914
16069
  cookie?: never;
15915
16070
  };
15916
- requestBody?: {
15917
- content: {
15918
- "application/json": {
15919
- /** @description Push notification text */
15920
- message?: string;
15921
- };
15922
- };
15923
- };
16071
+ requestBody?: never;
15924
16072
  responses: {
15925
- /** @description Mock events published */
16073
+ /** @description Entities of the caller */
15926
16074
  200: {
15927
16075
  headers: {
15928
16076
  [name: string]: unknown;
@@ -15930,34 +16078,1276 @@ export interface paths {
15930
16078
  content: {
15931
16079
  "application/json": {
15932
16080
  /** @example true */
15933
- success?: boolean;
15934
- data?: {
15935
- /** Format: uuid */
15936
- notification_id?: string;
15937
- /** Format: uuid */
15938
- signaled_wallet_id?: string | null;
15939
- /**
15940
- * @description Result of the real inbox notification; null when no wallet was passed or it has no orders
15941
- * @enum {string|null}
15942
- */
15943
- inbox_outcome?: "PROCESSED" | "SKIPPED_UNRESOLVED" | "SKIPPED_DUPLICATE" | null;
15944
- /**
15945
- * Format: uuid
15946
- * @description Order the real notification was built from
15947
- */
15948
- inbox_order_uuid?: string | null;
15949
- };
16081
+ success: boolean;
16082
+ data: components["schemas"]["KycFormsEntity"][];
15950
16083
  };
15951
16084
  };
15952
16085
  };
16086
+ /** @description `KYC_FORMS_NOT_ENABLED` — the tenant still runs KYC through the BFF */
16087
+ 400: {
16088
+ headers: {
16089
+ [name: string]: unknown;
16090
+ };
16091
+ content: {
16092
+ "application/json": components["schemas"]["ErrorResponse"];
16093
+ };
16094
+ };
15953
16095
  401: components["responses"]["UnauthorizedError"];
15954
16096
  };
15955
16097
  };
15956
- delete?: never;
15957
- options?: never;
15958
- head?: never;
15959
- patch?: never;
15960
- trace?: never;
16098
+ put?: never;
16099
+ /**
16100
+ * Create the caller's KYC entity (forms flow)
16101
+ * @description Same path and shape as the BFF `POST /kyc/entities`. For `individual` the call is idempotent and answers the caller's personal entity; a `business` entity is created on every call. `201` also when an existing personal entity is returned. The type must be one the tenant enabled (`403 ACCESS_DENIED` otherwise). Authorization: Bearer token and `x-tenant-id`. One creation per user at a time (`409 OPERATION_IN_PROGRESS`).
16102
+ */
16103
+ post: {
16104
+ parameters: {
16105
+ query?: never;
16106
+ header?: never;
16107
+ path?: never;
16108
+ cookie?: never;
16109
+ };
16110
+ requestBody: {
16111
+ content: {
16112
+ /** @example {
16113
+ * "type": "individual"
16114
+ * } */
16115
+ "application/json": components["schemas"]["KycFormsCreateEntityRequest"];
16116
+ };
16117
+ };
16118
+ responses: {
16119
+ /** @description The entity */
16120
+ 201: {
16121
+ headers: {
16122
+ [name: string]: unknown;
16123
+ };
16124
+ content: {
16125
+ "application/json": {
16126
+ /** @example true */
16127
+ success: boolean;
16128
+ data: components["schemas"]["KycFormsEntity"];
16129
+ };
16130
+ };
16131
+ };
16132
+ /** @description `VALIDATION_ERROR` — `type` is missing or not `individual` / `business` (a message only); `KYC_FORMS_NOT_ENABLED` — the tenant still runs KYC through the BFF */
16133
+ 400: {
16134
+ headers: {
16135
+ [name: string]: unknown;
16136
+ };
16137
+ content: {
16138
+ "application/json": components["schemas"]["ErrorResponse"];
16139
+ };
16140
+ };
16141
+ 401: components["responses"]["UnauthorizedError"];
16142
+ /** @description `ACCESS_DENIED` — the entity type is not enabled for the tenant */
16143
+ 403: {
16144
+ headers: {
16145
+ [name: string]: unknown;
16146
+ };
16147
+ content: {
16148
+ "application/json": components["schemas"]["ErrorResponse"];
16149
+ };
16150
+ };
16151
+ /** @description `KYC_INDIVIDUAL_AMBIGUOUS` — the user has several personal entities, contact support; `OPERATION_IN_PROGRESS` — another creation by the same user is running */
16152
+ 409: {
16153
+ headers: {
16154
+ [name: string]: unknown;
16155
+ };
16156
+ content: {
16157
+ "application/json": components["schemas"]["ErrorResponse"];
16158
+ };
16159
+ };
16160
+ 503: components["responses"]["KycFormsLockUnavailable"];
16161
+ };
16162
+ };
16163
+ delete?: never;
16164
+ options?: never;
16165
+ head?: never;
16166
+ patch?: never;
16167
+ trace?: never;
16168
+ };
16169
+ "/frontend/kyc/targets": {
16170
+ parameters: {
16171
+ query?: never;
16172
+ header?: never;
16173
+ path?: never;
16174
+ cookie?: never;
16175
+ };
16176
+ /**
16177
+ * What a client of a type can be put on, before any entity or wallet
16178
+ * @description For the screen before KYC: the rails a client of `type` can apply for — the active rails of the type and the universal ones, as a new wallet of that type will list them — each with the account programs it opens and the card programs it makes visible, and, for `individual`, those card programs with the level their vendor demands. The ids are the `rails` / `programs` of `GET /frontend/kyc/entities/{entity_id}/forms`: pick them here, then create the entity (`POST /frontend/kyc/entities`) and its wallet (`POST /frontend/wallets` with `kyc_entity_id` — the link is set once, at creation), and open the form with `wallet_id`: CORE puts that wallet on the form's rails and programs once the form is accepted and the KYC `APPROVED`. A rail with a non-empty `account_programs` carries payments. Once the entity and wallet exist, `GET …/entities/{entity_id}/targets` tells the state of each form and application. Authorization: Bearer token and `x-tenant-id`; any user of the tenant.
16179
+ */
16180
+ get: {
16181
+ parameters: {
16182
+ query: {
16183
+ /** @description The client type: the type of the KYC entity the client is going to create. */
16184
+ type: "individual" | "business";
16185
+ };
16186
+ header?: never;
16187
+ path?: never;
16188
+ cookie?: never;
16189
+ };
16190
+ requestBody?: never;
16191
+ responses: {
16192
+ /** @description The rails and the card programs */
16193
+ 200: {
16194
+ headers: {
16195
+ [name: string]: unknown;
16196
+ };
16197
+ content: {
16198
+ "application/json": components["schemas"]["KycFormsTypeTargets"];
16199
+ };
16200
+ };
16201
+ /** @description `VALIDATION_ERROR` — `type` is missing or not `individual` / `business` (a message only); `KYC_FORMS_NOT_ENABLED` — the tenant still runs KYC through the BFF */
16202
+ 400: {
16203
+ headers: {
16204
+ [name: string]: unknown;
16205
+ };
16206
+ content: {
16207
+ "application/json": components["schemas"]["ErrorResponse"];
16208
+ };
16209
+ };
16210
+ 401: components["responses"]["UnauthorizedError"];
16211
+ /** @description `ACCESS_DENIED` — the type is not enabled for the tenant */
16212
+ 403: {
16213
+ headers: {
16214
+ [name: string]: unknown;
16215
+ };
16216
+ content: {
16217
+ "application/json": components["schemas"]["ErrorResponse"];
16218
+ };
16219
+ };
16220
+ };
16221
+ };
16222
+ put?: never;
16223
+ post?: never;
16224
+ delete?: never;
16225
+ options?: never;
16226
+ head?: never;
16227
+ patch?: never;
16228
+ trace?: never;
16229
+ };
16230
+ "/frontend/kyc/entities/{entity_id}": {
16231
+ parameters: {
16232
+ query?: never;
16233
+ header?: never;
16234
+ path?: never;
16235
+ cookie?: never;
16236
+ };
16237
+ /**
16238
+ * A KYC entity (forms flow)
16239
+ * @description One entity with its addresses, beneficial owners and documents, as the BFF `GET /kyc/entities/{id}` answered it. Access: the owner of the entity, or an owner / admin of a wallet it is linked to.
16240
+ */
16241
+ get: {
16242
+ parameters: {
16243
+ query?: never;
16244
+ header?: never;
16245
+ path: {
16246
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16247
+ entity_id: components["parameters"]["KycFormsEntityId"];
16248
+ };
16249
+ cookie?: never;
16250
+ };
16251
+ requestBody?: never;
16252
+ responses: {
16253
+ /** @description The entity */
16254
+ 200: {
16255
+ headers: {
16256
+ [name: string]: unknown;
16257
+ };
16258
+ content: {
16259
+ "application/json": {
16260
+ /** @example true */
16261
+ success: boolean;
16262
+ data: components["schemas"]["KycFormsEntity"];
16263
+ };
16264
+ };
16265
+ };
16266
+ 400: components["responses"]["KycFormsBadRequest"];
16267
+ 401: components["responses"]["UnauthorizedError"];
16268
+ 403: components["responses"]["KycFormsAccessDenied"];
16269
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant */
16270
+ 404: {
16271
+ headers: {
16272
+ [name: string]: unknown;
16273
+ };
16274
+ content: {
16275
+ "application/json": components["schemas"]["ErrorResponse"];
16276
+ };
16277
+ };
16278
+ };
16279
+ };
16280
+ put?: never;
16281
+ post?: never;
16282
+ delete?: never;
16283
+ options?: never;
16284
+ head?: never;
16285
+ patch?: never;
16286
+ trace?: never;
16287
+ };
16288
+ "/frontend/kyc/entities/{entity_id}/overview": {
16289
+ parameters: {
16290
+ query?: never;
16291
+ header?: never;
16292
+ path?: never;
16293
+ cookie?: never;
16294
+ };
16295
+ /**
16296
+ * What to show next for an entity
16297
+ * @description The stage of the application, whose move it is and the next step, with the state of the base form, the identity verification and — for an entity linked to a wallet — the rails. Build the screen by `stage`, `waiting_on` and `next_step`, not by the raw `status`. A business entity's `verification.applicant` is the filler's own check — the owner of the business entity, whoever reads the overview — `verification.owners[]` the checks of its beneficial owners — the persons, and the companies the identity provider checks (`type`). Access: the owner of the entity, or an owner / admin of a wallet it is linked to; `cards[]` only for the owner.
16298
+ */
16299
+ get: {
16300
+ parameters: {
16301
+ query?: {
16302
+ /** @description Language of the texts (labels, hints, options, section titles, general messages); takes precedence over `Accept-Language`. A language outside the tenant's list is served in English. */
16303
+ locale?: components["parameters"]["KycFormsLocale"];
16304
+ };
16305
+ header?: {
16306
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
16307
+ "Accept-Language"?: components["parameters"]["KycFormsAcceptLanguage"];
16308
+ };
16309
+ path: {
16310
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16311
+ entity_id: components["parameters"]["KycFormsEntityId"];
16312
+ };
16313
+ cookie?: never;
16314
+ };
16315
+ requestBody?: never;
16316
+ responses: {
16317
+ /** @description The overview */
16318
+ 200: {
16319
+ headers: {
16320
+ [name: string]: unknown;
16321
+ };
16322
+ content: {
16323
+ "application/json": components["schemas"]["KycFormsOverview"];
16324
+ };
16325
+ };
16326
+ 400: components["responses"]["KycFormsBadRequest"];
16327
+ 401: components["responses"]["UnauthorizedError"];
16328
+ 403: components["responses"]["KycFormsAccessDenied"];
16329
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant */
16330
+ 404: {
16331
+ headers: {
16332
+ [name: string]: unknown;
16333
+ };
16334
+ content: {
16335
+ "application/json": components["schemas"]["ErrorResponse"];
16336
+ };
16337
+ };
16338
+ 409: components["responses"]["KycFormsConditionsCycle"];
16339
+ };
16340
+ };
16341
+ put?: never;
16342
+ post?: never;
16343
+ delete?: never;
16344
+ options?: never;
16345
+ head?: never;
16346
+ patch?: never;
16347
+ trace?: never;
16348
+ };
16349
+ "/frontend/kyc/entities/{entity_id}/targets": {
16350
+ parameters: {
16351
+ query?: never;
16352
+ header?: never;
16353
+ path?: never;
16354
+ cookie?: never;
16355
+ };
16356
+ /**
16357
+ * What a multi form can be made of for an entity and a wallet
16358
+ * @description One read before composing `GET …/forms?rails=…&programs=…&wallet_id=…`: the base form, the active rails the wallet sees for this entity — with the wallet's application on each, as `GET /frontend/wallets/{wallet_id}/kyc-rails` shows it, without the terms — and, for a personal entity, the card programs the wallet may ask a card of, with the level their vendor demands. Every target carries the state of its form (`form_state`, `missing_required`, `submission`), so the client learns in one read what is still to be filled where. Access as the forms: the owner, or an owner / admin of a linked wallet.
16359
+ */
16360
+ get: {
16361
+ parameters: {
16362
+ query?: {
16363
+ /** @description The wallet the rails and the card programs are read for. Optional: without it the first linked wallet (main wallet first) that the entity's owner and the caller are both members of is used; when there is none — no linked wallet, or none the two share — the answer has `wallet_id: null` and empty `rails` and `programs`. With it, the entity's owner must be an active member of the wallet, and so must the caller when it is someone else, else `403 ACCESS_DENIED`. */
16364
+ wallet_id?: components["parameters"]["KycFormsTargetsWalletId"];
16365
+ };
16366
+ header?: never;
16367
+ path: {
16368
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16369
+ entity_id: components["parameters"]["KycFormsEntityId"];
16370
+ };
16371
+ cookie?: never;
16372
+ };
16373
+ requestBody?: never;
16374
+ responses: {
16375
+ /** @description The targets */
16376
+ 200: {
16377
+ headers: {
16378
+ [name: string]: unknown;
16379
+ };
16380
+ content: {
16381
+ "application/json": components["schemas"]["KycFormsTargets"];
16382
+ };
16383
+ };
16384
+ /** @description `VALIDATION_ERROR` — `entity_id` or `wallet_id` is not a uuid (a message only); `KYC_FORMS_NOT_ENABLED` — the tenant still runs KYC through the BFF */
16385
+ 400: {
16386
+ headers: {
16387
+ [name: string]: unknown;
16388
+ };
16389
+ content: {
16390
+ "application/json": components["schemas"]["ErrorResponse"];
16391
+ };
16392
+ };
16393
+ 401: components["responses"]["UnauthorizedError"];
16394
+ 403: components["responses"]["KycFormsAccessDenied"];
16395
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant */
16396
+ 404: {
16397
+ headers: {
16398
+ [name: string]: unknown;
16399
+ };
16400
+ content: {
16401
+ "application/json": components["schemas"]["ErrorResponse"];
16402
+ };
16403
+ };
16404
+ 409: components["responses"]["KycFormsConditionsCycle"];
16405
+ };
16406
+ };
16407
+ put?: never;
16408
+ post?: never;
16409
+ delete?: never;
16410
+ options?: never;
16411
+ head?: never;
16412
+ patch?: never;
16413
+ trace?: never;
16414
+ };
16415
+ "/frontend/kyc/entities/{entity_id}/forms": {
16416
+ parameters: {
16417
+ query?: never;
16418
+ header?: never;
16419
+ path?: never;
16420
+ cookie?: never;
16421
+ };
16422
+ /**
16423
+ * The form of an entity for a set of purposes
16424
+ * @description Built on every call from the tenant's requirement profiles and the entity. Without `rails` and `programs` it is the base form. With one rail it is that rail's form: the base profile, the tenant's rail profile and the vendor's minimum merged: a field required by any of them is required, `review` wins over `auto`, and a field is shown when any of them shows it (one asking it without a condition — the vendor's minimum always — shows it always); profiles whose conditions read each other in a circle answer `409 KYC_FORM_CONDITIONS_CYCLE`. Sections are the groups to draw, `visible_when` the show logic, `required_by` the purposes a field is required for, the locks (`saved`, `from_document`, `pending`, `status`) what the client cannot change, `schema_version` what to echo back. Fields that come from the identity document (names, date of birth, citizenship, the document number and dates) are left out until the document is verified; the document itself is asked: its type `gov_id_type` (`PASSPORT`, `ID_CARD`, `RESIDENCE_PERMIT`, `DRIVERS` — the codes `…/owners/{owner_id}/document` takes as `type` too), issuing country `gov_id_country` and photos `gov_id_front` and `gov_id_back` (shown unless a passport) — saved, and no longer asked, once it is verified; `state: complete` on a rail form means nothing is left to ask and the client goes straight to the rail's terms. With one program and `wallet_id` it is the form before a card: the level the program's vendor demands (`minimal`: name, email, phone; `basic`: plus date of birth, citizenship, gender, identity document type and number, residential address; `declared` / `full`: plus the identity document and the face, verified after the form) merged with the tenant's binding for the program, without the base form; what the personal entity already holds is locked `saved`, so `state: complete` means the card can be asked for at once. Several rails and programs at once is the multi form: the base form, every rail and every program merged, each field once with `required_by` naming the purposes. Access: the owner of the entity, or an owner / admin of a wallet it is linked to.
16425
+ */
16426
+ get: {
16427
+ parameters: {
16428
+ query?: {
16429
+ /** @description `kyc_rails.id` of the tenant the form is for, as a native query array: `rails[]=a&rails[]=b` or `rails=a&rails=b` (a comma-separated string is not a list). Empty with `programs`: the base form. One rail alone: that rail's form. Several, or together with `programs`: the multi form over the whole set (`scope: multi`), whatever the order of the ids. A rail of another client type than the entity's (and not universal), or one the tenant does not have, is `404 NOT_FOUND`; a value that is not a uuid is `400 VALIDATION_ERROR`. */
16430
+ rails?: components["parameters"]["KycFormsRails"];
16431
+ /** @description `issuing_programs.id` of the tenant the form is for, as a native query array: `programs[]=a&programs[]=b` or `programs=a&programs=b`. One program alone: the form before a card of that program (`scope: card`). Together with `rails` or several at once: the multi form. Only a personal entity has card forms (`400 FORM_TARGET_UNSUPPORTED` on a business entity); `wallet_id` is required whenever programs are named. A program the tenant does not have is `404 NOT_FOUND`. */
16432
+ programs?: components["parameters"]["KycFormsPrograms"];
16433
+ /** @description The wallet the form is filled for; the draft and the submission carry it, and CORE puts this wallet on the form's rails and programs once the form is accepted and the KYC is `APPROVED`. Required when `programs` are named (`400 INVALID_REQUEST` without it): the entity's owner must be an active member of it (any role; the cardholder is theirs), and so must the caller when it is someone else, else `403 ACCESS_DENIED`. Optional when only `rails` are named: a rail is opened per wallet, so it must be a wallet of this entity (`400 KYC_FORM_WALLET_NOT_LINKED` otherwise) with the same membership rule; without it the entity's main wallet. Ignored on the base form. Not a uuid: `400 VALIDATION_ERROR`. */
16434
+ wallet_id?: components["parameters"]["KycFormsWalletId"];
16435
+ /** @description Language of the texts (labels, hints, options, section titles, general messages); takes precedence over `Accept-Language`. A language outside the tenant's list is served in English. */
16436
+ locale?: components["parameters"]["KycFormsLocale"];
16437
+ };
16438
+ header?: {
16439
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
16440
+ "Accept-Language"?: components["parameters"]["KycFormsAcceptLanguage"];
16441
+ };
16442
+ path: {
16443
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16444
+ entity_id: components["parameters"]["KycFormsEntityId"];
16445
+ };
16446
+ cookie?: never;
16447
+ };
16448
+ requestBody?: never;
16449
+ responses: {
16450
+ /** @description The form and its values */
16451
+ 200: {
16452
+ headers: {
16453
+ [name: string]: unknown;
16454
+ };
16455
+ content: {
16456
+ "application/json": components["schemas"]["KycFormsFormResponse"];
16457
+ };
16458
+ };
16459
+ /** @description `VALIDATION_ERROR` — `entity_id`, `wallet_id` or an id in `rails` / `programs` is not a uuid (a message only); `FORM_TARGET_UNSUPPORTED` — a card program named on a business entity; `INVALID_REQUEST` — `wallet_id` missing for a form over card programs; `KYC_FORM_WALLET_NOT_LINKED` — `wallet_id` of a form over rails is not a wallet of this entity; `KYC_BASE_BINDING_MISSING` — the tenant has no base form for this client type; `KYC_FORMS_NOT_ENABLED` — the tenant still runs KYC through the BFF */
16460
+ 400: {
16461
+ headers: {
16462
+ [name: string]: unknown;
16463
+ };
16464
+ content: {
16465
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
16466
+ };
16467
+ };
16468
+ 401: components["responses"]["UnauthorizedError"];
16469
+ 403: components["responses"]["KycFormsAccessDenied"];
16470
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant, or a rail / program of the query does not exist for the tenant (a rail of another client type than the entity's included) */
16471
+ 404: {
16472
+ headers: {
16473
+ [name: string]: unknown;
16474
+ };
16475
+ content: {
16476
+ "application/json": components["schemas"]["ErrorResponse"];
16477
+ };
16478
+ };
16479
+ 409: components["responses"]["KycFormsConditionsCycle"];
16480
+ };
16481
+ };
16482
+ put?: never;
16483
+ post?: never;
16484
+ delete?: never;
16485
+ options?: never;
16486
+ head?: never;
16487
+ patch?: never;
16488
+ trace?: never;
16489
+ };
16490
+ "/frontend/kyc/entities/{entity_id}/forms/draft": {
16491
+ parameters: {
16492
+ query?: never;
16493
+ header?: never;
16494
+ path?: never;
16495
+ cookie?: never;
16496
+ };
16497
+ get?: never;
16498
+ /**
16499
+ * Save the draft of a form
16500
+ * @description The form is the one `rails` and `programs` name, as for `GET …/forms`. Replaces the draft as a whole with the given values of open fields. Types are checked, rules and requiredness are not — except that owner shares over 100% in total and a value whose condition reads an empty required source are refused here too. Nothing is written to the KYC entity. The first draft of a business form moves the application to `PENDING`. The entity's owner, or an owner or admin of a linked wallet.
16501
+ */
16502
+ put: {
16503
+ parameters: {
16504
+ query?: {
16505
+ /** @description `kyc_rails.id` of the tenant the form is for, as a native query array: `rails[]=a&rails[]=b` or `rails=a&rails=b` (a comma-separated string is not a list). Empty with `programs`: the base form. One rail alone: that rail's form. Several, or together with `programs`: the multi form over the whole set (`scope: multi`), whatever the order of the ids. A rail of another client type than the entity's (and not universal), or one the tenant does not have, is `404 NOT_FOUND`; a value that is not a uuid is `400 VALIDATION_ERROR`. */
16506
+ rails?: components["parameters"]["KycFormsRails"];
16507
+ /** @description `issuing_programs.id` of the tenant the form is for, as a native query array: `programs[]=a&programs[]=b` or `programs=a&programs=b`. One program alone: the form before a card of that program (`scope: card`). Together with `rails` or several at once: the multi form. Only a personal entity has card forms (`400 FORM_TARGET_UNSUPPORTED` on a business entity); `wallet_id` is required whenever programs are named. A program the tenant does not have is `404 NOT_FOUND`. */
16508
+ programs?: components["parameters"]["KycFormsPrograms"];
16509
+ /** @description The wallet the form is filled for; the draft and the submission carry it, and CORE puts this wallet on the form's rails and programs once the form is accepted and the KYC is `APPROVED`. Required when `programs` are named (`400 INVALID_REQUEST` without it): the entity's owner must be an active member of it (any role; the cardholder is theirs), and so must the caller when it is someone else, else `403 ACCESS_DENIED`. Optional when only `rails` are named: a rail is opened per wallet, so it must be a wallet of this entity (`400 KYC_FORM_WALLET_NOT_LINKED` otherwise) with the same membership rule; without it the entity's main wallet. Ignored on the base form. Not a uuid: `400 VALIDATION_ERROR`. */
16510
+ wallet_id?: components["parameters"]["KycFormsWalletId"];
16511
+ /** @description Language of the texts (labels, hints, options, section titles, general messages); takes precedence over `Accept-Language`. A language outside the tenant's list is served in English. */
16512
+ locale?: components["parameters"]["KycFormsLocale"];
16513
+ };
16514
+ header?: {
16515
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
16516
+ "Accept-Language"?: components["parameters"]["KycFormsAcceptLanguage"];
16517
+ };
16518
+ path: {
16519
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16520
+ entity_id: components["parameters"]["KycFormsEntityId"];
16521
+ };
16522
+ cookie?: never;
16523
+ };
16524
+ requestBody: {
16525
+ content: {
16526
+ "application/json": components["schemas"]["KycFormsAnswersRequest"];
16527
+ };
16528
+ };
16529
+ responses: {
16530
+ /** @description Saved: the new state of the form and how many required fields are still empty */
16531
+ 200: {
16532
+ headers: {
16533
+ [name: string]: unknown;
16534
+ };
16535
+ content: {
16536
+ "application/json": components["schemas"]["KycFormsDraftSaved"];
16537
+ };
16538
+ };
16539
+ 400: components["responses"]["KycFormsFieldErrors"];
16540
+ 401: components["responses"]["UnauthorizedError"];
16541
+ 403: components["responses"]["KycFormsAccessDenied"];
16542
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant, or a rail / program of the query does not exist for the tenant */
16543
+ 404: {
16544
+ headers: {
16545
+ [name: string]: unknown;
16546
+ };
16547
+ content: {
16548
+ "application/json": components["schemas"]["ErrorResponse"];
16549
+ };
16550
+ };
16551
+ /** @description `FORM_LOCKED` — the form is read-only by the application status, or its last submission waits on the verification or the review; `FORM_OUTDATED` — `schema_version` is not the one the form has now, reload it (`GET …/forms`) and send again; `KYC_FORM_CONDITIONS_CYCLE` — the tenant's form settings show fields on conditions that read each other in a circle */
16552
+ 409: {
16553
+ headers: {
16554
+ [name: string]: unknown;
16555
+ };
16556
+ content: {
16557
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
16558
+ };
16559
+ };
16560
+ };
16561
+ };
16562
+ post?: never;
16563
+ delete?: never;
16564
+ options?: never;
16565
+ head?: never;
16566
+ patch?: never;
16567
+ trace?: never;
16568
+ };
16569
+ "/frontend/kyc/entities/{entity_id}/forms/uploads": {
16570
+ parameters: {
16571
+ query?: never;
16572
+ header?: never;
16573
+ path?: never;
16574
+ cookie?: never;
16575
+ };
16576
+ get?: never;
16577
+ put?: never;
16578
+ /**
16579
+ * Upload a file into a file field of a form
16580
+ * @description The form is the one `rails` and `programs` name. Multipart: `field` (the key of an open file field: shown, not locked) and `file`. PDF, JPEG or PNG up to 20 MB, told by the bytes — a renamed file is refused with `DOCUMENT_REJECTED`; a field whose `file.accept` lists only images (the photos of the identity document, `gov_id_front` / `gov_id_back`) refuses a PDF the same way. A field that takes no files now — unknown, not a file field, locked (a form read-only by the application status locks every field), or hidden by its condition — is refused with `FORM_FIELD_NOT_ALLOWED`, whatever the file. The file stays in the draft until the submission is applied; a file of a field hidden by its condition stays in the draft's storage (removable by its `id`), is not listed in the form's `values` while hidden, and does not go with the submission. The photos of the identity document go to the identity provider once the submission waits on the verification. The entity's owner, or an owner or admin of a linked wallet.
16581
+ */
16582
+ post: {
16583
+ parameters: {
16584
+ query?: {
16585
+ /** @description `kyc_rails.id` of the tenant the form is for, as a native query array: `rails[]=a&rails[]=b` or `rails=a&rails=b` (a comma-separated string is not a list). Empty with `programs`: the base form. One rail alone: that rail's form. Several, or together with `programs`: the multi form over the whole set (`scope: multi`), whatever the order of the ids. A rail of another client type than the entity's (and not universal), or one the tenant does not have, is `404 NOT_FOUND`; a value that is not a uuid is `400 VALIDATION_ERROR`. */
16586
+ rails?: components["parameters"]["KycFormsRails"];
16587
+ /** @description `issuing_programs.id` of the tenant the form is for, as a native query array: `programs[]=a&programs[]=b` or `programs=a&programs=b`. One program alone: the form before a card of that program (`scope: card`). Together with `rails` or several at once: the multi form. Only a personal entity has card forms (`400 FORM_TARGET_UNSUPPORTED` on a business entity); `wallet_id` is required whenever programs are named. A program the tenant does not have is `404 NOT_FOUND`. */
16588
+ programs?: components["parameters"]["KycFormsPrograms"];
16589
+ /** @description The wallet the form is filled for; the draft and the submission carry it, and CORE puts this wallet on the form's rails and programs once the form is accepted and the KYC is `APPROVED`. Required when `programs` are named (`400 INVALID_REQUEST` without it): the entity's owner must be an active member of it (any role; the cardholder is theirs), and so must the caller when it is someone else, else `403 ACCESS_DENIED`. Optional when only `rails` are named: a rail is opened per wallet, so it must be a wallet of this entity (`400 KYC_FORM_WALLET_NOT_LINKED` otherwise) with the same membership rule; without it the entity's main wallet. Ignored on the base form. Not a uuid: `400 VALIDATION_ERROR`. */
16590
+ wallet_id?: components["parameters"]["KycFormsWalletId"];
16591
+ /** @description Language of the texts (labels, hints, options, section titles, general messages); takes precedence over `Accept-Language`. A language outside the tenant's list is served in English. */
16592
+ locale?: components["parameters"]["KycFormsLocale"];
16593
+ };
16594
+ header?: {
16595
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
16596
+ "Accept-Language"?: components["parameters"]["KycFormsAcceptLanguage"];
16597
+ };
16598
+ path: {
16599
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16600
+ entity_id: components["parameters"]["KycFormsEntityId"];
16601
+ };
16602
+ cookie?: never;
16603
+ };
16604
+ requestBody: {
16605
+ content: {
16606
+ "multipart/form-data": {
16607
+ /**
16608
+ * @description The key of the file field the file goes into.
16609
+ * @example document.proof_of_address
16610
+ */
16611
+ field: string;
16612
+ /**
16613
+ * Format: binary
16614
+ * @description One file, up to 20 MB.
16615
+ */
16616
+ file: string;
16617
+ };
16618
+ };
16619
+ };
16620
+ responses: {
16621
+ /** @description The uploaded file as the form lists it */
16622
+ 201: {
16623
+ headers: {
16624
+ [name: string]: unknown;
16625
+ };
16626
+ content: {
16627
+ "application/json": components["schemas"]["KycFormsUploadedFile"];
16628
+ };
16629
+ };
16630
+ /** @description `FORM_FIELD_NOT_ALLOWED` with `details.fields = [field]` — the field takes no files now (unknown, not a file field, locked, or hidden by its condition); `DOCUMENT_REJECTED` — the file: empty, over 20 MB, not PDF / JPEG / PNG by its bytes, a PDF for a field that takes photos only, or one more than the field takes (`file.max_files`); `VALIDATION_ERROR` — no `field` part, a `field` that is not a catalog key, or an id (`entity_id`, `wallet_id`, `rails`, `programs`) that is not a uuid; `INVALID_REQUEST` — no `file` part (or more than one), an unreadable multipart body, or `wallet_id` missing for a form over card programs; `FORM_TARGET_UNSUPPORTED` — a card program named on a business entity; `KYC_BASE_BINDING_MISSING` — the tenant has no base form for this client type; `KYC_FORMS_NOT_ENABLED`. */
16631
+ 400: {
16632
+ headers: {
16633
+ [name: string]: unknown;
16634
+ };
16635
+ content: {
16636
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
16637
+ };
16638
+ };
16639
+ 401: components["responses"]["UnauthorizedError"];
16640
+ 403: components["responses"]["KycFormsAccessDenied"];
16641
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant, or a rail / program of the query does not exist for the tenant */
16642
+ 404: {
16643
+ headers: {
16644
+ [name: string]: unknown;
16645
+ };
16646
+ content: {
16647
+ "application/json": components["schemas"]["ErrorResponse"];
16648
+ };
16649
+ };
16650
+ /** @description `FORM_LOCKED` — the last submission of the form waits on the verification or the review (a form read-only by the application status answers `400 FORM_FIELD_NOT_ALLOWED` instead); `KYC_FORM_CONDITIONS_CYCLE` — the tenant's form settings show fields on conditions that read each other in a circle. */
16651
+ 409: {
16652
+ headers: {
16653
+ [name: string]: unknown;
16654
+ };
16655
+ content: {
16656
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
16657
+ };
16658
+ };
16659
+ /** @description File storage is not configured on this server (SERVICE_UNAVAILABLE) */
16660
+ 503: {
16661
+ headers: {
16662
+ [name: string]: unknown;
16663
+ };
16664
+ content: {
16665
+ "application/json": components["schemas"]["ErrorResponse"];
16666
+ };
16667
+ };
16668
+ };
16669
+ };
16670
+ delete?: never;
16671
+ options?: never;
16672
+ head?: never;
16673
+ patch?: never;
16674
+ trace?: never;
16675
+ };
16676
+ "/frontend/kyc/entities/{entity_id}/forms/uploads/{upload_id}": {
16677
+ parameters: {
16678
+ query?: never;
16679
+ header?: never;
16680
+ path?: never;
16681
+ cookie?: never;
16682
+ };
16683
+ get?: never;
16684
+ put?: never;
16685
+ post?: never;
16686
+ /**
16687
+ * Remove a file from the draft of a form
16688
+ * @description The form is the one `rails` and `programs` name. Only a file of the draft (`saved: false`) can be removed; a document already in the KYC entity never is. The entity's owner, or an owner or admin of a linked wallet.
16689
+ */
16690
+ delete: {
16691
+ parameters: {
16692
+ query?: {
16693
+ /** @description `kyc_rails.id` of the tenant the form is for, as a native query array: `rails[]=a&rails[]=b` or `rails=a&rails=b` (a comma-separated string is not a list). Empty with `programs`: the base form. One rail alone: that rail's form. Several, or together with `programs`: the multi form over the whole set (`scope: multi`), whatever the order of the ids. A rail of another client type than the entity's (and not universal), or one the tenant does not have, is `404 NOT_FOUND`; a value that is not a uuid is `400 VALIDATION_ERROR`. */
16694
+ rails?: components["parameters"]["KycFormsRails"];
16695
+ /** @description `issuing_programs.id` of the tenant the form is for, as a native query array: `programs[]=a&programs[]=b` or `programs=a&programs=b`. One program alone: the form before a card of that program (`scope: card`). Together with `rails` or several at once: the multi form. Only a personal entity has card forms (`400 FORM_TARGET_UNSUPPORTED` on a business entity); `wallet_id` is required whenever programs are named. A program the tenant does not have is `404 NOT_FOUND`. */
16696
+ programs?: components["parameters"]["KycFormsPrograms"];
16697
+ /** @description The wallet the form is filled for; the draft and the submission carry it, and CORE puts this wallet on the form's rails and programs once the form is accepted and the KYC is `APPROVED`. Required when `programs` are named (`400 INVALID_REQUEST` without it): the entity's owner must be an active member of it (any role; the cardholder is theirs), and so must the caller when it is someone else, else `403 ACCESS_DENIED`. Optional when only `rails` are named: a rail is opened per wallet, so it must be a wallet of this entity (`400 KYC_FORM_WALLET_NOT_LINKED` otherwise) with the same membership rule; without it the entity's main wallet. Ignored on the base form. Not a uuid: `400 VALIDATION_ERROR`. */
16698
+ wallet_id?: components["parameters"]["KycFormsWalletId"];
16699
+ };
16700
+ header?: never;
16701
+ path: {
16702
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16703
+ entity_id: components["parameters"]["KycFormsEntityId"];
16704
+ /** @description The `id` of a file in the draft (`saved: false`) */
16705
+ upload_id: components["parameters"]["KycFormsUploadId"];
16706
+ };
16707
+ cookie?: never;
16708
+ };
16709
+ requestBody?: never;
16710
+ responses: {
16711
+ /** @description Removed */
16712
+ 200: {
16713
+ headers: {
16714
+ [name: string]: unknown;
16715
+ };
16716
+ content: {
16717
+ "application/json": {
16718
+ /** @example true */
16719
+ success: boolean;
16720
+ data: {
16721
+ /** @example true */
16722
+ removed: boolean;
16723
+ };
16724
+ };
16725
+ };
16726
+ };
16727
+ /** @description `VALIDATION_ERROR` — an id (`entity_id`, `upload_id`, `wallet_id`, `rails`, `programs`) is not a uuid; `INVALID_REQUEST` — `wallet_id` missing for a form over card programs; `KYC_FORMS_NOT_ENABLED`. */
16728
+ 400: {
16729
+ headers: {
16730
+ [name: string]: unknown;
16731
+ };
16732
+ content: {
16733
+ "application/json": components["schemas"]["ErrorResponse"];
16734
+ };
16735
+ };
16736
+ 401: components["responses"]["UnauthorizedError"];
16737
+ 403: components["responses"]["KycFormsAccessDenied"];
16738
+ /** @description The entity does not exist or belongs to another tenant, or the upload is not in the draft of this form — a saved document is never removed here (`NOT_FOUND`). */
16739
+ 404: {
16740
+ headers: {
16741
+ [name: string]: unknown;
16742
+ };
16743
+ content: {
16744
+ "application/json": components["schemas"]["ErrorResponse"];
16745
+ };
16746
+ };
16747
+ };
16748
+ };
16749
+ options?: never;
16750
+ head?: never;
16751
+ patch?: never;
16752
+ trace?: never;
16753
+ };
16754
+ "/frontend/kyc/entities/{entity_id}/forms/submit": {
16755
+ parameters: {
16756
+ query?: never;
16757
+ header?: never;
16758
+ path?: never;
16759
+ cookie?: never;
16760
+ };
16761
+ get?: never;
16762
+ put?: never;
16763
+ /**
16764
+ * Send a form
16765
+ * @description The form is the one `rails` and `programs` name. The full check of every open field (all errors in one `VALIDATION_ERROR`), then a submission: `awaiting_verification` when the identity document and face are still needed, `applied` when every profile of the form writes the answers into the KYC entity at once, `in_review` when compliance decides (any profile of the form in review mode). Answers `200` with the form in its new state. One submission of a form at a time. A form over rails or programs that brings nothing new — no value and no file, every required field already saved in the entity (not just waiting in another submission under review) — is `applied` at once whatever the review mode: there is nothing for compliance to decide. A rail form does not change the application status. A card form is `auto` unless a profile of it says otherwise and never changes the application status. A multi form moves the application like the base form it includes; once applied, every rail and program of the set is satisfied from the shared data. Once a rail, card or multi form is accepted (`applied`, or `approved` by compliance) and the wallet's KYC is `APPROVED` — whichever comes second — when the form was sent by an owner or admin of the wallet (the role those routes ask for), CORE submits the wallet itself: to each rail of the form the wallet has no application on yet — only for a form of the wallet's own KYC entity, a member's form never puts the wallet on a rail — (as `POST /frontend/wallets/{wallet_id}/kyc-rails/{rail_id}` would; it then shows in `GET …/kyc-rails`), and to each program the member has no cardholder in yet (as `POST /frontend/issuing/cardholders` with `user_data_id` and its submit would). The latest form sent for a rail or program decides: returned, rejected or still in review, nothing is submitted. A submission CORE could not make — refused by the rail or the vendor, a program at its limit, a form sent by a member without that role — is left for the client to make with those routes, as before. The entity's owner, or an owner or admin of a linked wallet.
16766
+ */
16767
+ post: {
16768
+ parameters: {
16769
+ query?: {
16770
+ /** @description `kyc_rails.id` of the tenant the form is for, as a native query array: `rails[]=a&rails[]=b` or `rails=a&rails=b` (a comma-separated string is not a list). Empty with `programs`: the base form. One rail alone: that rail's form. Several, or together with `programs`: the multi form over the whole set (`scope: multi`), whatever the order of the ids. A rail of another client type than the entity's (and not universal), or one the tenant does not have, is `404 NOT_FOUND`; a value that is not a uuid is `400 VALIDATION_ERROR`. */
16771
+ rails?: components["parameters"]["KycFormsRails"];
16772
+ /** @description `issuing_programs.id` of the tenant the form is for, as a native query array: `programs[]=a&programs[]=b` or `programs=a&programs=b`. One program alone: the form before a card of that program (`scope: card`). Together with `rails` or several at once: the multi form. Only a personal entity has card forms (`400 FORM_TARGET_UNSUPPORTED` on a business entity); `wallet_id` is required whenever programs are named. A program the tenant does not have is `404 NOT_FOUND`. */
16773
+ programs?: components["parameters"]["KycFormsPrograms"];
16774
+ /** @description The wallet the form is filled for; the draft and the submission carry it, and CORE puts this wallet on the form's rails and programs once the form is accepted and the KYC is `APPROVED`. Required when `programs` are named (`400 INVALID_REQUEST` without it): the entity's owner must be an active member of it (any role; the cardholder is theirs), and so must the caller when it is someone else, else `403 ACCESS_DENIED`. Optional when only `rails` are named: a rail is opened per wallet, so it must be a wallet of this entity (`400 KYC_FORM_WALLET_NOT_LINKED` otherwise) with the same membership rule; without it the entity's main wallet. Ignored on the base form. Not a uuid: `400 VALIDATION_ERROR`. */
16775
+ wallet_id?: components["parameters"]["KycFormsWalletId"];
16776
+ /** @description Language of the texts (labels, hints, options, section titles, general messages); takes precedence over `Accept-Language`. A language outside the tenant's list is served in English. */
16777
+ locale?: components["parameters"]["KycFormsLocale"];
16778
+ };
16779
+ header?: {
16780
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
16781
+ "Accept-Language"?: components["parameters"]["KycFormsAcceptLanguage"];
16782
+ };
16783
+ path: {
16784
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16785
+ entity_id: components["parameters"]["KycFormsEntityId"];
16786
+ };
16787
+ cookie?: never;
16788
+ };
16789
+ requestBody: {
16790
+ content: {
16791
+ "application/json": components["schemas"]["KycFormsAnswersRequest"];
16792
+ };
16793
+ };
16794
+ responses: {
16795
+ /** @description The form after the submission */
16796
+ 200: {
16797
+ headers: {
16798
+ [name: string]: unknown;
16799
+ };
16800
+ content: {
16801
+ "application/json": components["schemas"]["KycFormsFormResponse"];
16802
+ };
16803
+ };
16804
+ 400: components["responses"]["KycFormsFieldErrors"];
16805
+ 401: components["responses"]["UnauthorizedError"];
16806
+ 403: components["responses"]["KycFormsAccessDenied"];
16807
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant, or a rail / program of the query does not exist for the tenant */
16808
+ 404: {
16809
+ headers: {
16810
+ [name: string]: unknown;
16811
+ };
16812
+ content: {
16813
+ "application/json": components["schemas"]["ErrorResponse"];
16814
+ };
16815
+ };
16816
+ /** @description `FORM_LOCKED` — the form is read-only by the application status, or its last submission waits on the verification or the review; `FORM_OUTDATED` — `schema_version` is not the one the form has now, reload it (`GET …/forms`) and send again; `OPERATION_IN_PROGRESS` — a submission of this form is already running; `KYC_FORM_CONDITIONS_CYCLE` — the tenant's form settings show fields on conditions that read each other in a circle */
16817
+ 409: {
16818
+ headers: {
16819
+ [name: string]: unknown;
16820
+ };
16821
+ content: {
16822
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
16823
+ };
16824
+ };
16825
+ 503: components["responses"]["KycFormsLockUnavailable"];
16826
+ };
16827
+ };
16828
+ delete?: never;
16829
+ options?: never;
16830
+ head?: never;
16831
+ patch?: never;
16832
+ trace?: never;
16833
+ };
16834
+ "/frontend/kyc/entities/{entity_id}/verification/session": {
16835
+ parameters: {
16836
+ query?: never;
16837
+ header?: never;
16838
+ path?: never;
16839
+ cookie?: never;
16840
+ };
16841
+ get?: never;
16842
+ put?: never;
16843
+ /**
16844
+ * Start or continue the identity verification; a widget token
16845
+ * @description The owner of a personal entity passes the identity check in the identity verification widget after sending a form whose purpose needs it (the submission is `awaiting_verification`), or again when the overview says `retry`. CORE finds or creates the applicant of the personal entity on the tenant's individual verification level — an applicant from the old flow is moved to that level, its passed steps kept — hands it the photos of the identity document uploaded with the waiting form (once per file; not when the provider already accepted a document of the applicant), and answers a token for the widget. With the document handed over, the widget asks only for the face; it asks for the document itself when the form carried none, when the provider could not take it, or to retake a photo the provider refused. Called on a business entity, it verifies the filler — the owner of the business entity, who alone may call it: the token is for their own personal entity (created when missing), whose id comes back in `entity_id`. An admin of the wallet fills and sends a business form, the owner passes the check (the overview answers the admin `waiting_on: applicant`). The token expires after `expires_in` seconds; the widget's expiry handler calls this route again. The result of the check arrives later through the provider's webhook; until then the overview shows `in_progress` (the widget is open, or the document was handed over and the face is due) and then `in_review` (the provider is looking). One start per entity at a time: a parallel call gets `409 OPERATION_IN_PROGRESS`; a handover of the document already running in the background is waited for a few seconds first. Takes no body.
16846
+ */
16847
+ post: {
16848
+ parameters: {
16849
+ query?: never;
16850
+ header?: never;
16851
+ path: {
16852
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16853
+ entity_id: components["parameters"]["KycFormsEntityId"];
16854
+ };
16855
+ cookie?: never;
16856
+ };
16857
+ requestBody?: never;
16858
+ responses: {
16859
+ /** @description The widget token */
16860
+ 200: {
16861
+ headers: {
16862
+ [name: string]: unknown;
16863
+ };
16864
+ content: {
16865
+ "application/json": {
16866
+ /** @example true */
16867
+ success: boolean;
16868
+ /** @example {
16869
+ * "provider": "kyc_widget",
16870
+ * "token": "eyJhbGciOiJIUzI1NiJ9.example",
16871
+ * "expires_in": 600,
16872
+ * "entity_id": "5e6f7081-9203-4b4c-8d5e-6f708192a3b4",
16873
+ * "applicant_id": "64a1b2c3d4e5f60718293a4b"
16874
+ * } */
16875
+ data: {
16876
+ /**
16877
+ * @description Which widget to open.
16878
+ * @enum {string}
16879
+ */
16880
+ provider: "kyc_widget";
16881
+ /** @description The widget access token; a credential — never log it. */
16882
+ token: string;
16883
+ /**
16884
+ * @description Seconds the token lives.
16885
+ * @example 600
16886
+ */
16887
+ expires_in: number;
16888
+ /**
16889
+ * Format: uuid
16890
+ * @description The personal entity the verification belongs to — the business owner's own when a business entity started it.
16891
+ */
16892
+ entity_id: string;
16893
+ /** @description The identity provider's applicant id. */
16894
+ applicant_id: string;
16895
+ };
16896
+ };
16897
+ };
16898
+ };
16899
+ /** @description `VALIDATION_ERROR` — `entity_id` is not a uuid; `KYC_FORMS_NOT_ENABLED`; `KYC_VERIFICATION_LEVEL_MISSING` — the tenant has no individual verification level configured; `VERIFICATION_PROVIDER_UNAVAILABLE` — the identity provider refused or did not answer, try later; `VERIFICATION_PROVIDER_NOT_CONFIGURED` — the identity verification is not configured on this server. */
16900
+ 400: {
16901
+ headers: {
16902
+ [name: string]: unknown;
16903
+ };
16904
+ content: {
16905
+ "application/json": components["schemas"]["ErrorResponse"];
16906
+ };
16907
+ };
16908
+ 401: components["responses"]["UnauthorizedError"];
16909
+ /** @description `ACCESS_DENIED` — not the owner of the entity, personal or business: an admin of a linked wallet fills and sends the forms but never passes the owner's identity check. */
16910
+ 403: {
16911
+ headers: {
16912
+ [name: string]: unknown;
16913
+ };
16914
+ content: {
16915
+ "application/json": components["schemas"]["ErrorResponse"];
16916
+ };
16917
+ };
16918
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant */
16919
+ 404: {
16920
+ headers: {
16921
+ [name: string]: unknown;
16922
+ };
16923
+ content: {
16924
+ "application/json": components["schemas"]["ErrorResponse"];
16925
+ };
16926
+ };
16927
+ /** @description `KYC_INDIVIDUAL_AMBIGUOUS` — the owner has several personal entities (a business entity started the verification), contact support; `OPERATION_IN_PROGRESS` — a start for this entity is already running. */
16928
+ 409: {
16929
+ headers: {
16930
+ [name: string]: unknown;
16931
+ };
16932
+ content: {
16933
+ "application/json": components["schemas"]["ErrorResponse"];
16934
+ };
16935
+ };
16936
+ 503: components["responses"]["KycFormsLockUnavailable"];
16937
+ };
16938
+ };
16939
+ delete?: never;
16940
+ options?: never;
16941
+ head?: never;
16942
+ patch?: never;
16943
+ trace?: never;
16944
+ };
16945
+ "/frontend/kyc/entities/{entity_id}/verification/owners/invite": {
16946
+ parameters: {
16947
+ query?: never;
16948
+ header?: never;
16949
+ path?: never;
16950
+ cookie?: never;
16951
+ };
16952
+ get?: never;
16953
+ put?: never;
16954
+ /**
16955
+ * Email the owners their identity check links again
16956
+ * @description A business entity whose base form was sent (step 8/8 of the KYC forms). Asks the identity provider to email the owners the link to their identity check once more. The provider writes every person linked to the company who has an email with it and has not passed the check — one addressee at a time is not offered: the owners whose item has `invite_by_email: true` and an email, and the person filling the form (their applicant carries the email of their account; they can still pass the check from the app through `POST …/verification/session`). An owner who has passed, or whose check is with the provider, is not written; a company among the owners (`type: company`) never is. The first mailing goes on its own right after the form is sent — this route repeats it, at most once in 10 minutes per business, the first mailing counted: `GET …/overview` shows `verification.invites.sent_at` and `next_at`, and `verification.owners[].invited_at` per owner. Nobody left to email (`400 KYC_NO_OWNER_TO_INVITE`): hand the link over through `…/owners/{owner_id}/link` or `/session`. Takes no body. Access: the owner of the business entity, or an owner / admin of a wallet it is linked to. One mailing per entity at a time, and none while the set-up after the sent form is running (`409 OPERATION_IN_PROGRESS`).
16957
+ */
16958
+ post: {
16959
+ parameters: {
16960
+ query?: never;
16961
+ header?: never;
16962
+ path: {
16963
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
16964
+ entity_id: components["parameters"]["KycFormsEntityId"];
16965
+ };
16966
+ cookie?: never;
16967
+ };
16968
+ requestBody?: never;
16969
+ responses: {
16970
+ /** @description The provider was asked */
16971
+ 200: {
16972
+ headers: {
16973
+ [name: string]: unknown;
16974
+ };
16975
+ content: {
16976
+ "application/json": {
16977
+ /** @example true */
16978
+ success: boolean;
16979
+ /** @example {
16980
+ * "sent_at": "2026-10-22T09:30:00.000Z",
16981
+ * "next_at": "2026-10-22T09:40:00.000Z",
16982
+ * "owners": [
16983
+ * "2d7c1b9e-4f30-4a8c-9e21-7b6a5c4d3e2f",
16984
+ * "9b1f6c3a-2e4d-4f7a-8c5b-1d2e3f4a5b6c"
16985
+ * ]
16986
+ * } */
16987
+ data: {
16988
+ /**
16989
+ * Format: date-time
16990
+ * @description When the identity provider was asked — the new `verification.invites.sent_at` of the overview.
16991
+ */
16992
+ sent_at: string;
16993
+ /**
16994
+ * Format: date-time
16995
+ * @description From when this route is taken again: 10 minutes after `sent_at`.
16996
+ */
16997
+ next_at: string;
16998
+ /** @description The owners the mailing reaches by what CORE knows — the `owner_id`s whose `invited_at` was set now, the filler's own row included. */
16999
+ owners: string[];
17000
+ };
17001
+ };
17002
+ };
17003
+ };
17004
+ /** @description `KYC_NO_OWNER_TO_INVITE` — nobody is left to email: every owner with an email at the identity provider has passed the check, or none has an email there (hand the link over: `…/owners/{owner_id}/link` or `/session`); `VALIDATION_ERROR` — `entity_id` is not a uuid; `KYC_FORMS_NOT_ENABLED`; `VERIFICATION_PROVIDER_UNAVAILABLE` — the identity provider refused or did not answer, try later; `VERIFICATION_PROVIDER_NOT_CONFIGURED`. */
17005
+ 400: {
17006
+ headers: {
17007
+ [name: string]: unknown;
17008
+ };
17009
+ content: {
17010
+ "application/json": components["schemas"]["ErrorResponse"];
17011
+ };
17012
+ };
17013
+ 401: components["responses"]["UnauthorizedError"];
17014
+ 403: components["responses"]["KycFormsAccessDenied"];
17015
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant */
17016
+ 404: {
17017
+ headers: {
17018
+ [name: string]: unknown;
17019
+ };
17020
+ content: {
17021
+ "application/json": components["schemas"]["ErrorResponse"];
17022
+ };
17023
+ };
17024
+ 409: components["responses"]["KycFormsOwnerInviteConflict"];
17025
+ 503: components["responses"]["KycFormsLockUnavailable"];
17026
+ };
17027
+ };
17028
+ delete?: never;
17029
+ options?: never;
17030
+ head?: never;
17031
+ patch?: never;
17032
+ trace?: never;
17033
+ };
17034
+ "/frontend/kyc/entities/{entity_id}/verification/owners/{owner_id}/link": {
17035
+ parameters: {
17036
+ query?: never;
17037
+ header?: never;
17038
+ path?: never;
17039
+ cookie?: never;
17040
+ };
17041
+ get?: never;
17042
+ put?: never;
17043
+ /**
17044
+ * The identity check link of a beneficial owner, to hand over yourself
17045
+ * @description A business entity whose base form was sent (step 8/8 of the KYC forms). CORE makes sure the owner has an applicant with the identity provider — created from what the form declared about them, so the provider compares it with the document — and answers a link to the provider's own check page for it, for the filler to pass on by their own channel. After the form is sent the identity provider itself emails the link to the owners whose item has `invite_by_email: true` and an email (and to the filler), and `POST …/verification/owners/invite` has it email them again, at most once in 10 minutes; this route is for an owner without an email, or to pass the link on by your own channel. Valid 7 days; every call makes a new link for the same applicant, the previous one keeps working until it expires. The outcome arrives through the provider's webhook: `GET …/overview` shows it under `verification.owners[]`. Takes no body. Access: the owner of the business entity, or an owner / admin of a wallet it is linked to.
17046
+ */
17047
+ post: {
17048
+ parameters: {
17049
+ query?: never;
17050
+ header?: never;
17051
+ path: {
17052
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
17053
+ entity_id: components["parameters"]["KycFormsEntityId"];
17054
+ /** @description The `id` of a beneficial owner of the business entity — an item of `beneficial_owners` as `GET …/forms` lists it after the base form was sent (every saved item carries its `id`; `verification.owners[].id` of the overview is the same id). A person, not a company; not the owner the filler marked as themselves (`is_applicant`). */
17055
+ owner_id: components["parameters"]["KycFormsOwnerId"];
17056
+ };
17057
+ cookie?: never;
17058
+ };
17059
+ requestBody?: never;
17060
+ responses: {
17061
+ /** @description The link */
17062
+ 200: {
17063
+ headers: {
17064
+ [name: string]: unknown;
17065
+ };
17066
+ content: {
17067
+ "application/json": {
17068
+ /** @example true */
17069
+ success: boolean;
17070
+ /** @example {
17071
+ * "url": "https://verify.example.com/idCheck/abc123",
17072
+ * "expires_at": "2026-10-26T09:30:00Z"
17073
+ * } */
17074
+ data: {
17075
+ /**
17076
+ * Format: uri
17077
+ * @description The identity check page of the owner; a credential — show it to the owner only.
17078
+ */
17079
+ url: string;
17080
+ /**
17081
+ * Format: date-time
17082
+ * @description Seven days from the call.
17083
+ */
17084
+ expires_at: string;
17085
+ };
17086
+ };
17087
+ };
17088
+ };
17089
+ 400: components["responses"]["KycFormsOwnerErrors"];
17090
+ 401: components["responses"]["UnauthorizedError"];
17091
+ 403: components["responses"]["KycFormsAccessDenied"];
17092
+ 404: components["responses"]["KycFormsOwnerNotFound"];
17093
+ 409: components["responses"]["KycFormsOwnerConflict"];
17094
+ 503: components["responses"]["KycFormsLockUnavailable"];
17095
+ };
17096
+ };
17097
+ delete?: never;
17098
+ options?: never;
17099
+ head?: never;
17100
+ patch?: never;
17101
+ trace?: never;
17102
+ };
17103
+ "/frontend/kyc/entities/{entity_id}/verification/owners/{owner_id}/session": {
17104
+ parameters: {
17105
+ query?: never;
17106
+ header?: never;
17107
+ path?: never;
17108
+ cookie?: never;
17109
+ };
17110
+ get?: never;
17111
+ put?: never;
17112
+ /**
17113
+ * A widget token for a beneficial owner's identity check
17114
+ * @description Like `POST …/verification/session`, for an owner who is with the filler: the identity verification widget opens for the owner's applicant (created when missing). No email is needed — the filler can pass every owner's check on this device, one owner after another. The token lets its holder pass the check as that owner — hand it to the owner only. It expires after `expires_in` seconds; call again for a new one. Takes no body. Access: the owner of the business entity, or an owner / admin of a wallet it is linked to.
17115
+ */
17116
+ post: {
17117
+ parameters: {
17118
+ query?: never;
17119
+ header?: never;
17120
+ path: {
17121
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
17122
+ entity_id: components["parameters"]["KycFormsEntityId"];
17123
+ /** @description The `id` of a beneficial owner of the business entity — an item of `beneficial_owners` as `GET …/forms` lists it after the base form was sent (every saved item carries its `id`; `verification.owners[].id` of the overview is the same id). A person, not a company; not the owner the filler marked as themselves (`is_applicant`). */
17124
+ owner_id: components["parameters"]["KycFormsOwnerId"];
17125
+ };
17126
+ cookie?: never;
17127
+ };
17128
+ requestBody?: never;
17129
+ responses: {
17130
+ /** @description The widget token */
17131
+ 200: {
17132
+ headers: {
17133
+ [name: string]: unknown;
17134
+ };
17135
+ content: {
17136
+ "application/json": {
17137
+ /** @example true */
17138
+ success: boolean;
17139
+ data: {
17140
+ /**
17141
+ * @description Which widget to open.
17142
+ * @enum {string}
17143
+ */
17144
+ provider: "kyc_widget";
17145
+ /** @description The widget access token; a credential — never log it. */
17146
+ token: string;
17147
+ /**
17148
+ * @description Seconds the token lives.
17149
+ * @example 600
17150
+ */
17151
+ expires_in: number;
17152
+ /**
17153
+ * Format: uuid
17154
+ * @description The business entity.
17155
+ */
17156
+ entity_id: string;
17157
+ /** Format: uuid */
17158
+ owner_id: string;
17159
+ /** @description The identity provider's applicant id of the owner. */
17160
+ applicant_id: string;
17161
+ };
17162
+ };
17163
+ };
17164
+ };
17165
+ 400: components["responses"]["KycFormsOwnerErrors"];
17166
+ 401: components["responses"]["UnauthorizedError"];
17167
+ 403: components["responses"]["KycFormsAccessDenied"];
17168
+ 404: components["responses"]["KycFormsOwnerNotFound"];
17169
+ 409: components["responses"]["KycFormsOwnerConflict"];
17170
+ 503: components["responses"]["KycFormsLockUnavailable"];
17171
+ };
17172
+ };
17173
+ delete?: never;
17174
+ options?: never;
17175
+ head?: never;
17176
+ patch?: never;
17177
+ trace?: never;
17178
+ };
17179
+ "/frontend/kyc/entities/{entity_id}/verification/owners/{owner_id}/document": {
17180
+ parameters: {
17181
+ query?: never;
17182
+ header?: never;
17183
+ path?: never;
17184
+ cookie?: never;
17185
+ };
17186
+ get?: never;
17187
+ put?: never;
17188
+ /**
17189
+ * Upload a beneficial owner's identity document for them
17190
+ * @description Multipart: `file` (JPEG or PNG up to 20 MB, told by the bytes — the provider takes photos only, a PDF is refused), `side` (`front` or `back`; a passport has only a front side, so `back` needs a `type` other than `passport`), optional `type` (`passport` by default) and `country` (alpha-2 from the country directory — `DE`, not `DEU` or `Germany`; the owner's citizenship by default). The file is filed as the owner's `gov_id_front` / `gov_id_back` document (`source: client`, not verified) and handed to the identity provider as the owner's document; the owner still passes the face check by the link or the widget. The owner's applicant is created when missing. A file of another format is refused with `DOCUMENT_REJECTED`. Access: the owner of the business entity, or an owner / admin of a wallet it is linked to.
17191
+ */
17192
+ post: {
17193
+ parameters: {
17194
+ query?: never;
17195
+ header?: never;
17196
+ path: {
17197
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
17198
+ entity_id: components["parameters"]["KycFormsEntityId"];
17199
+ /** @description The `id` of a beneficial owner of the business entity — an item of `beneficial_owners` as `GET …/forms` lists it after the base form was sent (every saved item carries its `id`; `verification.owners[].id` of the overview is the same id). A person, not a company; not the owner the filler marked as themselves (`is_applicant`). */
17200
+ owner_id: components["parameters"]["KycFormsOwnerId"];
17201
+ };
17202
+ cookie?: never;
17203
+ };
17204
+ requestBody: {
17205
+ content: {
17206
+ "multipart/form-data": {
17207
+ /**
17208
+ * Format: binary
17209
+ * @description One JPEG or PNG photo, up to 20 MB.
17210
+ */
17211
+ file: string;
17212
+ /**
17213
+ * @description `back` only for a type other than `passport`.
17214
+ * @enum {string}
17215
+ */
17216
+ side: "front" | "back";
17217
+ /**
17218
+ * @description The kind of document: the codes of the form's `gov_id_type` dictionary (`PASSPORT`, `ID_CARD`, `RESIDENCE_PERMIT`, `DRIVERS`). The lowercase codes are the same kinds under their older names — `passport` = `PASSPORT`, `id_card` = `ID_CARD`, `residence_permit` = `RESIDENCE_PERMIT`, `driving_license` = `DRIVERS` — and are still taken.
17219
+ * @default PASSPORT
17220
+ * @enum {string}
17221
+ */
17222
+ type?: "PASSPORT" | "ID_CARD" | "RESIDENCE_PERMIT" | "DRIVERS" | "passport" | "id_card" | "residence_permit" | "driving_license";
17223
+ /**
17224
+ * @description Alpha-2 of the issuing country, a code the country directory knows; the owner's citizenship when omitted.
17225
+ * @example DE
17226
+ */
17227
+ country?: string;
17228
+ };
17229
+ };
17230
+ };
17231
+ responses: {
17232
+ /** @description The document as filed */
17233
+ 201: {
17234
+ headers: {
17235
+ [name: string]: unknown;
17236
+ };
17237
+ content: {
17238
+ "application/json": {
17239
+ /** @example true */
17240
+ success: boolean;
17241
+ data: {
17242
+ /**
17243
+ * Format: uuid
17244
+ * @description The `kyc_documents` row.
17245
+ */
17246
+ document_id: string;
17247
+ /** @enum {string} */
17248
+ type: "gov_id_front" | "gov_id_back";
17249
+ };
17250
+ };
17251
+ };
17252
+ };
17253
+ /** @description The errors of `KycFormsOwnerErrors`; `VALIDATION_ERROR` — a `side` or `type` outside the list, `side: back` of a passport (the default type), or a `country` that is not a known alpha-2 code; `DOCUMENT_REJECTED` — a file that is not JPEG or PNG (a PDF included), empty, or over 20 MB; `INVALID_REQUEST` — no `file` part (or more than one), or an unreadable multipart body. */
17254
+ 400: {
17255
+ headers: {
17256
+ [name: string]: unknown;
17257
+ };
17258
+ content: {
17259
+ "application/json": components["schemas"]["ErrorResponse"];
17260
+ };
17261
+ };
17262
+ 401: components["responses"]["UnauthorizedError"];
17263
+ 403: components["responses"]["KycFormsAccessDenied"];
17264
+ 404: components["responses"]["KycFormsOwnerNotFound"];
17265
+ 409: components["responses"]["KycFormsOwnerConflict"];
17266
+ /** @description `SERVICE_UNAVAILABLE` — file storage is not configured on this server, or the locking service is unavailable */
17267
+ 503: {
17268
+ headers: {
17269
+ [name: string]: unknown;
17270
+ };
17271
+ content: {
17272
+ "application/json": components["schemas"]["ErrorResponse"];
17273
+ };
17274
+ };
17275
+ };
17276
+ };
17277
+ delete?: never;
17278
+ options?: never;
17279
+ head?: never;
17280
+ patch?: never;
17281
+ trace?: never;
17282
+ };
17283
+ "/frontend/notifications/test": {
17284
+ parameters: {
17285
+ query?: never;
17286
+ header?: never;
17287
+ path?: never;
17288
+ cookie?: never;
17289
+ };
17290
+ get?: never;
17291
+ put?: never;
17292
+ /**
17293
+ * Send mock notification events (development only)
17294
+ * @description Publishes MOCK events straight to the delivery channels so a client can verify its realtime integration: `notification.created` plus a push carrier on the personal channel, and `data.changed` on the wallet channel when `wallet_id` is passed. The mock events are not stored. Additionally, when the wallet has at least one order, a REAL `ORDER_STATUS_CHANGED` notification is produced through the regular pipeline for the wallet's newest order — it lands in the inbox of every wallet member and is delivered over realtime and push (`inbox_outcome` reports the result; `null` means no order was found). Available only on development deployments.
17295
+ */
17296
+ post: {
17297
+ parameters: {
17298
+ query?: {
17299
+ /** @description Accessible wallet whose channel receives the mock `data.changed` signal */
17300
+ wallet_id?: string;
17301
+ };
17302
+ header?: never;
17303
+ path?: never;
17304
+ cookie?: never;
17305
+ };
17306
+ requestBody?: {
17307
+ content: {
17308
+ "application/json": {
17309
+ /** @description Push notification text */
17310
+ message?: string;
17311
+ };
17312
+ };
17313
+ };
17314
+ responses: {
17315
+ /** @description Mock events published */
17316
+ 200: {
17317
+ headers: {
17318
+ [name: string]: unknown;
17319
+ };
17320
+ content: {
17321
+ "application/json": {
17322
+ /** @example true */
17323
+ success?: boolean;
17324
+ data?: {
17325
+ /** Format: uuid */
17326
+ notification_id?: string;
17327
+ /** Format: uuid */
17328
+ signaled_wallet_id?: string | null;
17329
+ /**
17330
+ * @description Result of the real inbox notification; null when no wallet was passed or it has no orders
17331
+ * @enum {string|null}
17332
+ */
17333
+ inbox_outcome?: "PROCESSED" | "SKIPPED_UNRESOLVED" | "SKIPPED_DUPLICATE" | null;
17334
+ /**
17335
+ * Format: uuid
17336
+ * @description Order the real notification was built from
17337
+ */
17338
+ inbox_order_uuid?: string | null;
17339
+ };
17340
+ };
17341
+ };
17342
+ };
17343
+ 401: components["responses"]["UnauthorizedError"];
17344
+ };
17345
+ };
17346
+ delete?: never;
17347
+ options?: never;
17348
+ head?: never;
17349
+ patch?: never;
17350
+ trace?: never;
15961
17351
  };
15962
17352
  }
15963
17353
  export type webhooks = Record<string, never>;
@@ -15968,7 +17358,7 @@ export interface components {
15968
17358
  * @example EXCHANGE_OMNI
15969
17359
  * @enum {string}
15970
17360
  */
15971
- OrderTypeId: "EXCHANGE_OMNI" | "EXCHANGE_OMNI_ONRAMP" | "EXCHANGE_OMNI_OFFRAMP" | "EXCHANGE_OMNI_CRYPTO" | "EXCHANGE_CRYPTO_INTERNAL" | "L2F_ACH_ONRAMP" | "L2F_ACH_OFFRAMP" | "L2F_SEPA_ONRAMP" | "L2F_SEPA_OFFRAMP" | "L2F_SWIFT_ONRAMP" | "L2F_SWIFT_OFFRAMP" | "L2F_WIRE_ONRAMP" | "L2F_WIRE_OFFRAMP" | "L2F_CHAPS_ONRAMP" | "L2F_CHAPS_OFFRAMP" | "L2F_FPS_ONRAMP" | "L2F_FPS_OFFRAMP" | "BRL_WIRE_ONRAMP" | "BRL_WIRE_OFFRAMP" | "BRL_ACH_ONRAMP" | "BRL_ACH_OFFRAMP" | "BRL_RTP_OFFRAMP" | "DLS_WIRE_ONRAMP" | "DLS_WIRE_OFFRAMP" | "DLS_ACH_ONRAMP" | "DLS_ACH_OFFRAMP" | "DLS_SEPA_ONRAMP" | "DLS_SEPA_OFFRAMP" | "DLS_SWIFT_ONRAMP" | "DLS_SWIFT_OFFRAMP" | "BC1_SEPA_ONRAMP" | "BC1_SEPA_OFFRAMP" | "BC1_SWIFT_ONRAMP" | "BC1_SWIFT_OFFRAMP" | "BC3_SEPA_ONRAMP" | "BC3_SEPA_OFFRAMP" | "RPP_SWIFT_OFFRAMP" | "RPP_SEPA_OFFRAMP" | "RPP_FPS_OFFRAMP" | "RPP_ACH_OFFRAMP" | "OMNIBUS_CRYPTO_TRANSFER" | "OMNIBUS_CRYPTO_WITHDRAWAL" | "OMNIBUS_INTERNAL_TRANSFER" | "SEGREGATED_CRYPTO_TRANSFER" | "TRANSFER_INTERNAL" | "TRANSFER_CARD_PREPAID" | "TRANSFER_CARD_SUBACCOUNT" | "TRANSFER_CARD_WHOLESALE" | "WITHDRAW_CARD_PREPAID" | "WITHDRAW_CARD_SUBACCOUNT" | "REFUND_CARD_PREPAID" | "REFUND_CARD_SUBACCOUNT" | "RN_CARDS_OFFRAMP" | "CARD_ISSUING_FEE" | "MONTHLY_FEE" | "REFERRAL_PAYOUT";
17361
+ OrderTypeId: "EXCHANGE_OMNI" | "EXCHANGE_OMNI_ONRAMP" | "EXCHANGE_OMNI_OFFRAMP" | "EXCHANGE_OMNI_CRYPTO" | "EXCHANGE_CRYPTO_INTERNAL" | "L2F_ACH_ONRAMP" | "L2F_ACH_OFFRAMP" | "L2F_SEPA_ONRAMP" | "L2F_SEPA_OFFRAMP" | "L2F_SWIFT_ONRAMP" | "L2F_SWIFT_OFFRAMP" | "L2F_WIRE_ONRAMP" | "L2F_WIRE_OFFRAMP" | "L2F_CHAPS_ONRAMP" | "L2F_CHAPS_OFFRAMP" | "L2F_FPS_ONRAMP" | "L2F_FPS_OFFRAMP" | "BRL_WIRE_ONRAMP" | "BRL_WIRE_OFFRAMP" | "BRL_ACH_ONRAMP" | "BRL_ACH_OFFRAMP" | "BRL_FEDNOW_ONRAMP" | "BRL_RTP_OFFRAMP" | "DLS_WIRE_ONRAMP" | "DLS_WIRE_OFFRAMP" | "DLS_ACH_ONRAMP" | "DLS_ACH_OFFRAMP" | "DLS_SEPA_ONRAMP" | "DLS_SEPA_OFFRAMP" | "DLS_SWIFT_ONRAMP" | "DLS_SWIFT_OFFRAMP" | "BC1_SEPA_ONRAMP" | "BC1_SEPA_OFFRAMP" | "BC1_SWIFT_ONRAMP" | "BC1_SWIFT_OFFRAMP" | "BC3_SEPA_ONRAMP" | "BC3_SEPA_OFFRAMP" | "RPP_SWIFT_OFFRAMP" | "RPP_SEPA_OFFRAMP" | "RPP_FPS_OFFRAMP" | "RPP_ACH_OFFRAMP" | "OMNIBUS_CRYPTO_TRANSFER" | "OMNIBUS_CRYPTO_WITHDRAWAL" | "OMNIBUS_INTERNAL_TRANSFER" | "SEGREGATED_CRYPTO_TRANSFER" | "TRANSFER_INTERNAL" | "TRANSFER_CARD_PREPAID" | "TRANSFER_CARD_SUBACCOUNT" | "TRANSFER_CARD_WHOLESALE" | "WITHDRAW_CARD_PREPAID" | "WITHDRAW_CARD_SUBACCOUNT" | "REFUND_CARD_PREPAID" | "REFUND_CARD_SUBACCOUNT" | "RN_CARDS_OFFRAMP" | "CARD_ISSUING_FEE" | "MONTHLY_FEE" | "REFERRAL_PAYOUT";
15972
17362
  OrderCalculation: {
15973
17363
  /**
15974
17364
  * Format: uuid
@@ -16089,7 +17479,7 @@ export interface components {
16089
17479
  * @description Rail an order type pays through (`order_types.payment_method`)
16090
17480
  * @enum {string}
16091
17481
  */
16092
- OrderPaymentMethod: "ACH" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "RTP" | "INTERNAL" | "CARD";
17482
+ OrderPaymentMethod: "ACH" | "SWIFT" | "SEPA" | "CRYPTO_EXTERNAL" | "CRYPTO_INTERNAL" | "CHAPS" | "FPS" | "FEDWIRE" | "RTP" | "INTERNAL" | "CARD" | "FEDNOW";
16093
17483
  /** @description The tenant's markup for the order type (`tenant_order_type_rates`) */
16094
17484
  OrderTypeTenantRates: {
16095
17485
  markup_percent: number | null;
@@ -16145,18 +17535,40 @@ export interface components {
16145
17535
  documents_required_from_amount: number | null;
16146
17536
  tenant_rates: components["schemas"]["OrderTypeTenantRates"];
16147
17537
  };
17538
+ /** @description The error envelope of every non-2xx answer, whatever the status: `success` is always `false`, `error.code` is the machine-readable code to match on, `error.message` the text for people. `details` is present only when the error carries a structured payload. */
16148
17539
  ErrorResponse: {
16149
- /** @example false */
16150
- success?: boolean;
16151
- /** @description Request correlation id — quote it in support requests */
17540
+ /** @enum {boolean} */
17541
+ success: false;
17542
+ /**
17543
+ * Format: uuid
17544
+ * @description Request correlation id — quote it in support requests
17545
+ */
16152
17546
  correlationId?: string;
16153
- error?: {
16154
- code?: string;
16155
- message?: string;
17547
+ error: {
17548
+ /** @example VALIDATION_ERROR */
17549
+ code: string;
17550
+ /** @example Invalid request */
17551
+ message: string;
16156
17552
  /** @description Structured payload (validation issues, missing fields) when the error carries one */
16157
17553
  details?: Record<string, never> | null;
16158
17554
  };
16159
17555
  };
17556
+ /**
17557
+ * @description Why `POST /frontend/issuing/cards` refused the card with `400`. Nothing is debited from the wallet on such a refusal: either nothing was charged, or the charge was returned before the answer.
17558
+ * @enum {string}
17559
+ */
17560
+ CardIssuanceRefusalCode: "INITIAL_TOPUP_BELOW_MINIMUM" | "INITIAL_TOPUP_BELOW_FEE" | "INITIAL_TOPUP_BELOW_OPENING_LOAD" | "OPENING_LOAD_NOT_PAID" | "INSUFFICIENT_FUNDS" | "TENANT_FEE_NOT_CONFIGURED" | "CARDHOLDER_NOT_LINKED" | "CARDHOLDER_CARD_LIMIT_REACHED" | "CARD_VENDOR_VALIDATION" | "CARD_VENDOR_UNSUPPORTED" | "INVALID_REQUEST" | "INVALID_AMOUNT" | "MALFORMED_TRANSACTION_BATCH" | "OVERDRAFT_ORDER_TYPE" | "EXTERNAL_SERVICE_ERROR";
17561
+ CardIssuanceRefusalResponse: {
17562
+ /** @enum {boolean} */
17563
+ success: false;
17564
+ error: {
17565
+ code: components["schemas"]["CardIssuanceRefusalCode"];
17566
+ /** @description Human-readable reason; not meant for matching — use `code` */
17567
+ message: string;
17568
+ /** @description Present only on `CARDHOLDER_CARD_LIMIT_REACHED` */
17569
+ details?: Record<string, never>;
17570
+ };
17571
+ };
16160
17572
  /** @description Counterparty account (beneficiary). Wallet-scoped. */
16161
17573
  CounterpartyAccount: {
16162
17574
  /** Format: uuid */
@@ -16230,6 +17642,8 @@ export interface components {
16230
17642
  bank_name: string | null;
16231
17643
  /** @description SWIFT/BIC (ISO 9362) */
16232
17644
  swift_bic?: string | null;
17645
+ /** @description BIC of the intermediary (correspondent) bank, SWIFT payment method only; 8 or 11 characters, ISO 9362 */
17646
+ intermediary_bic?: string | null;
16233
17647
  /** @description IBAN (ISO 13616) */
16234
17648
  iban?: string | null;
16235
17649
  /** @description Sort code (6 digits, UK banking) */
@@ -16740,7 +18154,11 @@ export interface components {
16740
18154
  }[];
16741
18155
  /** @description Units of billing currency per unit of transaction currency, so `transaction_amount * conversion_rate ≈ billing_amount`. 1 when the currencies match. */
16742
18156
  conversion_rate?: number;
16743
- failure_reason?: string;
18157
+ /**
18158
+ * @description Neutral reason of a declined operation, derived from its decline code (e.g. 'Insufficient funds', 'Card spending limit exceeded'; 'Declined' when no specific reason applies). Never the card issuer's own text. Empty or null when the operation was not declined.
18159
+ * @example Insufficient funds
18160
+ */
18161
+ failure_reason?: string | null;
16744
18162
  has_receipt?: boolean;
16745
18163
  merchant?: components["schemas"]["TransactionMerchant"];
16746
18164
  /** Format: date-time */
@@ -17528,7 +18946,7 @@ export interface components {
17528
18946
  amount_to: number | null;
17529
18947
  order_type: string;
17530
18948
  /**
17531
- * @description Complete set for these routes — a failure is always `FAILED`, there is no second failure status. `EXPECTED` is a scheduled payment waiting for its `scheduled_at`; `REFUNDED` is a failed order whose funds were paid back, as opposed to `CANCELED`, where nothing ever moved.
18949
+ * @description Complete set for these routes — a failure is always `FAILED`, there is no second failure status. `EXPECTED` is a scheduled payment waiting for its `scheduled_at`; `REFUNDED` is an order whose funds moved and were paid back (a failed order refunded, or the fee and initial top-up of a card that was not issued), as opposed to `CANCELED`, where nothing ever moved.
17532
18950
  * @enum {string}
17533
18951
  */
17534
18952
  status: "NEW" | "PENDING" | "EXPECTED" | "PROCESSING" | "COMPLETE" | "FAILED" | "CANCELED" | "REFUNDED";
@@ -17885,10 +19303,10 @@ export interface components {
17885
19303
  */
17886
19304
  type: "individual" | "business" | "universal";
17887
19305
  /**
17888
- * @description KYC verification status. A refusal is one of three values: `DECLINED`, `REJECT` or `SOFT_REJECT`. Only `APPROVED` (full access) and `HOLD` (read-only) open the wallet.
19306
+ * @description KYC verification status. A refusal is one of three values: `DECLINED`, `REJECT` or `SOFT_REJECT`. Only `APPROVED` (full access) and `HOLD` (read-only) open the wallet. `OFFBOARDED` — final: the work with this company or person is over; `EXPIRED` — the verification lapsed and the client passes it again.
17889
19307
  * @enum {string}
17890
19308
  */
17891
- status: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW";
19309
+ status: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW" | "EXPIRED" | "OFFBOARDED";
17892
19310
  business_name: string | null;
17893
19311
  first_name: string | null;
17894
19312
  last_name: string | null;
@@ -17913,7 +19331,7 @@ export interface components {
17913
19331
  /** @description The wallet's application on the rail. `null` on the rail while the wallet never submitted to it. */
17914
19332
  WalletKycRailApplication: {
17915
19333
  /**
17916
- * @description `APPROVED` — onboarded. `PROCESSING` / `PENDING` — with the vendor. `HOLD` / `SOFT_REJECT` — the vendor asked for a resubmission. `WAITING_ON_REVIEW` — a manual rail waiting for compliance.
19334
+ * @description `APPROVED` — onboarded. `PROCESSING` / `PENDING` — with the vendor. `HOLD` / `SOFT_REJECT` — the vendor asked for a resubmission. `WAITING_ON_REVIEW` — a manual rail waiting for compliance. An application is never `EXPIRED` or `OFFBOARDED`: those belong to the KYC entity (`kyc_info.status`).
17917
19335
  * @enum {string}
17918
19336
  */
17919
19337
  status: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW";
@@ -17934,7 +19352,7 @@ export interface components {
17934
19352
  id: string;
17935
19353
  /** @description The rail takes submissions at all. */
17936
19354
  is_submit_available: boolean;
17937
- /** @description The wallet can submit to the rail right now: it has an onboarding implementation, is of the entity's type or universal, the entity's KYC is approved (not merely under review), and no application is approved or with the vendor. */
19355
+ /** @description The rail would take the wallet now: it has an onboarding implementation, is of the entity's type or universal, the entity's KYC is approved (not merely under review), and no application is approved or with the vendor. The rail's form is not looked at: on the KYC forms flow its state is `form_state` / `missing_required` of the rail in `GET /frontend/kyc/entities/{entity_id}/targets`, and a submission while it is not `complete` answers `400 RAIL_REQUIREMENTS_INCOMPLETE`. */
17938
19356
  can_submit: boolean;
17939
19357
  /** @description The rail's active terms, in display order. */
17940
19358
  terms_and_conditions: components["schemas"]["WalletKycRailTerms"][];
@@ -17971,7 +19389,7 @@ export interface components {
17971
19389
  created_at: string;
17972
19390
  /**
17973
19391
  * Format: uuid
17974
- * @description KYC entity the wallet was opened for (`GET /kyc/entities`). `null` for a wallet created without one.
19392
+ * @description KYC entity the wallet was opened for: `GET /frontend/kyc/entities` on a tenant of the KYC forms flow, the BFF `GET /kyc/entities` on the old flow. `null` for a wallet created without one.
17975
19393
  */
17976
19394
  kyc_entity_id: string | null;
17977
19395
  kyc_info: components["schemas"]["WalletKycInfo"] | null;
@@ -18022,7 +19440,7 @@ export interface components {
18022
19440
  created_at: string;
18023
19441
  /**
18024
19442
  * Format: uuid
18025
- * @description KYC entity the wallet was opened for (`GET /kyc/entities`). `null` for a wallet created without one.
19443
+ * @description KYC entity the wallet was opened for: `GET /frontend/kyc/entities` on a tenant of the KYC forms flow, the BFF `GET /kyc/entities` on the old flow. `null` for a wallet created without one.
18026
19444
  */
18027
19445
  kyc_entity_id: string | null;
18028
19446
  kyc_info: components["schemas"]["WalletKycInfo"] | null;
@@ -18505,11 +19923,17 @@ export interface components {
18505
19923
  /** Format: uuid */
18506
19924
  id: string;
18507
19925
  /** @enum {string} */
18508
- type: "DEPOSIT_RECEIVED" | "DEPOSIT_NOT_ACCEPTED" | "TRANSFER_RECEIVED" | "ORDER_STATUS_CHANGED" | "KYC_STATUS_CHANGED" | "ANNOUNCEMENT" | "SYSTEM_MESSAGE" | "MASS_PAYOUT_STATUS_CHANGED" | "CARD_OTP" | "RFI_REQUESTED" | "RFI_RESOLVED" | "REPORT_READY" | "SCHEDULED_PAYMENT_REMINDER" | "SCHEDULED_PAYMENT_LOW_BALANCE" | "SCHEDULED_PAYMENT_APPROVAL_REQUIRED";
19926
+ type: "DEPOSIT_RECEIVED" | "DEPOSIT_NOT_ACCEPTED" | "TRANSFER_RECEIVED" | "ORDER_STATUS_CHANGED" | "KYC_STATUS_CHANGED" | "ANNOUNCEMENT" | "SYSTEM_MESSAGE" | "MASS_PAYOUT_STATUS_CHANGED" | "CARD_OTP" | "RFI_REQUESTED" | "RFI_RESOLVED" | "REPORT_READY" | "SCHEDULED_PAYMENT_REMINDER" | "SCHEDULED_PAYMENT_LOW_BALANCE" | "SCHEDULED_PAYMENT_APPROVAL_REQUIRED" | "SCHEDULED_PAYMENT_APPROVAL_CLOSING" | "WALLET_INACTIVITY";
19927
+ /** @description Title of the item, rendered server-side from `payload` with the same template as the push and Telegram copy. `null` when the type has no texts (historical `CARD_OTP` rows) or when the texts could not be built from `payload`. */
19928
+ title: string | null;
19929
+ /** @description Text of the item, rendered like `title`; `null` in the same cases. */
19930
+ body: string | null;
18509
19931
  /** @description Structured fact snapshot; the client renders the presentation. Shape depends on `type`; evolution is additive-only. */
18510
19932
  payload: Record<string, never>;
18511
19933
  /** Format: uuid */
18512
19934
  wallet_id: string | null;
19935
+ /** @description The wallet's current display name (what `GET /frontend/wallets` returns as `display_name`), resolved when the item is read, so it follows a rename. `null` for notifications not scoped to a wallet, for a wallet the user can no longer access (the inbox keeps the notifications of a wallet the user has left) and for a wallet that no longer exists. */
19936
+ wallet_name: string | null;
18513
19937
  /** Format: date-time */
18514
19938
  read_at: string | null;
18515
19939
  /** Format: date-time */
@@ -18805,150 +20229,945 @@ export interface components {
18805
20229
  /** Format: uuid */
18806
20230
  id: string;
18807
20231
  /**
18808
- * @description Human-facing id — quoted in the notification email
18809
- * @example RFI-000042
20232
+ * @description Human-facing id — quoted in the notification email
20233
+ * @example RFI-000042
20234
+ */
20235
+ reference: string;
20236
+ /**
20237
+ * @description `onboarding` — questions during verification (KYC / KYB); `transaction` — questions about specific transactions; `ongoing` — a periodic review of an active client. The list may grow: a new value is added here and announced in the changelog before any request carries it.
20238
+ * @enum {string}
20239
+ */
20240
+ type: "onboarding" | "transaction" | "ongoing";
20241
+ /**
20242
+ * @description What the request is about — the subject compliance wrote when opening it. Show it as is above the conversation; `messages` hold the question itself.
20243
+ * @example Incoming payments of $10,970 and $7,500
20244
+ */
20245
+ subject: string;
20246
+ /**
20247
+ * @description `action_required` — compliance asked and waits for the client; `awaiting_compliance` — the client answered, compliance is reviewing; `closed` — no longer accepts replies.
20248
+ * @enum {string}
20249
+ */
20250
+ status: "action_required" | "awaiting_compliance" | "closed";
20251
+ /**
20252
+ * Format: date-time
20253
+ * @description When the answer is due. The date is set each time the request is handed to the client: when it is opened, and again on every new round — compliance asks after the client answered. A further message from compliance while the answer is still awaited keeps the date.
20254
+ */
20255
+ due_at: string | null;
20256
+ /** @description True only while `action_required` and past `due_at` (red banner) */
20257
+ overdue: boolean;
20258
+ /** @description True while the request keeps one of its transactions on hold — the one marked `held` in `transactions`. Decided when the request is opened and never turned on later: only a `transaction` request holds, and only when one of the transactions it covers was frozen by compliance at that moment. A request holds at most one transaction. The hold ends when the request closes — compliance's decision lets the transaction through or fails it — and the flag is false from then on. */
20259
+ holds_transaction: boolean;
20260
+ /** @description The account is on hold while the request is open */
20261
+ holds_account: boolean;
20262
+ /** @description How many transactions the request covers */
20263
+ transactions_count: number;
20264
+ /** @description The last message of the conversation, for the card — null while nothing is visible yet */
20265
+ last_message: {
20266
+ /** @enum {string} */
20267
+ author: "compliance" | "client";
20268
+ /** @description One line of the message, up to 140 characters, cut at a word; null when the message has no text — an answer of files only */
20269
+ preview: string | null;
20270
+ /** Format: date-time */
20271
+ created_at: string;
20272
+ } | null;
20273
+ /** Format: date-time */
20274
+ created_at: string;
20275
+ /** Format: date-time */
20276
+ updated_at: string;
20277
+ /** Format: date-time */
20278
+ closed_at: string | null;
20279
+ };
20280
+ RfiAttachment: {
20281
+ /** Format: uuid */
20282
+ id: string;
20283
+ file_name: string;
20284
+ /** @description The type the file's content proves (for files sent in the app); null only on some files that came by email */
20285
+ content_type: string | null;
20286
+ size_bytes: number | null;
20287
+ /** Format: date-time */
20288
+ created_at: string;
20289
+ };
20290
+ RfiMessage: {
20291
+ /** Format: uuid */
20292
+ id: string;
20293
+ /**
20294
+ * @description Which side wrote the message. The analyst is never named — show a placeholder (e.g. "Compliance team") for `compliance` and "You" for `client`.
20295
+ * @enum {string}
20296
+ */
20297
+ author: "compliance" | "client";
20298
+ /** @description The text of the message. An empty string when the client answered with files only — show the attachments alone. */
20299
+ body: string;
20300
+ attachments: components["schemas"]["RfiAttachment"][];
20301
+ /** Format: date-time */
20302
+ created_at: string;
20303
+ };
20304
+ RfiTransaction: {
20305
+ order_uuid: string;
20306
+ order_type: string | null;
20307
+ status: string | null;
20308
+ amount_from: number | null;
20309
+ amount_to: number | null;
20310
+ /** Format: date-time */
20311
+ created_at: string | null;
20312
+ /** @description True for the one transaction the request keeps on hold while it is open (see `holds_transaction`). False for every other transaction, and for all of them once the request is closed. */
20313
+ held: boolean;
20314
+ };
20315
+ RfiCaseDetail: components["schemas"]["RfiCase"] & {
20316
+ /** @description Whether YOU may answer this request now: it is open (`action_required` or `awaiting_compliance`) and your role on the account writes — `owner` or `admin`. False on a closed request and for an `auditor`, who reads the conversation only: show it read-only, without the answer box. Otherwise `POST …/messages` answers 409 `RFI_CLOSED` or 403 `ACCESS_DENIED` respectively. */
20317
+ can_reply: boolean;
20318
+ /** @description The conversation, oldest first */
20319
+ messages: components["schemas"]["RfiMessage"][];
20320
+ /** @description Every transaction the request covers, in the order compliance linked them. For the full table (currencies, paging) open the order list with `filters=[{"rfi_case_id":"<id>"}]`. */
20321
+ transactions: components["schemas"]["RfiTransaction"][];
20322
+ };
20323
+ WalletKycRailResponse: {
20324
+ /** @example true */
20325
+ success: boolean;
20326
+ data: components["schemas"]["WalletKycRail"];
20327
+ };
20328
+ /** @description The error envelope of a rail submission: `ErrorResponse`, with `details` only on `RAIL_REQUIREMENTS_INCOMPLETE`. */
20329
+ WalletKycRailSubmitErrorResponse: components["schemas"]["ErrorResponse"] & {
20330
+ error?: {
20331
+ /** @description `RAIL_REQUIREMENTS_INCOMPLETE` only (absent on every other code): `fields` lists the keys of the required fields of the rail's form with nothing saved in the KYC entity yet, in form order — the `key` of the fields `GET /frontend/kyc/entities/{entity_id}/forms?rails={rail_id}` answers (`address.city`, `document.proof_of_address`, `beneficial_owners`, …). Open that form and highlight them; a draft or a submission still in review does not count until it is applied. */
20332
+ details?: {
20333
+ /** @example [
20334
+ * "expected_monthly_volume",
20335
+ * "document.proof_of_address"
20336
+ * ] */
20337
+ fields: string[];
20338
+ } | null;
20339
+ };
20340
+ };
20341
+ /**
20342
+ * @description Raw application status of the KYC entity (`kyc_entity.status`) — the same value the wallet shows as `kyc_info.status` (`WalletKycInfo`); a rail application (`wallet_rail.status`) has its own status of the same set. Build screens by the overview `stage`, not by this value: a status can be added without a release. `PROCESSING` is not set by the forms flow — a vendor sync of the old flow leaves it on an entity — and the overview answers `stage: unknown` for it, as for any status it does not know. `EXPIRED` (a lapsed verification; nothing sets it yet) and `OFFBOARDED` (compliance ended the relationship; final) are set in CORE, never by the identity provider, and no form or provider event moves them — but one: an `EXPIRED` application whose applicant passes the identity check again goes on to its owners (`WAITING_ON_UBOS`) or to compliance (`WAITING_ON_REVIEW`).
20343
+ * @enum {string}
20344
+ */
20345
+ KycFormsEntityStatus: "UNVERIFIED" | "PENDING" | "PROCESSING" | "WAITING_ON_REVIEW" | "WAITING_ON_UBOS" | "NEEDS_ATTENTION" | "HOLD" | "APPROVED" | "SOFT_REJECT" | "REJECT" | "DECLINED" | "DOUBLE" | "EXPIRED" | "OFFBOARDED";
20346
+ /**
20347
+ * @description State of one form. `draft` — a draft with values or files exists (checked first, even when everything is already saved); `complete` — every required visible field has a saved value (also when the form has none); `in_review` — nothing is left to fill, the rest of the required values wait in a sent submission of this or another form (`awaiting_verification` or `in_review`: the identity check or compliance still has to let them through into the KYC entity); `not_started` — otherwise.
20348
+ * @enum {string}
20349
+ */
20350
+ KycFormsFormState: "not_started" | "draft" | "in_review" | "complete";
20351
+ /**
20352
+ * @description State of an identity check, computed on every read. `not_started` — no applicant yet; `in_progress` — the check is set up with the identity provider and not finished: the widget may not have been opened yet (an owner whose check the background set up), be open, or the document was handed over and the face is due; `in_review` — the identity provider is looking (also right after a row nobody has read yet, and for an owner whose declared data does not match the document); `passed`; `retry` — the provider asks to go again, call the session route for a new token; `failed` — a final refusal (the application is not rejected by it: it goes to compliance, so build a refusal screen by this value, not by `stage`).
20353
+ * @enum {string}
20354
+ */
20355
+ KycFormsVerificationState: "not_started" | "in_progress" | "in_review" | "passed" | "retry" | "failed";
20356
+ /**
20357
+ * @description A KYC entity as `GET /kyc/entities` of the BFF has always answered it: the `kyc_entity` columns plus `address`, `physical_address`, `beneficial_owners` and `documents`. Additional properties are the entity columns.
20358
+ * @example {
20359
+ * "id": "5e6f7081-9203-4b4c-8d5e-6f708192a3b4",
20360
+ * "user_data_uuid": "1a2b3c4d-5e6f-4708-9192-a3b4c5d6e7f8",
20361
+ * "type": "individual",
20362
+ * "status": "UNVERIFIED",
20363
+ * "created_at": "2026-10-19T09:00:00Z",
20364
+ * "address": null,
20365
+ * "physical_address": null,
20366
+ * "beneficial_owners": [],
20367
+ * "documents": []
20368
+ * }
20369
+ */
20370
+ KycFormsEntity: {
20371
+ /** Format: uuid */
20372
+ id: string;
20373
+ /**
20374
+ * Format: uuid
20375
+ * @description The owner of the entity.
20376
+ */
20377
+ user_data_uuid: string;
20378
+ /** @enum {string} */
20379
+ type: "individual" | "business";
20380
+ status: components["schemas"]["KycFormsEntityStatus"];
20381
+ /** Format: date-time */
20382
+ created_at: string;
20383
+ /** @description Registered address (`kyc_address` columns, `country` joined). */
20384
+ address: {
20385
+ [key: string]: unknown;
20386
+ } | null;
20387
+ /** @description Business address of a company when it differs from the registered one. */
20388
+ physical_address: {
20389
+ [key: string]: unknown;
20390
+ } | null;
20391
+ /** @description The `kyc_beneficial_owner` rows of a business entity with their `address`; empty for a personal entity. The `id` of a row is the `owner_id` of the owner routes. */
20392
+ beneficial_owners: {
20393
+ [key: string]: unknown;
20394
+ }[];
20395
+ documents: {
20396
+ /** Format: uuid */
20397
+ id: string;
20398
+ /** Format: uuid */
20399
+ kyc_entity_id: string;
20400
+ /**
20401
+ * Format: uuid
20402
+ * @description The beneficial owner the document belongs to; null for the entity's own document.
20403
+ */
20404
+ ubo_id: string | null;
20405
+ /** @example proof_of_address */
20406
+ type: string;
20407
+ /** Format: uri */
20408
+ link: string;
20409
+ /** Format: date */
20410
+ issuance_date: string | null;
20411
+ /** Format: date */
20412
+ expiration_date: string | null;
20413
+ /**
20414
+ * @description `client` — uploaded through a form; `kyc_provider` — filed from the identity check.
20415
+ * @enum {string}
20416
+ */
20417
+ source: "backfill" | "panel" | "admin_api" | "kyc_provider" | "bff" | "client";
20418
+ /** Format: uuid */
20419
+ batch_id: string;
20420
+ position: number;
20421
+ /** Format: date-time */
20422
+ created_at: string;
20423
+ }[];
20424
+ } & {
20425
+ [key: string]: unknown;
20426
+ };
20427
+ KycFormsCreateEntityRequest: {
20428
+ /**
20429
+ * @description Individual is idempotent: the caller's personal entity is returned when it exists. A business entity is created on every call. The type must be enabled for the tenant, else `403 ACCESS_DENIED`.
20430
+ * @enum {string}
20431
+ */
20432
+ type: "individual" | "business";
20433
+ };
20434
+ /** @description The newest sent submission of the form (never a draft); null when none was sent. */
20435
+ KycFormsSubmission: {
20436
+ /** Format: uuid */
20437
+ id: string;
20438
+ /**
20439
+ * @description `awaiting_verification` — sent, the identity document and face are still needed; `in_review` — compliance decides; `returned` — sent back with `comment`, the form is open again; `approved` / `rejected` — compliance decided (an approval does not set the application status by itself); `applied` — the answers are written into the KYC entity.
20440
+ * @enum {string}
20441
+ */
20442
+ status: "awaiting_verification" | "in_review" | "returned" | "approved" | "rejected" | "applied";
20443
+ /** @description Compliance comment of a returned or rejected submission. */
20444
+ comment: string | null;
20445
+ } | null;
20446
+ /** @description One rule: the value of another field of the form (inside a list item — of the same item) compared with `value`. */
20447
+ KycFormsConditionRule: {
20448
+ /** @example expected_monthly_volume */
20449
+ field: string;
20450
+ /**
20451
+ * @description `eq` / `neq` / `in` — for a multi value the match is any chosen value; an empty value (null, empty string, empty array) matches only null. `gt` / `gte` / `lt` / `lte` — numbers, `YYYY-MM-DD` dates (by the day), or an `enum` field: the `numeric` of the chosen option is compared; an empty value or an option without `numeric` fails the rule. `filled` — the value is not empty when `value` is absent or `true`; with `value: false` the rule holds when the value IS empty.
20452
+ * @enum {string}
20453
+ */
20454
+ op: "eq" | "neq" | "in" | "gt" | "gte" | "lt" | "lte" | "filled";
20455
+ /** @description A literal or a list of literals, never a reference to another field. For `filled` it is absent or a boolean: absent / `true` — the field must be filled, `false` — it must be empty. */
20456
+ value?: (string | number | boolean | (string | number | boolean)[]) | null;
20457
+ };
20458
+ KycFormsConditionAll: {
20459
+ /** @description Holds when every condition does. */
20460
+ all: components["schemas"]["KycFormsCondition"][];
20461
+ };
20462
+ KycFormsConditionAny: {
20463
+ /** @description Holds when any of the conditions does. */
20464
+ any: components["schemas"]["KycFormsCondition"][];
20465
+ };
20466
+ /**
20467
+ * @description A show condition: a rule, or `{ all: [...] }` / `{ any: [...] }` of conditions. Evaluate it on the client against the current values on every change (see `visible_when` of the field).
20468
+ * @example {
20469
+ * "all": [
20470
+ * {
20471
+ * "field": "purpose",
20472
+ * "op": "eq",
20473
+ * "value": "other"
20474
+ * },
20475
+ * {
20476
+ * "field": "expected_monthly_volume",
20477
+ * "op": "gte",
20478
+ * "value": 25000
20479
+ * }
20480
+ * ]
20481
+ * }
20482
+ */
20483
+ KycFormsCondition: components["schemas"]["KycFormsConditionRule"] | components["schemas"]["KycFormsConditionAll"] | components["schemas"]["KycFormsConditionAny"];
20484
+ /** @description A file of a file field as `values` lists it. */
20485
+ KycFormsFileValue: {
20486
+ /**
20487
+ * Format: uuid
20488
+ * @description For a file in the draft the `upload_id` of the delete route.
20489
+ */
20490
+ id: string;
20491
+ file_name: string | null;
20492
+ /** Format: date-time */
20493
+ uploaded_at: string;
20494
+ /** @description false — in the draft, deletable; true — already a KYC document, never removed here. */
20495
+ saved: boolean;
20496
+ };
20497
+ /**
20498
+ * @description One item of a `list` field (`beneficial_owners`): an object keyed by the `item.fields[].key` of the field, each value shaped by that item field's `type` (an item field never takes files). `id` is set on a row already saved in the KYC entity (for an owner, the `owner_id` of the owner routes); send it back to keep the row, leave it out for a new one.
20499
+ * @example {
20500
+ * "id": "2d7c1b9e-4f30-4a8c-9e21-7b6a5c4d3e2f",
20501
+ * "owner_type": "individual",
20502
+ * "first_name": "Anna",
20503
+ * "last_name": "Berg",
20504
+ * "role": "UBO",
20505
+ * "share_proportion": 40,
20506
+ * "is_applicant": false,
20507
+ * "invite_by_email": true,
20508
+ * "email": "anna@example.com"
20509
+ * }
20510
+ */
20511
+ KycFormsListItemValue: {
20512
+ /**
20513
+ * Format: uuid
20514
+ * @description The saved row; absent on an item that is not saved yet.
20515
+ */
20516
+ id?: string;
20517
+ } & {
20518
+ [key: string]: unknown;
20519
+ };
20520
+ /** @description The value of one field in `values`, shaped by the field's `type`: `text`, `textarea`, `email`, `phone` (E.164), `date` (`YYYY-MM-DD`), `enum` (an `options[].value`), `country` (alpha-2) — a string; `number`, `integer` — a number; `bool`, `consent` — a boolean; `multi_enum`, `country_multi` — an array of strings; `file` — an array of `KycFormsFileValue`; `list` — an array of `KycFormsListItemValue`. Empty is null. */
20521
+ KycFormsFieldValue: (string | number | boolean | string[] | components["schemas"]["KycFormsFileValue"][] | components["schemas"]["KycFormsListItemValue"][]) | null;
20522
+ /** @description The value of one open field in the draft or the submission, shaped by the field's `type` as `KycFormsFieldValue` — except a `file` field, whose files travel through the uploads routes only (its key is refused with `FORM_FIELD_NOT_ALLOWED`). `null` clears the field. */
20523
+ KycFormsAnswerValue: (string | number | boolean | string[] | components["schemas"]["KycFormsListItemValue"][]) | null;
20524
+ KycFormsField: {
20525
+ /**
20526
+ * @description Stable key in the API: `email`, `address.city`, `physical_address.city`, `document.proof_of_address`, `beneficial_owners` (a list).
20527
+ * @example purpose_other
20528
+ */
20529
+ key: string;
20530
+ /**
20531
+ * @description The control, and the shape of the value in `values` and in the draft: `text`, `textarea`, `email` — string; `phone` — E.164 string; `number`, `integer` — number; `date` — `YYYY-MM-DD`; `bool` — boolean; `consent` — only `true` is accepted; `enum` — one `options[].value`; `multi_enum` — an array of them; `country` — alpha-2; `country_multi` — an array of alpha-2; `file` — files travel through the uploads routes, `values` lists them as `KycFormsFileValue`; `list` — an array of items, each an object keyed by `item.fields[].key` (plus `id` for a saved row).
20532
+ * @enum {string}
20533
+ */
20534
+ type: "text" | "textarea" | "number" | "integer" | "date" | "bool" | "consent" | "enum" | "multi_enum" | "country" | "country_multi" | "email" | "phone" | "file" | "list";
20535
+ label: string;
20536
+ hint: string | null;
20537
+ placeholder: string | null;
20538
+ /** @description Required while the field is shown; a hidden field is neither required nor accepted. */
20539
+ required: boolean;
20540
+ /** @description The purposes of the form that require the field, in form order: `{ scope: base }`, `{ scope: rail, id }`, `{ scope: card, id }` — for a field shown on a condition, the purposes whose settings require it while shown. Empty for an optional field. */
20541
+ required_by: {
20542
+ /** @enum {string} */
20543
+ scope: "base" | "rail" | "card";
20544
+ /**
20545
+ * Format: uuid
20546
+ * @description The rail or program id; null for the base form.
20547
+ */
20548
+ id: string | null;
20549
+ }[];
20550
+ /** @description A locked field is shown with its value and not accepted by the draft or the submission. */
20551
+ locked: boolean;
20552
+ /**
20553
+ * @description Why the field is locked; null when it is not. `saved` — the value is already in the KYC entity, only compliance changes it; `from_document` — taken from the verified identity document; `pending` — the value waits in a submission of this or another form of the entity: shown, locked, not asked again; `status` — the whole form is read-only by the application status.
20554
+ * @enum {string|null}
20555
+ */
20556
+ lock_reason: "saved" | "from_document" | "pending" | "status" | null;
20557
+ /** @description When the field is shown; null — always. The conditions come from the tenant's form settings and change without a release: evaluate `visible_when` against the current values on every change, and treat `required` as "required while shown" — a hidden field is neither required nor accepted. In a list item it combines the item structure (a person or a company, the filler's own item) with the settings. */
20558
+ visible_when: components["schemas"]["KycFormsCondition"] | null;
20559
+ /** @description Rules checked on submit (the draft checks the type only); null — none. `min` / `max` are numbers, or `YYYY-MM-DD` for a date; the text of a broken rule is the matching `form.messages` entry (`{value}` stands for the bound) or the `message` of a pattern. */
20560
+ validation: {
20561
+ min?: number | string;
20562
+ max?: number | string;
20563
+ min_length?: number;
20564
+ max_length?: number;
20565
+ patterns?: {
20566
+ regex: string;
20567
+ message: string;
20568
+ }[];
20569
+ } | null;
20570
+ /** @description `enum` and `multi_enum`: the values the field takes, in display order. `country` and `country_multi`: the countries the field takes — `value` alpha-2, `label` the full name (English), by name; each country field carries its own list (it may be narrowed per field later), send only a `value` from it. No other type has options. */
20571
+ options?: {
20572
+ value: string;
20573
+ label: string;
20574
+ /**
20575
+ * @description The number the option stands for in a `gt` / `gte` / `lt` / `lte` condition — a volume range carries its upper bound. Present only on the options of a dictionary that gives numbers: compare it with the condition's `value` to evaluate `visible_when` on an `enum` field.
20576
+ * @example 50000
20577
+ */
20578
+ numeric?: number;
20579
+ }[];
20580
+ /** @description `file` fields only. */
20581
+ file?: {
20582
+ max_files: number;
20583
+ /** @example 20 */
20584
+ max_size_mb: number;
20585
+ /** @description MIME types the field takes, told by the bytes. The photos of the identity document (`gov_id_front`, `gov_id_back`) take JPEG and PNG only; other document fields also take `application/pdf`. */
20586
+ accept: string[];
20587
+ };
20588
+ /** @description List fields only: the fields of one item, and the bounds of the list. */
20589
+ item?: {
20590
+ /** @description The fields of one item with their own `required`, `required_by` and `visible_when`; a `visible_when` inside an item reads the other fields of the same item. */
20591
+ fields: components["schemas"]["KycFormsField"][];
20592
+ min_items: number;
20593
+ max_items: number;
20594
+ add_label: string;
20595
+ };
20596
+ };
20597
+ KycFormsForm: {
20598
+ /**
20599
+ * @description What the form is for: the base form, a rail, a card program (`card`), or one form over several rails and programs (`multi`).
20600
+ * @enum {string}
18810
20601
  */
18811
- reference: string;
20602
+ scope: "base" | "rail" | "card" | "multi";
20603
+ /** @description The rails the form is built for; empty for the base form. */
20604
+ rails: string[];
20605
+ /** @description The card programs the form is built for; empty for the base form. */
20606
+ programs: string[];
18812
20607
  /**
18813
- * @description `onboarding` — questions during verification (KYC / KYB); `transaction` — questions about specific transactions; `ongoing` — a periodic review of an active client. The list may grow: a new value is added here and announced in the changelog before any request carries it.
18814
- * @enum {string}
20608
+ * Format: uuid
20609
+ * @description The wallet the form is built for: the `wallet_id` of the query for a form over card programs or rails; otherwise the entity's first linked wallet (main wallet first), null when the entity is linked to none. The draft and the submission carry it.
18815
20610
  */
18816
- type: "onboarding" | "transaction" | "ongoing";
20611
+ wallet_id: string | null;
20612
+ /** @enum {string} */
20613
+ entity_type: "individual" | "business";
18817
20614
  /**
18818
- * @description What the request is about — the subject compliance wrote when opening it. Show it as is above the conversation; `messages` hold the question itself.
18819
- * @example Incoming payments of $10,970 and $7,500
20615
+ * @description The language the texts are in (English when the requested one is not in the tenant's list).
20616
+ * @example en
18820
20617
  */
18821
- subject: string;
20618
+ locale: string;
18822
20619
  /**
18823
- * @description `action_required` — compliance asked and waits for the client; `awaiting_compliance` — the client answered, compliance is reviewing; `closed` — no longer accepts replies.
18824
- * @enum {string}
20620
+ * @description Hash of the form composition (keys, requiredness, conditions, list item fields; not the texts); echo it back in the draft and the submission. It can change between the load and the send: `409 FORM_OUTDATED`.
20621
+ * @example b3f1c2a9
18825
20622
  */
18826
- status: "action_required" | "awaiting_compliance" | "closed";
20623
+ schema_version: string;
20624
+ state: components["schemas"]["KycFormsFormState"];
20625
+ submission: components["schemas"]["KycFormsSubmission"];
20626
+ /** @description false while the application status (HOLD, REJECT, DECLINED, DOUBLE) makes the whole form read-only, or while the last submission of the form waits on the verification or the review. Then the draft and a new submission answer 409 FORM_LOCKED; an upload answers 409 FORM_LOCKED while a submission waits, and 400 FORM_FIELD_NOT_ALLOWED under the status lock (every field is locked with `status`). */
20627
+ editable: boolean;
20628
+ /** @description How many required visible fields are still empty (saved, pending and draft values together). */
20629
+ missing_required: number;
18827
20630
  /**
18828
- * Format: date-time
18829
- * @description When the answer is due. The date is set each time the request is handed to the client: when it is opened, and again on every new round — compliance asks after the client answered. A further message from compliance while the answer is still awaited keeps the date.
20631
+ * @description General validation messages by code (`required`, `min`, `max`, `min_length`, `max_length`, `invalid`); `{value}` stands for the bound.
20632
+ * @example {
20633
+ * "required": "This field is required",
20634
+ * "min": "The value must be at least {value}",
20635
+ * "invalid": "Check the value"
20636
+ * }
18830
20637
  */
18831
- due_at: string | null;
18832
- /** @description True only while `action_required` and past `due_at` (red banner) */
18833
- overdue: boolean;
18834
- /** @description True while the request keeps one of its transactions on hold — the one marked `held` in `transactions`. Decided when the request is opened and never turned on later: only a `transaction` request holds, and only when one of the transactions it covers was frozen by compliance at that moment. A request holds at most one transaction. The hold ends when the request closes — compliance's decision lets the transaction through or fails it — and the flag is false from then on. */
18835
- holds_transaction: boolean;
18836
- /** @description The account is on hold while the request is open */
18837
- holds_account: boolean;
18838
- /** @description How many transactions the request covers */
18839
- transactions_count: number;
18840
- /** @description The last message of the conversation, for the card — null while nothing is visible yet */
18841
- last_message: {
18842
- /** @enum {string} */
18843
- author: "compliance" | "client";
18844
- /** @description One line of the message, up to 140 characters, cut at a word; null when the message has no text — an answer of files only */
18845
- preview: string | null;
18846
- /** Format: date-time */
18847
- created_at: string;
18848
- } | null;
18849
- /** Format: date-time */
18850
- created_at: string;
18851
- /** Format: date-time */
18852
- updated_at: string;
18853
- /** Format: date-time */
18854
- closed_at: string | null;
20638
+ messages: {
20639
+ [key: string]: string;
20640
+ };
20641
+ /** @description The groups to draw, in order; each field is in exactly one section. */
20642
+ sections: {
20643
+ /** @example purpose */
20644
+ key: string;
20645
+ title: string;
20646
+ description: string | null;
20647
+ fields: components["schemas"]["KycFormsField"][];
20648
+ }[];
18855
20649
  };
18856
- RfiAttachment: {
18857
- /** Format: uuid */
18858
- id: string;
18859
- file_name: string;
18860
- /** @description The type the file's content proves (for files sent in the app); null only on some files that came by email */
18861
- content_type: string | null;
18862
- size_bytes: number | null;
18863
- /** Format: date-time */
18864
- created_at: string;
20650
+ KycFormsFormResponse: {
20651
+ /** @example true */
20652
+ success: boolean;
20653
+ data: {
20654
+ form: components["schemas"]["KycFormsForm"];
20655
+ /**
20656
+ * @description Current value per field key (saved in KYC first, then pending, then the draft), each shaped by the field's `type` (`KycFormsFieldValue`): strings, numbers, booleans, `YYYY-MM-DD` dates, alpha-2 countries, arrays of strings; files as `KycFormsFileValue[]`; lists as `KycFormsListItemValue[]` with an `id` on saved rows. Every field of the form has a key here; empty is null.
20657
+ * @example {
20658
+ * "email": "user@example.com",
20659
+ * "citizenship": "DE",
20660
+ * "gov_id_front": [
20661
+ * {
20662
+ * "id": "3f2a9c1e-5b7d-4e0a-9c11-2d8f6a4b7e90",
20663
+ * "file_name": "front.jpg",
20664
+ * "uploaded_at": "2026-10-19T09:30:00Z",
20665
+ * "saved": false
20666
+ * }
20667
+ * ],
20668
+ * "phone": null
20669
+ * }
20670
+ */
20671
+ values: {
20672
+ [key: string]: components["schemas"]["KycFormsFieldValue"];
20673
+ };
20674
+ };
18865
20675
  };
18866
- RfiMessage: {
18867
- /** Format: uuid */
18868
- id: string;
20676
+ KycFormsAnswersRequest: {
18869
20677
  /**
18870
- * @description Which side wrote the message. The analyst is never named — show a placeholder (e.g. "Compliance team") for `compliance` and "You" for `client`.
18871
- * @enum {string}
20678
+ * @description `form.schema_version` of the form as loaded.
20679
+ * @example b3f1c2a9
18872
20680
  */
18873
- author: "compliance" | "client";
18874
- /** @description The text of the message. An empty string when the client answered with files only — show the attachments alone. */
18875
- body: string;
18876
- attachments: components["schemas"]["RfiAttachment"][];
18877
- /** Format: date-time */
18878
- created_at: string;
20681
+ schema_version: string;
20682
+ /**
20683
+ * @description Values of open visible fields only, by key (keys 1–120 characters), each shaped by the field's `type` (`KycFormsAnswerValue`), the whole set every time: the draft is replaced as a whole. Any other key (unknown, locked, hidden, a file field) refuses the whole request with `FORM_FIELD_NOT_ALLOWED` — except a field hidden only because a source of its condition is empty (and required) or wrong: then `VALIDATION_ERROR` names the source and the value is dropped. Files travel through the uploads routes, never here.
20684
+ * @default {}
20685
+ * @example {
20686
+ * "email": "user@example.com",
20687
+ * "citizenship": "DE"
20688
+ * }
20689
+ */
20690
+ values: {
20691
+ [key: string]: components["schemas"]["KycFormsAnswerValue"];
20692
+ };
18879
20693
  };
18880
- RfiTransaction: {
18881
- order_uuid: string;
18882
- order_type: string | null;
18883
- status: string | null;
18884
- amount_from: number | null;
18885
- amount_to: number | null;
18886
- /** Format: date-time */
18887
- created_at: string | null;
18888
- /** @description True for the one transaction the request keeps on hold while it is open (see `holds_transaction`). False for every other transaction, and for all of them once the request is closed. */
18889
- held: boolean;
20694
+ KycFormsDraftSaved: {
20695
+ /** @example true */
20696
+ success: boolean;
20697
+ data: {
20698
+ state: components["schemas"]["KycFormsFormState"];
20699
+ missing_required: number;
20700
+ };
18890
20701
  };
18891
- RfiCaseDetail: components["schemas"]["RfiCase"] & {
18892
- /** @description Whether YOU may answer this request now: it is open (`action_required` or `awaiting_compliance`) and your role on the account writes — `owner` or `admin`. False on a closed request and for an `auditor`, who reads the conversation only: show it read-only, without the answer box. Otherwise `POST …/messages` answers 409 `RFI_CLOSED` or 403 `ACCESS_DENIED` respectively. */
18893
- can_reply: boolean;
18894
- /** @description The conversation, oldest first */
18895
- messages: components["schemas"]["RfiMessage"][];
18896
- /** @description Every transaction the request covers, in the order compliance linked them. For the full table (currencies, paging) open the order list with `filters=[{"rfi_case_id":"<id>"}]`. */
18897
- transactions: components["schemas"]["RfiTransaction"][];
20702
+ KycFormsUploadedFile: {
20703
+ /** @example true */
20704
+ success: boolean;
20705
+ data: {
20706
+ /**
20707
+ * Format: uuid
20708
+ * @description The `upload_id` of the delete route.
20709
+ */
20710
+ id: string;
20711
+ file_name: string;
20712
+ /** Format: date-time */
20713
+ uploaded_at: string;
20714
+ /**
20715
+ * @description false: in the draft, deletable; it becomes a KYC document when the submission is applied.
20716
+ * @example false
20717
+ */
20718
+ saved: boolean;
20719
+ };
18898
20720
  };
18899
- WalletKycRailResponse: {
20721
+ /** @description The base form in the overview. */
20722
+ KycFormsFormSummary: {
20723
+ state: components["schemas"]["KycFormsFormState"];
20724
+ missing_required: number;
20725
+ submission: components["schemas"]["KycFormsSubmission"];
20726
+ };
20727
+ KycFormsOverview: {
18900
20728
  /** @example true */
18901
20729
  success: boolean;
18902
- data: components["schemas"]["WalletKycRail"];
20730
+ /** @example {
20731
+ * "entity_type": "individual",
20732
+ * "status": "PENDING",
20733
+ * "stage": "action_required",
20734
+ * "waiting_on": "you",
20735
+ * "next_step": "verification",
20736
+ * "base_form": {
20737
+ * "state": "in_review",
20738
+ * "missing_required": 0,
20739
+ * "submission": {
20740
+ * "id": "7b0f3c52-1d2e-4a6b-8f90-3c4d5e6f7a81",
20741
+ * "status": "awaiting_verification",
20742
+ * "comment": null
20743
+ * }
20744
+ * },
20745
+ * "verification": {
20746
+ * "applicant": {
20747
+ * "state": "in_progress"
20748
+ * },
20749
+ * "owners": [],
20750
+ * "invites": null
20751
+ * },
20752
+ * "rails": [],
20753
+ * "cards": []
20754
+ * } */
20755
+ data: {
20756
+ /** @enum {string} */
20757
+ entity_type: "individual" | "business";
20758
+ status: components["schemas"]["KycFormsEntityStatus"];
20759
+ /**
20760
+ * @description Build the screen by this, not by `status`. `not_required` — the tenant asks nothing of this client type (`base_form` is null); `not_started` — the base form was not started; `incomplete` — a draft exists; `action_required` — the client's move: pass the identity check (`next_step: verification`), or, for a business, get the owners through theirs (`next_step: owners`); `in_review` — the identity provider or compliance is looking; `resubmit` — returned by compliance, the form is open again with `submission.comment`; `on_hold` — frozen by compliance; `verified` — approved; `expired` — the verification lapsed: the applicant passes the identity check again (`next_step: verification`), then compliance looks again; `rejected` — refused, the form is read-only; `offboarded` — compliance ended the relationship, final; `unknown` — a status this contract does not know. The stage of each `status`: `APPROVED` → `verified`; `REJECT`, `DECLINED`, `DOUBLE` → `rejected`; `OFFBOARDED` → `offboarded`; `EXPIRED` → `expired`; `HOLD` → `on_hold`; `WAITING_ON_REVIEW` → `in_review`; `NEEDS_ATTENTION` → `resubmit`; `WAITING_ON_UBOS` → `action_required` while an owner other than the filler's row has a check to start, finish or redo (`next_step: owners`), else `in_review`; `UNVERIFIED`, `PENDING`, `SOFT_REJECT` → by the base form and the identity check: `not_required` (no base form), `not_started`, `incomplete` (a draft), `action_required` (the check is the move), `in_review` (sent, with compliance or the provider), `resubmit` (the latest submission was returned) — the forms flow never sets `SOFT_REJECT`, one left by the old flow shows the screen of its form like `PENDING`; `PROCESSING` → `unknown` (the forms flow never sets it, an old-flow vendor sync may leave it).
20761
+ * @enum {string}
20762
+ */
20763
+ stage: "not_required" | "not_started" | "incomplete" | "action_required" | "in_review" | "resubmit" | "on_hold" | "verified" | "expired" | "rejected" | "offboarded" | "unknown";
20764
+ /**
20765
+ * @description `you` — the client's move; `applicant` — the identity check is the entity owner's to pass (`verification.applicant`, for a business the filler) and the reader is someone else, an admin of the wallet: `next_step` is `wait` where the owner gets `verification` — show who is awaited; `compliance` — also while the identity provider looks (`verification.applicant.state: in_review`); `nobody` — nothing to wait for (verified or rejected).
20766
+ * @enum {string}
20767
+ */
20768
+ waiting_on: "you" | "applicant" | "compliance" | "nobody";
20769
+ /**
20770
+ * @description `form` — show the base form (`GET …/forms`); `verification` — open the identity check (`POST …/verification/session`); `owners` — a business under `WAITING_ON_UBOS` with an owner whose check is not started, not finished or asked again: show `verification.owners[]` and move each one along through the owner routes (`…/verification/owners/{owner_id}/session`, `/link`, `/document`), or have the identity provider email them again (`…/verification/owners/invite`, see `verification.invites`); `wait` — nothing to do now (also a business whose owners' checks are all with the identity provider); `none` — nothing more.
20771
+ * @enum {string}
20772
+ */
20773
+ next_step: "form" | "verification" | "owners" | "wait" | "none";
20774
+ /** @description null when the tenant asks nothing of this client type. */
20775
+ base_form: components["schemas"]["KycFormsFormSummary"] | null;
20776
+ verification: {
20777
+ /** @description The identity check of the person: of the entity's owner for a personal entity, of the filler (their own personal entity) for a business. `passed` also when the entity holds a verified identity document, unless the provider asks to go again. */
20778
+ applicant: {
20779
+ state: components["schemas"]["KycFormsVerificationState"];
20780
+ };
20781
+ /** @description A business with a base form only (empty otherwise): one item per individual beneficial owner — the filler's own row included, told by `is_applicant` in the form's `values.beneficial_owners` — and per company among the owners whose check the identity provider runs (the tenant's company level checks companies; CORE requests the check on the company data of the item, there is no session, link or document for it). A company the provider does not check is not listed. `state` is that owner's own check; `not_started` while a person has no applicant. */
20782
+ owners: {
20783
+ /**
20784
+ * Format: uuid
20785
+ * @description The `owner_id` of the owner routes (a person only).
20786
+ */
20787
+ id: string;
20788
+ /**
20789
+ * @description `individual` — a person who passes the check themselves (the owner routes apply); `company` — a company among the owners, checked on the company data the form declared, nothing for the client to do (the owner routes answer `400 KYC_OWNER_NOT_INDIVIDUAL`), and never an addressee of the provider's mailing.
20790
+ * @enum {string}
20791
+ */
20792
+ type: "individual" | "company";
20793
+ /** @description The owner as the form names them: a person's first and last name, a company's name; null when the form gave none. The filler's own row is null until they pass the identity check — then the name comes from their document. */
20794
+ name: string | null;
20795
+ /**
20796
+ * @description The owner's `role` as sent in the form — a code of the `ubo_role` dictionary, its labels in the `options` of the form's role field; null when none.
20797
+ * @enum {string|null}
20798
+ */
20799
+ role: "UBO" | "OWNER_OR_OPERATOR" | "PARTNER" | "DIRECTOR_CONTROL_PERSON_OR_LEGAL_REP" | "AGENT_OR_AUTHORISED_PERSON" | null;
20800
+ /** @description The filler's own row — the item the filler marked as themselves (`is_applicant` in the form), or the one CORE added for them from `applicant_role`. Draw it without the owner actions: the owner routes answer it `400 KYC_OWNER_IS_FILLER`. Its `state` is the filler's own check on their personal entity — the same as `verification.applicant.state` for the owner of the business — and it never counts towards `next_step: owners`. */
20801
+ is_applicant: boolean;
20802
+ state: components["schemas"]["KycFormsVerificationState"];
20803
+ /**
20804
+ * Format: date-time
20805
+ * @description When the identity provider last emailed this owner their link — after the form was sent and on each `POST …/verification/owners/invite`, to the persons whose item has `invite_by_email: true` and an email; the filler's row too (through the email of their account); null = never (the owner gets the link by hand: `…/owners/{owner_id}/link` or `/session`); always null for a company.
20806
+ */
20807
+ invited_at: string | null;
20808
+ }[];
20809
+ /** @description The mailing of the owners' links of a business with a base form; null for a personal entity. */
20810
+ invites: {
20811
+ /**
20812
+ * Format: date-time
20813
+ * @description When the identity provider was last asked to email the owners — right after the form was sent, or by `POST …/verification/owners/invite`; null = never.
20814
+ */
20815
+ sent_at: string | null;
20816
+ /**
20817
+ * Format: date-time
20818
+ * @description From when `POST …/verification/owners/invite` is taken again (10 minutes after `sent_at`); null = now.
20819
+ */
20820
+ next_at: string | null;
20821
+ } | null;
20822
+ };
20823
+ /** @description Only for an entity linked to a wallet and with a base form: one item per active rail of the tenant of the entity's client type (and the universal ones) — not filtered by what the wallet sees (`GET …/targets` does that); empty otherwise. */
20824
+ rails: {
20825
+ /** Format: uuid */
20826
+ rail_id: string;
20827
+ form_state: components["schemas"]["KycFormsFormState"];
20828
+ missing_required: number;
20829
+ submission: components["schemas"]["KycFormsSubmission"];
20830
+ }[];
20831
+ /** @description A personal entity, the owner's own screen only (empty for a business entity and for any other caller): the forms before a card the owner has saved or sent, one per program and wallet; nothing is listed before a card form is opened and saved. */
20832
+ cards: {
20833
+ /** Format: uuid */
20834
+ program_id: string;
20835
+ /** Format: uuid */
20836
+ wallet_id: string;
20837
+ form_state: components["schemas"]["KycFormsFormState"];
20838
+ missing_required: number;
20839
+ submission: components["schemas"]["KycFormsSubmission"];
20840
+ }[];
20841
+ };
20842
+ };
20843
+ /** @description The state of the form of one target, as `GET …/forms` would build it. */
20844
+ KycFormsTargetForm: {
20845
+ form_state: components["schemas"]["KycFormsFormState"];
20846
+ missing_required: number;
20847
+ submission: components["schemas"]["KycFormsSubmission"];
20848
+ };
20849
+ KycFormsTargets: {
20850
+ /** @example true */
20851
+ success: boolean;
20852
+ /** @example {
20853
+ * "entity_id": "9d1e6a40-2b3c-4d5e-8f70-a1b2c3d4e5f6",
20854
+ * "wallet_id": "4c5d6e7f-8091-4a2b-b3c4-d5e6f7081920",
20855
+ * "base": {
20856
+ * "form_state": "complete",
20857
+ * "missing_required": 0,
20858
+ * "submission": null
20859
+ * },
20860
+ * "rails": [
20861
+ * {
20862
+ * "id": "0a1b2c3d-4e5f-4061-8293-a4b5c6d7e8f9",
20863
+ * "is_submit_available": true,
20864
+ * "can_submit": true,
20865
+ * "application": null,
20866
+ * "form": {
20867
+ * "form_state": "not_started",
20868
+ * "missing_required": 4,
20869
+ * "submission": null
20870
+ * }
20871
+ * }
20872
+ * ],
20873
+ * "programs": []
20874
+ * } */
20875
+ data: {
20876
+ /** Format: uuid */
20877
+ entity_id: string;
20878
+ /**
20879
+ * Format: uuid
20880
+ * @description The wallet the rails and the programs are read for; null when the entity has none and the query named none.
20881
+ */
20882
+ wallet_id: string | null;
20883
+ /** @description The base form; null when the tenant asks nothing of this client type. */
20884
+ base: components["schemas"]["KycFormsTargetForm"] | null;
20885
+ /** @description The active rails the wallet sees for this entity (its type and the universal ones), each with the wallet's application and the state of the rail's form. Empty without a wallet, and when the tenant asks nothing of this client type (a rail form includes the base form). A rail is known by `id` alone. */
20886
+ rails: {
20887
+ /**
20888
+ * Format: uuid
20889
+ * @description The `rails` value for `GET …/forms`.
20890
+ */
20891
+ id: string;
20892
+ /** @description The rail takes submissions at all. */
20893
+ is_submit_available: boolean;
20894
+ /** @description The rail would take the wallet now, as `can_submit` of `GET /frontend/wallets/{wallet_id}/kyc-rails` says: an onboarding behind it, the entity's type, the KYC `APPROVED`, no application approved or with the vendor. The rail's form is not looked at: it is `form` here (`form_state`, `missing_required`). Offer `POST …/kyc-rails/{rail_id}` when `can_submit` is `true` and `form.form_state` is `complete`; with the form not complete the submission answers `400 RAIL_REQUIREMENTS_INCOMPLETE` — show the form first. */
20895
+ can_submit: boolean;
20896
+ /** @description The wallet's application on the rail; null before the first submission. */
20897
+ application: {
20898
+ /**
20899
+ * @description As `wallet_rail.status` of `GET /frontend/wallets/{wallet_id}/kyc-rails`: an application is never `EXPIRED` or `OFFBOARDED`, those belong to the KYC entity.
20900
+ * @example PENDING
20901
+ * @enum {string}
20902
+ */
20903
+ status: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW";
20904
+ /** @description A neutral text for the status. */
20905
+ message: string | null;
20906
+ terms_confirmed: boolean;
20907
+ } | null;
20908
+ form: components["schemas"]["KycFormsTargetForm"];
20909
+ }[];
20910
+ /** @description A personal entity with a wallet only: the card programs the wallet may ask a card of, as `GET /frontend/issuing/config/programs?wallet_id=` lists them, each with the level its vendor demands and the state of the card form built for the wallet. Empty for a business entity and without a wallet. */
20911
+ programs: {
20912
+ /**
20913
+ * Format: uuid
20914
+ * @description The `programs` value for `GET …/forms`.
20915
+ */
20916
+ id: string;
20917
+ name: string;
20918
+ /**
20919
+ * @description The cardholder KYC bar of the program: `minimal` and `basic` are typed in, `declared` and `full` end in the identity check.
20920
+ * @enum {string}
20921
+ */
20922
+ level: "minimal" | "basic" | "declared" | "full";
20923
+ /** @description The card form ends in the identity check (the document or the face is required). */
20924
+ needs_identity_verification: boolean;
20925
+ form: components["schemas"]["KycFormsTargetForm"];
20926
+ }[];
20927
+ };
20928
+ };
20929
+ KycFormsTypeTargets: {
20930
+ /** @example true */
20931
+ success: boolean;
20932
+ /** @example {
20933
+ * "type": "business",
20934
+ * "rails": [
20935
+ * {
20936
+ * "id": "0a1b2c3d-4e5f-4061-8293-a4b5c6d7e8f9",
20937
+ * "is_submit_available": true,
20938
+ * "account_programs": [
20939
+ * {
20940
+ * "id": "5e6f7081-9a0b-4c1d-8e2f-a3b4c5d6e7f8",
20941
+ * "name": "EUR account"
20942
+ * }
20943
+ * ],
20944
+ * "card_program_ids": []
20945
+ * },
20946
+ * {
20947
+ * "id": "1b2c3d4e-5f60-4172-93a4-b5c6d7e8f901",
20948
+ * "is_submit_available": true,
20949
+ * "account_programs": [],
20950
+ * "card_program_ids": [
20951
+ * "2c3d4e5f-6071-4283-a4b5-c6d7e8f90123"
20952
+ * ]
20953
+ * }
20954
+ * ],
20955
+ * "programs": []
20956
+ * } */
20957
+ data: {
20958
+ /** @enum {string} */
20959
+ type: "individual" | "business";
20960
+ /** @description The active rails of the type and the universal ones — those a new wallet of this type lists in `GET /frontend/wallets/{wallet_id}/kyc-rails`. A rail is known by `id` alone. */
20961
+ rails: {
20962
+ /**
20963
+ * Format: uuid
20964
+ * @description The `rails` value for `GET …/forms`.
20965
+ */
20966
+ id: string;
20967
+ /** @description The rail takes submissions at all. */
20968
+ is_submit_available: boolean;
20969
+ /** @description The active account programs on the rail — the programs the wallet will be able to open accounts of once approved on it. Non-empty: the rail carries payments (accounts to send and receive); empty: it opens no account. */
20970
+ account_programs: {
20971
+ /** Format: uuid */
20972
+ id: string;
20973
+ name: string;
20974
+ }[];
20975
+ /** @description The active card programs on the rail that the caller's group lets them ask a card of — the `id` of `programs[]` for a person (a business gets the ids, the programs are a person's). */
20976
+ card_program_ids: string[];
20977
+ }[];
20978
+ /** @description A person only (empty for `business`: the cardholder is a person, asked for through their own entity): the card programs the caller's group lets them ask a card of on these rails, each with the level its vendor demands. */
20979
+ programs: {
20980
+ /**
20981
+ * Format: uuid
20982
+ * @description The `programs` value for `GET …/forms`.
20983
+ */
20984
+ id: string;
20985
+ name: string;
20986
+ /**
20987
+ * Format: uuid
20988
+ * @description The rail that makes the program visible.
20989
+ */
20990
+ rail_id: string;
20991
+ /**
20992
+ * @description The cardholder KYC bar of the program: `minimal` and `basic` are typed in, `declared` and `full` end in the identity check.
20993
+ * @enum {string}
20994
+ */
20995
+ level: "minimal" | "basic" | "declared" | "full";
20996
+ /** @description The card form ends in the identity check (the document or the face is required). */
20997
+ needs_identity_verification: boolean;
20998
+ }[];
20999
+ };
21000
+ };
21001
+ /** @description The structured payload of an error that carries one (absent otherwise — an invalid uuid or a malformed body is a message only). `VALIDATION_ERROR`: `fields` is a map from the field key to its messages (a list item field is `beneficial_owners[0].role`, the list as a whole `beneficial_owners`). `FORM_FIELD_NOT_ALLOWED`, `KYC_FORM_CONDITIONS_CYCLE`: `fields` is a list of keys. */
21002
+ KycFormsErrorDetails: {
21003
+ fields: {
21004
+ [key: string]: string[];
21005
+ } | string[];
21006
+ };
21007
+ /** @description The error envelope of the KYC forms: `ErrorResponse` with the `details` of the field errors spelled out. */
21008
+ KycFormsErrorResponse: components["schemas"]["ErrorResponse"] & {
21009
+ error?: {
21010
+ details?: components["schemas"]["KycFormsErrorDetails"];
21011
+ };
18903
21012
  };
18904
21013
  };
18905
21014
  responses: {
18906
- /** @description Authentication credentials are missing or invalid */
21015
+ /** @description `UNAUTHORIZED` — authentication credentials are missing or invalid (the standard error envelope) */
18907
21016
  UnauthorizedError: {
18908
21017
  headers: {
18909
21018
  [name: string]: unknown;
18910
21019
  };
18911
21020
  content: {
18912
- "application/json": {
18913
- error?: {
18914
- /** @example UNAUTHORIZED */
18915
- code?: string;
18916
- /** @example Authorization header is missing */
18917
- message?: string;
18918
- };
18919
- };
21021
+ /** @example {
21022
+ * "success": false,
21023
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21024
+ * "error": {
21025
+ * "code": "UNAUTHORIZED",
21026
+ * "message": "Authorization header is missing"
21027
+ * }
21028
+ * } */
21029
+ "application/json": components["schemas"]["ErrorResponse"];
21030
+ };
21031
+ };
21032
+ /** @description `ACCESS_DENIED` — the user has no permission to access this resource (the standard error envelope) */
21033
+ ForbiddenError: {
21034
+ headers: {
21035
+ [name: string]: unknown;
21036
+ };
21037
+ content: {
21038
+ /** @example {
21039
+ * "success": false,
21040
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21041
+ * "error": {
21042
+ * "code": "ACCESS_DENIED",
21043
+ * "message": "You don't have permission to access this resource"
21044
+ * }
21045
+ * } */
21046
+ "application/json": components["schemas"]["ErrorResponse"];
21047
+ };
21048
+ };
21049
+ /** @description `NOT_FOUND` — the requested resource was not found (the standard error envelope) */
21050
+ NotFoundError: {
21051
+ headers: {
21052
+ [name: string]: unknown;
21053
+ };
21054
+ content: {
21055
+ /** @example {
21056
+ * "success": false,
21057
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21058
+ * "error": {
21059
+ * "code": "NOT_FOUND",
21060
+ * "message": "Resource not found"
21061
+ * }
21062
+ * } */
21063
+ "application/json": components["schemas"]["ErrorResponse"];
21064
+ };
21065
+ };
21066
+ /** @description `RAIL_NOT_FOUND` — no such rail on the wallet's tenant, or an archived rail the wallet is not approved on */
21067
+ WalletKycRailNotFound: {
21068
+ headers: {
21069
+ [name: string]: unknown;
21070
+ };
21071
+ content: {
21072
+ /** @example {
21073
+ * "success": false,
21074
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21075
+ * "error": {
21076
+ * "code": "RAIL_NOT_FOUND",
21077
+ * "message": "KYC rail not found"
21078
+ * }
21079
+ * } */
21080
+ "application/json": components["schemas"]["ErrorResponse"];
21081
+ };
21082
+ };
21083
+ /** @description `VALIDATION_ERROR` — `rail_id` is not a UUID (a message only) */
21084
+ WalletKycRailBadId: {
21085
+ headers: {
21086
+ [name: string]: unknown;
21087
+ };
21088
+ content: {
21089
+ "application/json": components["schemas"]["ErrorResponse"];
18920
21090
  };
18921
21091
  };
18922
- /** @description User does not have permission to access this resource */
18923
- ForbiddenError: {
21092
+ /** @description `VALIDATION_ERROR` — field errors in `details.fields[key] = [message]` (on a business form the owner list the KYC tables refuse, and owner shares adding up to more than 100%, come back under `beneficial_owners`; a value sent for a field whose condition reads a source left empty or wrong comes back as the error of the source, e.g. `beneficial_owners[0].role`), or a message only for a malformed body (`schema_version` missing or longer than 64, `values` not an object) and a path id that is not a uuid; `FORM_FIELD_NOT_ALLOWED` — a key the form does not accept (unknown, locked, hidden, a file field), `details.fields = [key]`, the whole request refused; `FORM_TARGET_UNSUPPORTED` — a card program named on a business entity; `INVALID_REQUEST` — `wallet_id` missing for a form over card programs; `KYC_FORM_WALLET_NOT_LINKED` — `wallet_id` of a form over rails is not a wallet of this entity; `KYC_BASE_BINDING_MISSING` — the tenant has no base form for this client type; `KYC_FORMS_NOT_ENABLED` — the tenant is not on the forms flow */
21093
+ KycFormsFieldErrors: {
18924
21094
  headers: {
18925
21095
  [name: string]: unknown;
18926
21096
  };
18927
21097
  content: {
18928
- "application/json": {
18929
- error?: {
18930
- /** @example ACCESS_DENIED */
18931
- code?: string;
18932
- /** @example You don't have permission to access this resource */
18933
- message?: string;
18934
- };
18935
- };
21098
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
18936
21099
  };
18937
21100
  };
18938
- /** @description The requested resource was not found */
18939
- NotFoundError: {
21101
+ /** @description `KYC_FORM_CONDITIONS_CYCLE` — the tenant's form settings show fields on conditions that read each other in a circle (`details.fields` lists the keys); nothing the client can fix, report it to support */
21102
+ KycFormsConditionsCycle: {
18940
21103
  headers: {
18941
21104
  [name: string]: unknown;
18942
21105
  };
18943
21106
  content: {
18944
- "application/json": {
18945
- error?: {
18946
- /** @example NOT_FOUND */
18947
- code?: string;
18948
- /** @example Resource not found */
18949
- message?: string;
18950
- };
18951
- };
21107
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
21108
+ };
21109
+ };
21110
+ /** @description `SERVICE_UNAVAILABLE` — the locking service is unavailable, the operation cannot be done safely; retry later */
21111
+ KycFormsLockUnavailable: {
21112
+ headers: {
21113
+ [name: string]: unknown;
21114
+ };
21115
+ content: {
21116
+ "application/json": components["schemas"]["ErrorResponse"];
21117
+ };
21118
+ };
21119
+ /** @description `KYC_FORMS_NOT_ENABLED` — the tenant still runs KYC through the BFF; `VALIDATION_ERROR` — a path id or a query value that is not a uuid (a message only) */
21120
+ KycFormsBadRequest: {
21121
+ headers: {
21122
+ [name: string]: unknown;
21123
+ };
21124
+ content: {
21125
+ "application/json": components["schemas"]["ErrorResponse"];
21126
+ };
21127
+ };
21128
+ /** @description `ACCESS_DENIED` — the caller is not the owner of the entity, nor an owner or admin of a wallet it is linked to (other wallet roles see nothing of the dossier); with `wallet_id` named: the entity's owner or the caller is no member of that wallet */
21129
+ KycFormsAccessDenied: {
21130
+ headers: {
21131
+ [name: string]: unknown;
21132
+ };
21133
+ content: {
21134
+ "application/json": components["schemas"]["ErrorResponse"];
21135
+ };
21136
+ };
21137
+ /** @description `KYC_BUSINESS_FORM_NOT_SENT` — the base form of the business was not sent yet (also on a personal entity: it has no owners); `KYC_OWNER_INVITES_NOT_AVAILABLE` — the owners are not emailed now, `details.reason` says why: `with_compliance` — the application is no longer the client's (`status` other than `PENDING` / `WAITING_ON_UBOS`), `not_ready` — the company is still being set up with the identity provider right after the form was sent, try again in a minute; `KYC_OWNER_INVITES_TOO_SOON` — the owners were emailed less than 10 minutes ago, `details.retry_at` (date-time) says from when the route is taken again (the overview's `verification.invites.next_at`); `OPERATION_IN_PROGRESS` — a mailing of this entity is already being asked for, or the set-up after the sent form is running right now: try again in a few seconds. */
21138
+ KycFormsOwnerInviteConflict: {
21139
+ headers: {
21140
+ [name: string]: unknown;
21141
+ };
21142
+ content: {
21143
+ "application/json": components["schemas"]["ErrorResponse"];
21144
+ };
21145
+ };
21146
+ /** @description `VALIDATION_ERROR` — `entity_id` or `owner_id` is not a uuid, or the body is malformed; `KYC_FORMS_NOT_ENABLED`; `KYC_OWNER_IS_FILLER` — the owner is the person filling the form: they verify their identity on their own profile (`POST …/verification/session`); `KYC_OWNER_NOT_INDIVIDUAL` — the owner is a company: it has nothing to pass itself, its check is requested on its behalf (`verification.owners[]` of the overview shows it with `type: company`); `KYC_VERIFICATION_LEVEL_MISSING` — the tenant has no individual verification level configured; `VERIFICATION_PROVIDER_UNAVAILABLE` — the identity provider refused or did not answer, try later; `VERIFICATION_PROVIDER_NOT_CONFIGURED`. */
21147
+ KycFormsOwnerErrors: {
21148
+ headers: {
21149
+ [name: string]: unknown;
21150
+ };
21151
+ content: {
21152
+ "application/json": components["schemas"]["ErrorResponse"];
21153
+ };
21154
+ };
21155
+ /** @description `NOT_FOUND` — the entity does not exist or belongs to another tenant; `KYC_OWNER_NOT_FOUND` — the owner is not a beneficial owner of this entity (also when the entity is a personal one). */
21156
+ KycFormsOwnerNotFound: {
21157
+ headers: {
21158
+ [name: string]: unknown;
21159
+ };
21160
+ content: {
21161
+ "application/json": components["schemas"]["ErrorResponse"];
21162
+ };
21163
+ };
21164
+ /** @description `KYC_BUSINESS_FORM_NOT_SENT` — the base form of the business was not sent yet: the owners are set up once it is; `OPERATION_IN_PROGRESS` — a request for this owner is already running. */
21165
+ KycFormsOwnerConflict: {
21166
+ headers: {
21167
+ [name: string]: unknown;
21168
+ };
21169
+ content: {
21170
+ "application/json": components["schemas"]["ErrorResponse"];
18952
21171
  };
18953
21172
  };
18954
21173
  };
@@ -18979,6 +21198,24 @@ export interface components {
18979
21198
  KycRailsWalletId: string;
18980
21199
  /** @description `kyc_rails.id` of the wallet's tenant */
18981
21200
  KycRailId: string;
21201
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
21202
+ KycFormsEntityId: string;
21203
+ /** @description `kyc_rails.id` of the tenant the form is for, as a native query array: `rails[]=a&rails[]=b` or `rails=a&rails=b` (a comma-separated string is not a list). Empty with `programs`: the base form. One rail alone: that rail's form. Several, or together with `programs`: the multi form over the whole set (`scope: multi`), whatever the order of the ids. A rail of another client type than the entity's (and not universal), or one the tenant does not have, is `404 NOT_FOUND`; a value that is not a uuid is `400 VALIDATION_ERROR`. */
21204
+ KycFormsRails: string[];
21205
+ /** @description `issuing_programs.id` of the tenant the form is for, as a native query array: `programs[]=a&programs[]=b` or `programs=a&programs=b`. One program alone: the form before a card of that program (`scope: card`). Together with `rails` or several at once: the multi form. Only a personal entity has card forms (`400 FORM_TARGET_UNSUPPORTED` on a business entity); `wallet_id` is required whenever programs are named. A program the tenant does not have is `404 NOT_FOUND`. */
21206
+ KycFormsPrograms: string[];
21207
+ /** @description The wallet the form is filled for; the draft and the submission carry it, and CORE puts this wallet on the form's rails and programs once the form is accepted and the KYC is `APPROVED`. Required when `programs` are named (`400 INVALID_REQUEST` without it): the entity's owner must be an active member of it (any role; the cardholder is theirs), and so must the caller when it is someone else, else `403 ACCESS_DENIED`. Optional when only `rails` are named: a rail is opened per wallet, so it must be a wallet of this entity (`400 KYC_FORM_WALLET_NOT_LINKED` otherwise) with the same membership rule; without it the entity's main wallet. Ignored on the base form. Not a uuid: `400 VALIDATION_ERROR`. */
21208
+ KycFormsWalletId: string;
21209
+ /** @description The wallet the rails and the card programs are read for. Optional: without it the first linked wallet (main wallet first) that the entity's owner and the caller are both members of is used; when there is none — no linked wallet, or none the two share — the answer has `wallet_id: null` and empty `rails` and `programs`. With it, the entity's owner must be an active member of the wallet, and so must the caller when it is someone else, else `403 ACCESS_DENIED`. */
21210
+ KycFormsTargetsWalletId: string;
21211
+ /** @description The `id` of a file in the draft (`saved: false`) */
21212
+ KycFormsUploadId: string;
21213
+ /** @description Language of the texts (labels, hints, options, section titles, general messages); takes precedence over `Accept-Language`. A language outside the tenant's list is served in English. */
21214
+ KycFormsLocale: string;
21215
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
21216
+ KycFormsAcceptLanguage: string;
21217
+ /** @description The `id` of a beneficial owner of the business entity — an item of `beneficial_owners` as `GET …/forms` lists it after the base form was sent (every saved item carries its `id`; `verification.owners[].id` of the overview is the same id). A person, not a company; not the owner the filler marked as themselves (`is_applicant`). */
21218
+ KycFormsOwnerId: string;
18982
21219
  };
18983
21220
  requestBodies: never;
18984
21221
  headers: never;