squarefi-bff-api-module 1.36.95 → 1.36.97

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;
@@ -12081,6 +12133,10 @@ export interface paths {
12081
12133
  * User-scoped: no wallet is involved, unlike
12082
12134
  * `/frontend/kyc_verification/{wallet_id}/init`.
12083
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
+ *
12084
12140
  * **Authentication**: Bearer token with x-tenant-id header required
12085
12141
  *
12086
12142
  */
@@ -12126,7 +12182,7 @@ export interface paths {
12126
12182
  };
12127
12183
  };
12128
12184
  };
12129
- /** @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 */
12130
12186
  400: {
12131
12187
  headers: {
12132
12188
  [name: string]: unknown;
@@ -12194,6 +12250,10 @@ export interface paths {
12194
12250
  * is already on, for the SDK's token-expiry callback. The caller's
12195
12251
  * Bearer token is forwarded to the Auth API.
12196
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
+ *
12197
12257
  * **Authentication**: Bearer token with x-tenant-id header required
12198
12258
  *
12199
12259
  */
@@ -12226,6 +12286,15 @@ export interface paths {
12226
12286
  };
12227
12287
  };
12228
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
+ };
12229
12298
  /** @description Missing or invalid Bearer token */
12230
12299
  401: {
12231
12300
  headers: {
@@ -12889,8 +12958,9 @@ export interface paths {
12889
12958
  * `is_main` wallet, else the oldest one.
12890
12959
  *
12891
12960
  * The selection cannot outlive the access it rides on: the flag sits on
12892
- * the membership row, so revoking membership drops it. A deleted wallet
12893
- * 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.
12894
12964
  *
12895
12965
  * **Authentication**: Bearer token with x-tenant-id header required
12896
12966
  *
@@ -12932,7 +13002,9 @@ export interface paths {
12932
13002
  * The choice is per user, not per wallet: selecting a wallet shared with
12933
13003
  * the caller changes nothing for its owner or for the other members.
12934
13004
  * Any wallet the caller is an **active member** of may be selected —
12935
- * 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.
12936
13008
  *
12937
13009
  * **Authentication**: Bearer token with x-tenant-id header required
12938
13010
  *
@@ -12971,16 +13043,46 @@ export interface paths {
12971
13043
  };
12972
13044
  };
12973
13045
  };
12974
- /** @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
+ * */
12975
13049
  400: {
12976
13050
  headers: {
12977
13051
  [name: string]: unknown;
12978
13052
  };
12979
- content?: never;
13053
+ content: {
13054
+ "application/json": components["schemas"]["ErrorResponse"];
13055
+ };
12980
13056
  };
12981
13057
  401: components["responses"]["UnauthorizedError"];
12982
- 403: components["responses"]["ForbiddenError"];
12983
- 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
+ };
12984
13086
  };
12985
13087
  };
12986
13088
  post?: never;
@@ -13274,15 +13376,17 @@ export interface paths {
13274
13376
  * Wallets where the caller holds the scoped `user` role are returned as a reduced shell
13275
13377
  * (`uuid`, `name`, `display_name`, `tenant_id`, `kyc_entity_id`, `kyc_info`, `created_at` + the role fields) — no `logo_url`.
13276
13378
  *
13379
+ * A wallet whose owner has deleted their account is closed for every member and is not listed.
13380
+ *
13277
13381
  * **Authentication**: Bearer token with x-tenant-id header required
13278
13382
  *
13279
13383
  */
13280
13384
  get: {
13281
13385
  parameters: {
13282
13386
  query?: {
13283
- /** @description Number of items to skip */
13387
+ /** @description Number of items to skip (negative values are raised to 0) */
13284
13388
  offset?: number;
13285
- /** @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) */
13286
13390
  limit?: number;
13287
13391
  /** @description Filter wallets by user's access role */
13288
13392
  role?: "owner" | "admin" | "user" | "auditor";
@@ -13340,9 +13444,10 @@ export interface paths {
13340
13444
  is_owner: boolean;
13341
13445
  /**
13342
13446
  * Format: uuid
13343
- * @description KYC entity the wallet was opened for (`GET /kyc/entities`) — group the
13344
- * list by it to see which accounts an entity already has. `null` for a
13345
- * 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.
13346
13451
  *
13347
13452
  */
13348
13453
  kyc_entity_id: string | null;
@@ -13360,6 +13465,17 @@ export interface paths {
13360
13465
  };
13361
13466
  };
13362
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
+ };
13363
13479
  /** @description Missing or invalid bearer token */
13364
13480
  401: {
13365
13481
  headers: {
@@ -13420,8 +13536,9 @@ export interface paths {
13420
13536
  /**
13421
13537
  * Format: uuid
13422
13538
  * @description Optional KYC entity to link (entity-first KYC model). Must be
13423
- * an entity of the current user (`GET /kyc/entities`); its type
13424
- * 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
13425
13542
  * creation and is immutable. Omitted → wallet is created
13426
13543
  * without a linked entity (legacy behaviour).
13427
13544
  *
@@ -14879,7 +14996,7 @@ export interface paths {
14879
14996
  *
14880
14997
  * @enum {string}
14881
14998
  */
14882
- 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";
14883
15000
  /** @description The member deleted their account. They keep their row and role in the
14884
15001
  * team, but have no access and receive no notifications.
14885
15002
  * */
@@ -15657,7 +15774,10 @@ export interface paths {
15657
15774
  * KYC rails of the wallet
15658
15775
  * @description The tenant's KYC rails of the wallet's entity type and the universal ones, each with the wallet's
15659
15776
  * application on it. A rail is listed while it is active; an archived rail stays listed only when the
15660
- * 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`.
15661
15781
  *
15662
15782
  * Replaces the BFF `GET /kyc/{wallet_id}/rails`; items have its shape plus `can_submit`, without the
15663
15783
  * rail's `code` and `name` — match a rail to a program by `id` (`kyc_rails_id`).
@@ -15692,12 +15812,14 @@ export interface paths {
15692
15812
  };
15693
15813
  401: components["responses"]["UnauthorizedError"];
15694
15814
  403: components["responses"]["ForbiddenError"];
15695
- /** @description Wallet not found (NOT_FOUND) */
15815
+ /** @description `NOT_FOUND` — wallet not found */
15696
15816
  404: {
15697
15817
  headers: {
15698
15818
  [name: string]: unknown;
15699
15819
  };
15700
- content?: never;
15820
+ content: {
15821
+ "application/json": components["schemas"]["ErrorResponse"];
15822
+ };
15701
15823
  };
15702
15824
  };
15703
15825
  };
@@ -15747,22 +15869,10 @@ export interface paths {
15747
15869
  "application/json": components["schemas"]["WalletKycRailResponse"];
15748
15870
  };
15749
15871
  };
15750
- /** @description `rail_id` is not a UUID (VALIDATION_ERROR) */
15751
- 400: {
15752
- headers: {
15753
- [name: string]: unknown;
15754
- };
15755
- content?: never;
15756
- };
15872
+ 400: components["responses"]["WalletKycRailBadId"];
15757
15873
  401: components["responses"]["UnauthorizedError"];
15758
15874
  403: components["responses"]["ForbiddenError"];
15759
- /** @description No such rail on the wallet's tenant, or an archived rail the wallet is not approved on (RAIL_NOT_FOUND) */
15760
- 404: {
15761
- headers: {
15762
- [name: string]: unknown;
15763
- };
15764
- content?: never;
15765
- };
15875
+ 404: components["responses"]["WalletKycRailNotFound"];
15766
15876
  };
15767
15877
  };
15768
15878
  put?: never;
@@ -15773,6 +15883,10 @@ export interface paths {
15773
15883
  * compliance (`WAITING_ON_REVIEW`); a universal rail is approved on the spot. An application the vendor
15774
15884
  * sent back (`HOLD`, `SOFT_REJECT`) is resubmitted. No body.
15775
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
+ *
15776
15890
  * Refused unless the rail has an onboarding implementation (retired rails never do), takes submissions,
15777
15891
  * fits the entity type, and the entity's KYC is `APPROVED` — an entity still under review
15778
15892
  * (`WAITING_ON_REVIEW`) cannot submit. On a tenant without KYC only the tenant's default universal rail
@@ -15805,48 +15919,67 @@ export interface paths {
15805
15919
  "application/json": components["schemas"]["WalletKycRailResponse"];
15806
15920
  };
15807
15921
  };
15808
- /** @description `rail_id` is not a UUID (VALIDATION_ERROR); the rail has no onboarding implementation, or is a universal
15809
- * rail other than the tenant's default on a tenant without KYC (RAIL_NOT_AVAILABLE); the rail takes no
15810
- * submissions (RAIL_SUBMIT_UNAVAILABLE); the rail is of the other entity type (RAIL_TYPE_MISMATCH); the
15811
- * onboarding behind the rail refused the submission (RAIL_SUBMISSION_REJECTED — the vendor's reason is
15812
- * 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
15813
15930
  * */
15814
15931
  400: {
15815
15932
  headers: {
15816
15933
  [name: string]: unknown;
15817
15934
  };
15818
- content?: never;
15935
+ content: {
15936
+ "application/json": components["schemas"]["WalletKycRailSubmitErrorResponse"];
15937
+ };
15819
15938
  };
15820
15939
  401: components["responses"]["UnauthorizedError"];
15821
- /** @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 */
15822
15941
  403: {
15823
15942
  headers: {
15824
15943
  [name: string]: unknown;
15825
15944
  };
15826
- 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
+ };
15827
15956
  };
15828
- /** @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 */
15829
15958
  404: {
15830
15959
  headers: {
15831
15960
  [name: string]: unknown;
15832
15961
  };
15833
- content?: never;
15962
+ content: {
15963
+ "application/json": components["schemas"]["ErrorResponse"];
15964
+ };
15834
15965
  };
15835
- /** @description Already approved on the rail (RAIL_ALREADY_APPROVED), an application is with the vendor
15836
- * (RAIL_SUBMISSION_IN_PROGRESS), or the same submission is being processed (OPERATION_IN_PROGRESS)
15837
- * */
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 */
15838
15967
  409: {
15839
15968
  headers: {
15840
15969
  [name: string]: unknown;
15841
15970
  };
15842
- content?: never;
15971
+ content: {
15972
+ "application/json": components["schemas"]["ErrorResponse"];
15973
+ };
15843
15974
  };
15844
- /** @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 */
15845
15976
  503: {
15846
15977
  headers: {
15847
15978
  [name: string]: unknown;
15848
15979
  };
15849
- content?: never;
15980
+ content: {
15981
+ "application/json": components["schemas"]["ErrorResponse"];
15982
+ };
15850
15983
  };
15851
15984
  };
15852
15985
  };
@@ -15897,21 +16030,17 @@ export interface paths {
15897
16030
  "application/json": components["schemas"]["WalletKycRailResponse"];
15898
16031
  };
15899
16032
  };
15900
- /** @description `rail_id` is not a UUID (VALIDATION_ERROR) */
15901
- 400: {
15902
- headers: {
15903
- [name: string]: unknown;
15904
- };
15905
- content?: never;
15906
- };
16033
+ 400: components["responses"]["WalletKycRailBadId"];
15907
16034
  401: components["responses"]["UnauthorizedError"];
15908
16035
  403: components["responses"]["ForbiddenError"];
15909
- /** @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 */
15910
16037
  404: {
15911
16038
  headers: {
15912
16039
  [name: string]: unknown;
15913
16040
  };
15914
- content?: never;
16041
+ content: {
16042
+ "application/json": components["schemas"]["ErrorResponse"];
16043
+ };
15915
16044
  };
15916
16045
  };
15917
16046
  };
@@ -15921,39 +16050,27 @@ export interface paths {
15921
16050
  patch?: never;
15922
16051
  trace?: never;
15923
16052
  };
15924
- "/frontend/notifications/test": {
16053
+ "/frontend/kyc/entities": {
15925
16054
  parameters: {
15926
16055
  query?: never;
15927
16056
  header?: never;
15928
16057
  path?: never;
15929
16058
  cookie?: never;
15930
16059
  };
15931
- get?: never;
15932
- put?: never;
15933
16060
  /**
15934
- * Send mock notification events (development only)
15935
- * @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`.
15936
16063
  */
15937
- post: {
16064
+ get: {
15938
16065
  parameters: {
15939
- query?: {
15940
- /** @description Accessible wallet whose channel receives the mock `data.changed` signal */
15941
- wallet_id?: string;
15942
- };
16066
+ query?: never;
15943
16067
  header?: never;
15944
16068
  path?: never;
15945
16069
  cookie?: never;
15946
16070
  };
15947
- requestBody?: {
15948
- content: {
15949
- "application/json": {
15950
- /** @description Push notification text */
15951
- message?: string;
15952
- };
15953
- };
15954
- };
16071
+ requestBody?: never;
15955
16072
  responses: {
15956
- /** @description Mock events published */
16073
+ /** @description Entities of the caller */
15957
16074
  200: {
15958
16075
  headers: {
15959
16076
  [name: string]: unknown;
@@ -15961,63 +16078,1305 @@ export interface paths {
15961
16078
  content: {
15962
16079
  "application/json": {
15963
16080
  /** @example true */
15964
- success?: boolean;
15965
- data?: {
15966
- /** Format: uuid */
15967
- notification_id?: string;
15968
- /** Format: uuid */
15969
- signaled_wallet_id?: string | null;
15970
- /**
15971
- * @description Result of the real inbox notification; null when no wallet was passed or it has no orders
15972
- * @enum {string|null}
15973
- */
15974
- inbox_outcome?: "PROCESSED" | "SKIPPED_UNRESOLVED" | "SKIPPED_DUPLICATE" | null;
15975
- /**
15976
- * Format: uuid
15977
- * @description Order the real notification was built from
15978
- */
15979
- inbox_order_uuid?: string | null;
15980
- };
16081
+ success: boolean;
16082
+ data: components["schemas"]["KycFormsEntity"][];
15981
16083
  };
15982
16084
  };
15983
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
+ };
15984
16095
  401: components["responses"]["UnauthorizedError"];
15985
16096
  };
15986
16097
  };
15987
- delete?: never;
15988
- options?: never;
15989
- head?: never;
15990
- patch?: never;
15991
- trace?: never;
15992
- };
15993
- }
15994
- export type webhooks = Record<string, never>;
15995
- export interface components {
15996
- schemas: {
16098
+ put?: never;
15997
16099
  /**
15998
- * @description Order type identifier. Must be one of the active values from the `order_types` table. Examples: `EXCHANGE_OMNI` (omnibus exchange), `BRL_WIRE_OFFRAMP` (wire offramp), `OMNIBUS_CRYPTO_TRANSFER` (crypto withdrawal). `L2F_*` ids are historical (rail retired) and cannot be used to create orders. Legacy `DEPOSIT_*`, `WITHDRAWAL_*` and `AUTO_CONVERT_CRYPTO` are intentionally excluded.
15999
- * @example EXCHANGE_OMNI
16000
- * @enum {string}
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`).
16001
16102
  */
16002
- 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";
16003
- OrderCalculation: {
16004
- /**
16005
- * Format: uuid
16006
- * @description Source currency UUID.
16007
- */
16008
- from_currency: string;
16009
- /**
16010
- * Format: uuid
16011
- * @description Destination currency UUID.
16012
- */
16013
- to_currency: string;
16014
- /**
16015
- * @description Amount to be spent in the source currency.
16016
- * @example 100
16017
- */
16018
- from_amount: number;
16019
- /**
16020
- * @description Amount to be received in the destination currency.
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 no field is left to ask. The terms of the form's rails — a rail it names and the rail of each of its card programs — come with the form in `terms`, to be accepted with the submission (`accepted_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 terms of the form's rails (`form.terms` of `GET …/forms`) are accepted with the submission only: a draft takes no `accepted_terms` (a key of that name is ignored, nothing about the terms is stored) and its answer carries no `terms`. 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 (its fields or the terms documents of its rails changed), 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`) and of the terms — a form with terms documents (`form.terms`) is sent only with every one of their ids in `accepted_terms` (`400 KYC_TERMS_NOT_ACCEPTED` otherwise, nothing written) — 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 rail opened so, or opened before with its terms unconfirmed — a rail of the form, or the rail of one of its programs — gets its terms confirmed (`terms_confirmed: true`) at the time the form was sent, when the form accepted every terms document the application holds; terms changed since the form was sent are left for the client to confirm with `POST …/kyc-rails/{rail_id}/terms-and-conditions`. 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"]["KycFormsSubmitRequest"];
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"]["KycFormsSubmitErrors"];
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 (its fields or the terms documents of its rails changed), 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;
17351
+ };
17352
+ }
17353
+ export type webhooks = Record<string, never>;
17354
+ export interface components {
17355
+ schemas: {
17356
+ /**
17357
+ * @description Order type identifier. Must be one of the active values from the `order_types` table. Examples: `EXCHANGE_OMNI` (omnibus exchange), `BRL_WIRE_OFFRAMP` (wire offramp), `OMNIBUS_CRYPTO_TRANSFER` (crypto withdrawal). `L2F_*` ids are historical (rail retired) and cannot be used to create orders. Legacy `DEPOSIT_*`, `WITHDRAWAL_*` and `AUTO_CONVERT_CRYPTO` are intentionally excluded.
17358
+ * @example EXCHANGE_OMNI
17359
+ * @enum {string}
17360
+ */
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";
17362
+ OrderCalculation: {
17363
+ /**
17364
+ * Format: uuid
17365
+ * @description Source currency UUID.
17366
+ */
17367
+ from_currency: string;
17368
+ /**
17369
+ * Format: uuid
17370
+ * @description Destination currency UUID.
17371
+ */
17372
+ to_currency: string;
17373
+ /**
17374
+ * @description Amount to be spent in the source currency.
17375
+ * @example 100
17376
+ */
17377
+ from_amount: number;
17378
+ /**
17379
+ * @description Amount to be received in the destination currency.
16021
17380
  * @example 98.5
16022
17381
  */
16023
17382
  result_amount: number;
@@ -16120,7 +17479,7 @@ export interface components {
16120
17479
  * @description Rail an order type pays through (`order_types.payment_method`)
16121
17480
  * @enum {string}
16122
17481
  */
16123
- 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";
16124
17483
  /** @description The tenant's markup for the order type (`tenant_order_type_rates`) */
16125
17484
  OrderTypeTenantRates: {
16126
17485
  markup_percent: number | null;
@@ -16176,18 +17535,40 @@ export interface components {
16176
17535
  documents_required_from_amount: number | null;
16177
17536
  tenant_rates: components["schemas"]["OrderTypeTenantRates"];
16178
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. */
16179
17539
  ErrorResponse: {
16180
- /** @example false */
16181
- success?: boolean;
16182
- /** @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
+ */
16183
17546
  correlationId?: string;
16184
- error?: {
16185
- code?: string;
16186
- message?: string;
17547
+ error: {
17548
+ /** @example VALIDATION_ERROR */
17549
+ code: string;
17550
+ /** @example Invalid request */
17551
+ message: string;
16187
17552
  /** @description Structured payload (validation issues, missing fields) when the error carries one */
16188
17553
  details?: Record<string, never> | null;
16189
17554
  };
16190
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
+ };
16191
17572
  /** @description Counterparty account (beneficiary). Wallet-scoped. */
16192
17573
  CounterpartyAccount: {
16193
17574
  /** Format: uuid */
@@ -16261,6 +17642,8 @@ export interface components {
16261
17642
  bank_name: string | null;
16262
17643
  /** @description SWIFT/BIC (ISO 9362) */
16263
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;
16264
17647
  /** @description IBAN (ISO 13616) */
16265
17648
  iban?: string | null;
16266
17649
  /** @description Sort code (6 digits, UK banking) */
@@ -16771,7 +18154,11 @@ export interface components {
16771
18154
  }[];
16772
18155
  /** @description Units of billing currency per unit of transaction currency, so `transaction_amount * conversion_rate ≈ billing_amount`. 1 when the currencies match. */
16773
18156
  conversion_rate?: number;
16774
- 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;
16775
18162
  has_receipt?: boolean;
16776
18163
  merchant?: components["schemas"]["TransactionMerchant"];
16777
18164
  /** Format: date-time */
@@ -17559,7 +18946,7 @@ export interface components {
17559
18946
  amount_to: number | null;
17560
18947
  order_type: string;
17561
18948
  /**
17562
- * @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.
17563
18950
  * @enum {string}
17564
18951
  */
17565
18952
  status: "NEW" | "PENDING" | "EXPECTED" | "PROCESSING" | "COMPLETE" | "FAILED" | "CANCELED" | "REFUNDED";
@@ -17916,10 +19303,10 @@ export interface components {
17916
19303
  */
17917
19304
  type: "individual" | "business" | "universal";
17918
19305
  /**
17919
- * @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.
17920
19307
  * @enum {string}
17921
19308
  */
17922
- 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";
17923
19310
  business_name: string | null;
17924
19311
  first_name: string | null;
17925
19312
  last_name: string | null;
@@ -17944,7 +19331,7 @@ export interface components {
17944
19331
  /** @description The wallet's application on the rail. `null` on the rail while the wallet never submitted to it. */
17945
19332
  WalletKycRailApplication: {
17946
19333
  /**
17947
- * @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`).
17948
19335
  * @enum {string}
17949
19336
  */
17950
19337
  status: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW";
@@ -17965,7 +19352,7 @@ export interface components {
17965
19352
  id: string;
17966
19353
  /** @description The rail takes submissions at all. */
17967
19354
  is_submit_available: boolean;
17968
- /** @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`. */
17969
19356
  can_submit: boolean;
17970
19357
  /** @description The rail's active terms, in display order. */
17971
19358
  terms_and_conditions: components["schemas"]["WalletKycRailTerms"][];
@@ -18002,7 +19389,7 @@ export interface components {
18002
19389
  created_at: string;
18003
19390
  /**
18004
19391
  * Format: uuid
18005
- * @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.
18006
19393
  */
18007
19394
  kyc_entity_id: string | null;
18008
19395
  kyc_info: components["schemas"]["WalletKycInfo"] | null;
@@ -18053,7 +19440,7 @@ export interface components {
18053
19440
  created_at: string;
18054
19441
  /**
18055
19442
  * Format: uuid
18056
- * @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.
18057
19444
  */
18058
19445
  kyc_entity_id: string | null;
18059
19446
  kyc_info: components["schemas"]["WalletKycInfo"] | null;
@@ -18536,7 +19923,7 @@ export interface components {
18536
19923
  /** Format: uuid */
18537
19924
  id: string;
18538
19925
  /** @enum {string} */
18539
- 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";
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";
18540
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`. */
18541
19928
  title: string | null;
18542
19929
  /** @description Text of the item, rendered like `title`; `null` in the same cases. */
@@ -18842,150 +20229,1013 @@ export interface components {
18842
20229
  /** Format: uuid */
18843
20230
  id: string;
18844
20231
  /**
18845
- * @description Human-facing id — quoted in the notification email
18846
- * @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
+ /** @description The terms of one rail of the form: a rail the form names, or the rail of one of its card programs — one group per rail, the programs that go through it listed with it. Draw one checkbox per group that accepts all of its `items`; send their ids in `accepted_terms` of `POST …/forms/submit`. */
20598
+ KycFormsTerms: {
20599
+ /** Format: uuid */
20600
+ rail_id: string;
20601
+ /** @description The card programs of the form that go through this rail; empty when only the rail itself is named. */
20602
+ program_ids: string[];
20603
+ /** @description The rail's active terms documents in display order; empty when the rail has none — nothing to accept. */
20604
+ items: {
20605
+ /** Format: uuid */
20606
+ id: string;
20607
+ /** @example Cardholder Agreement */
20608
+ title: string;
20609
+ description: string | null;
20610
+ /** @example https://example.com/terms.pdf */
20611
+ link: string | null;
20612
+ }[];
20613
+ };
20614
+ KycFormsForm: {
20615
+ /**
20616
+ * @description What the form is for: the base form, a rail, a card program (`card`), or one form over several rails and programs (`multi`).
20617
+ * @enum {string}
20618
+ */
20619
+ scope: "base" | "rail" | "card" | "multi";
20620
+ /** @description The rails the form is built for; empty for the base form. */
20621
+ rails: string[];
20622
+ /** @description The card programs the form is built for; empty for the base form. */
20623
+ programs: string[];
20624
+ /**
20625
+ * Format: uuid
20626
+ * @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.
20627
+ */
20628
+ wallet_id: string | null;
20629
+ /** @enum {string} */
20630
+ entity_type: "individual" | "business";
20631
+ /**
20632
+ * @description The language the texts are in (English when the requested one is not in the tenant's list).
20633
+ * @example en
20634
+ */
20635
+ locale: string;
20636
+ /**
20637
+ * @description Hash of the form composition (keys, requiredness, conditions, list item fields, the ids of the terms documents in `terms`; not the texts); echo it back in the draft and the submission. It can change between the load and the send: `409 FORM_OUTDATED`.
20638
+ * @example b3f1c2a9
20639
+ */
20640
+ schema_version: string;
20641
+ state: components["schemas"]["KycFormsFormState"];
20642
+ submission: components["schemas"]["KycFormsSubmission"];
20643
+ /** @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`). */
20644
+ editable: boolean;
20645
+ /** @description How many required visible fields are still empty (saved, pending and draft values together). */
20646
+ missing_required: number;
20647
+ /**
20648
+ * @description General validation messages by code (`required`, `min`, `max`, `min_length`, `max_length`, `invalid`); `{value}` stands for the bound.
20649
+ * @example {
20650
+ * "required": "This field is required",
20651
+ * "min": "The value must be at least {value}",
20652
+ * "invalid": "Check the value"
20653
+ * }
18847
20654
  */
18848
- reference: string;
20655
+ messages: {
20656
+ [key: string]: string;
20657
+ };
20658
+ /** @description The groups to draw, in order; each field is in exactly one section. */
20659
+ sections: {
20660
+ /** @example purpose */
20661
+ key: string;
20662
+ title: string;
20663
+ description: string | null;
20664
+ fields: components["schemas"]["KycFormsField"][];
20665
+ }[];
18849
20666
  /**
18850
- * @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.
18851
- * @enum {string}
20667
+ * @description The terms the client accepts with the form, one group per rail of the form: the rails named first, then the rail of each card program. Empty for the base form; a program without a rail adds none. The documents are those in force now: a change after the load answers the submission `409 FORM_OUTDATED`.
20668
+ * @example [
20669
+ * {
20670
+ * "rail_id": "a38b9a0c-5d1e-4f2a-8b3c-4d5e6f708192",
20671
+ * "program_ids": [
20672
+ * "d94ef320-1a2b-4c3d-8e4f-5a6b7c8d9e0f"
20673
+ * ],
20674
+ * "items": [
20675
+ * {
20676
+ * "id": "0c1d2e3f-4a5b-4c6d-8e7f-90a1b2c3d4e5",
20677
+ * "title": "Cardholder Agreement",
20678
+ * "description": null,
20679
+ * "link": "https://example.com/terms.pdf"
20680
+ * }
20681
+ * ]
20682
+ * },
20683
+ * {
20684
+ * "rail_id": "c1d7fac1-2b3c-4d5e-9f60-718293a4b5c6",
20685
+ * "program_ids": [],
20686
+ * "items": []
20687
+ * }
20688
+ * ]
18852
20689
  */
18853
- type: "onboarding" | "transaction" | "ongoing";
20690
+ terms: components["schemas"]["KycFormsTerms"][];
20691
+ };
20692
+ KycFormsFormResponse: {
20693
+ /** @example true */
20694
+ success: boolean;
20695
+ data: {
20696
+ form: components["schemas"]["KycFormsForm"];
20697
+ /**
20698
+ * @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.
20699
+ * @example {
20700
+ * "email": "user@example.com",
20701
+ * "citizenship": "DE",
20702
+ * "gov_id_front": [
20703
+ * {
20704
+ * "id": "3f2a9c1e-5b7d-4e0a-9c11-2d8f6a4b7e90",
20705
+ * "file_name": "front.jpg",
20706
+ * "uploaded_at": "2026-10-19T09:30:00Z",
20707
+ * "saved": false
20708
+ * }
20709
+ * ],
20710
+ * "phone": null
20711
+ * }
20712
+ */
20713
+ values: {
20714
+ [key: string]: components["schemas"]["KycFormsFieldValue"];
20715
+ };
20716
+ };
20717
+ };
20718
+ KycFormsAnswersRequest: {
18854
20719
  /**
18855
- * @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.
18856
- * @example Incoming payments of $10,970 and $7,500
20720
+ * @description `form.schema_version` of the form as loaded.
20721
+ * @example b3f1c2a9
18857
20722
  */
18858
- subject: string;
20723
+ schema_version: string;
18859
20724
  /**
18860
- * @description `action_required` — compliance asked and waits for the client; `awaiting_compliance` — the client answered, compliance is reviewing; `closed` — no longer accepts replies.
18861
- * @enum {string}
20725
+ * @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.
20726
+ * @default {}
20727
+ * @example {
20728
+ * "email": "user@example.com",
20729
+ * "citizenship": "DE"
20730
+ * }
18862
20731
  */
18863
- status: "action_required" | "awaiting_compliance" | "closed";
20732
+ values: {
20733
+ [key: string]: components["schemas"]["KycFormsAnswerValue"];
20734
+ };
20735
+ };
20736
+ KycFormsSubmitRequest: components["schemas"]["KycFormsAnswersRequest"] & {
18864
20737
  /**
18865
- * Format: date-time
18866
- * @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.
20738
+ * @description The ids of every terms document of the form (`form.terms[].items[].id`) — the client ticked the checkbox of each group. Required in full when the form has any: one left out answers `400 KYC_TERMS_NOT_ACCEPTED`, an id that is not a uuid or not of this form `400 VALIDATION_ERROR`. A form without terms documents is sent without it. The terms are checked after the fields: while a field is wrong, only the `VALIDATION_ERROR` comes back.
20739
+ * @default []
20740
+ * @example [
20741
+ * "0c1d2e3f-4a5b-4c6d-8e7f-90a1b2c3d4e5"
20742
+ * ]
18867
20743
  */
18868
- due_at: string | null;
18869
- /** @description True only while `action_required` and past `due_at` (red banner) */
18870
- overdue: boolean;
18871
- /** @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. */
18872
- holds_transaction: boolean;
18873
- /** @description The account is on hold while the request is open */
18874
- holds_account: boolean;
18875
- /** @description How many transactions the request covers */
18876
- transactions_count: number;
18877
- /** @description The last message of the conversation, for the card — null while nothing is visible yet */
18878
- last_message: {
18879
- /** @enum {string} */
18880
- author: "compliance" | "client";
18881
- /** @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 */
18882
- preview: string | null;
20744
+ accepted_terms: string[];
20745
+ };
20746
+ KycFormsDraftSaved: {
20747
+ /** @example true */
20748
+ success: boolean;
20749
+ data: {
20750
+ state: components["schemas"]["KycFormsFormState"];
20751
+ missing_required: number;
20752
+ };
20753
+ };
20754
+ KycFormsUploadedFile: {
20755
+ /** @example true */
20756
+ success: boolean;
20757
+ data: {
20758
+ /**
20759
+ * Format: uuid
20760
+ * @description The `upload_id` of the delete route.
20761
+ */
20762
+ id: string;
20763
+ file_name: string;
18883
20764
  /** Format: date-time */
18884
- created_at: string;
18885
- } | null;
18886
- /** Format: date-time */
18887
- created_at: string;
18888
- /** Format: date-time */
18889
- updated_at: string;
18890
- /** Format: date-time */
18891
- closed_at: string | null;
20765
+ uploaded_at: string;
20766
+ /**
20767
+ * @description false: in the draft, deletable; it becomes a KYC document when the submission is applied.
20768
+ * @example false
20769
+ */
20770
+ saved: boolean;
20771
+ };
18892
20772
  };
18893
- RfiAttachment: {
18894
- /** Format: uuid */
18895
- id: string;
18896
- file_name: string;
18897
- /** @description The type the file's content proves (for files sent in the app); null only on some files that came by email */
18898
- content_type: string | null;
18899
- size_bytes: number | null;
18900
- /** Format: date-time */
18901
- created_at: string;
20773
+ /** @description The base form in the overview. */
20774
+ KycFormsFormSummary: {
20775
+ state: components["schemas"]["KycFormsFormState"];
20776
+ missing_required: number;
20777
+ submission: components["schemas"]["KycFormsSubmission"];
18902
20778
  };
18903
- RfiMessage: {
18904
- /** Format: uuid */
18905
- id: string;
18906
- /**
18907
- * @description Which side wrote the message. The analyst is never named — show a placeholder (e.g. "Compliance team") for `compliance` and "You" for `client`.
18908
- * @enum {string}
18909
- */
18910
- author: "compliance" | "client";
18911
- /** @description The text of the message. An empty string when the client answered with files only — show the attachments alone. */
18912
- body: string;
18913
- attachments: components["schemas"]["RfiAttachment"][];
18914
- /** Format: date-time */
18915
- created_at: string;
20779
+ KycFormsOverview: {
20780
+ /** @example true */
20781
+ success: boolean;
20782
+ /** @example {
20783
+ * "entity_type": "individual",
20784
+ * "status": "PENDING",
20785
+ * "stage": "action_required",
20786
+ * "waiting_on": "you",
20787
+ * "next_step": "verification",
20788
+ * "base_form": {
20789
+ * "state": "in_review",
20790
+ * "missing_required": 0,
20791
+ * "submission": {
20792
+ * "id": "7b0f3c52-1d2e-4a6b-8f90-3c4d5e6f7a81",
20793
+ * "status": "awaiting_verification",
20794
+ * "comment": null
20795
+ * }
20796
+ * },
20797
+ * "verification": {
20798
+ * "applicant": {
20799
+ * "state": "in_progress"
20800
+ * },
20801
+ * "owners": [],
20802
+ * "invites": null
20803
+ * },
20804
+ * "rails": [],
20805
+ * "cards": []
20806
+ * } */
20807
+ data: {
20808
+ /** @enum {string} */
20809
+ entity_type: "individual" | "business";
20810
+ status: components["schemas"]["KycFormsEntityStatus"];
20811
+ /**
20812
+ * @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).
20813
+ * @enum {string}
20814
+ */
20815
+ stage: "not_required" | "not_started" | "incomplete" | "action_required" | "in_review" | "resubmit" | "on_hold" | "verified" | "expired" | "rejected" | "offboarded" | "unknown";
20816
+ /**
20817
+ * @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).
20818
+ * @enum {string}
20819
+ */
20820
+ waiting_on: "you" | "applicant" | "compliance" | "nobody";
20821
+ /**
20822
+ * @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.
20823
+ * @enum {string}
20824
+ */
20825
+ next_step: "form" | "verification" | "owners" | "wait" | "none";
20826
+ /** @description null when the tenant asks nothing of this client type. */
20827
+ base_form: components["schemas"]["KycFormsFormSummary"] | null;
20828
+ verification: {
20829
+ /** @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. */
20830
+ applicant: {
20831
+ state: components["schemas"]["KycFormsVerificationState"];
20832
+ };
20833
+ /** @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. */
20834
+ owners: {
20835
+ /**
20836
+ * Format: uuid
20837
+ * @description The `owner_id` of the owner routes (a person only).
20838
+ */
20839
+ id: string;
20840
+ /**
20841
+ * @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.
20842
+ * @enum {string}
20843
+ */
20844
+ type: "individual" | "company";
20845
+ /** @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. */
20846
+ name: string | null;
20847
+ /**
20848
+ * @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.
20849
+ * @enum {string|null}
20850
+ */
20851
+ role: "UBO" | "OWNER_OR_OPERATOR" | "PARTNER" | "DIRECTOR_CONTROL_PERSON_OR_LEGAL_REP" | "AGENT_OR_AUTHORISED_PERSON" | null;
20852
+ /** @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`. */
20853
+ is_applicant: boolean;
20854
+ state: components["schemas"]["KycFormsVerificationState"];
20855
+ /**
20856
+ * Format: date-time
20857
+ * @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.
20858
+ */
20859
+ invited_at: string | null;
20860
+ }[];
20861
+ /** @description The mailing of the owners' links of a business with a base form; null for a personal entity. */
20862
+ invites: {
20863
+ /**
20864
+ * Format: date-time
20865
+ * @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.
20866
+ */
20867
+ sent_at: string | null;
20868
+ /**
20869
+ * Format: date-time
20870
+ * @description From when `POST …/verification/owners/invite` is taken again (10 minutes after `sent_at`); null = now.
20871
+ */
20872
+ next_at: string | null;
20873
+ } | null;
20874
+ };
20875
+ /** @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. */
20876
+ rails: {
20877
+ /** Format: uuid */
20878
+ rail_id: string;
20879
+ form_state: components["schemas"]["KycFormsFormState"];
20880
+ missing_required: number;
20881
+ submission: components["schemas"]["KycFormsSubmission"];
20882
+ }[];
20883
+ /** @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. */
20884
+ cards: {
20885
+ /** Format: uuid */
20886
+ program_id: string;
20887
+ /** Format: uuid */
20888
+ wallet_id: string;
20889
+ form_state: components["schemas"]["KycFormsFormState"];
20890
+ missing_required: number;
20891
+ submission: components["schemas"]["KycFormsSubmission"];
20892
+ }[];
20893
+ };
18916
20894
  };
18917
- RfiTransaction: {
18918
- order_uuid: string;
18919
- order_type: string | null;
18920
- status: string | null;
18921
- amount_from: number | null;
18922
- amount_to: number | null;
18923
- /** Format: date-time */
18924
- created_at: string | null;
18925
- /** @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. */
18926
- held: boolean;
20895
+ /** @description The state of the form of one target, as `GET …/forms` would build it. */
20896
+ KycFormsTargetForm: {
20897
+ form_state: components["schemas"]["KycFormsFormState"];
20898
+ missing_required: number;
20899
+ submission: components["schemas"]["KycFormsSubmission"];
18927
20900
  };
18928
- RfiCaseDetail: components["schemas"]["RfiCase"] & {
18929
- /** @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. */
18930
- can_reply: boolean;
18931
- /** @description The conversation, oldest first */
18932
- messages: components["schemas"]["RfiMessage"][];
18933
- /** @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>"}]`. */
18934
- transactions: components["schemas"]["RfiTransaction"][];
20901
+ KycFormsTargets: {
20902
+ /** @example true */
20903
+ success: boolean;
20904
+ /** @example {
20905
+ * "entity_id": "9d1e6a40-2b3c-4d5e-8f70-a1b2c3d4e5f6",
20906
+ * "wallet_id": "4c5d6e7f-8091-4a2b-b3c4-d5e6f7081920",
20907
+ * "base": {
20908
+ * "form_state": "complete",
20909
+ * "missing_required": 0,
20910
+ * "submission": null
20911
+ * },
20912
+ * "rails": [
20913
+ * {
20914
+ * "id": "0a1b2c3d-4e5f-4061-8293-a4b5c6d7e8f9",
20915
+ * "is_submit_available": true,
20916
+ * "can_submit": true,
20917
+ * "application": null,
20918
+ * "form": {
20919
+ * "form_state": "not_started",
20920
+ * "missing_required": 4,
20921
+ * "submission": null
20922
+ * }
20923
+ * }
20924
+ * ],
20925
+ * "programs": []
20926
+ * } */
20927
+ data: {
20928
+ /** Format: uuid */
20929
+ entity_id: string;
20930
+ /**
20931
+ * Format: uuid
20932
+ * @description The wallet the rails and the programs are read for; null when the entity has none and the query named none.
20933
+ */
20934
+ wallet_id: string | null;
20935
+ /** @description The base form; null when the tenant asks nothing of this client type. */
20936
+ base: components["schemas"]["KycFormsTargetForm"] | null;
20937
+ /** @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. */
20938
+ rails: {
20939
+ /**
20940
+ * Format: uuid
20941
+ * @description The `rails` value for `GET …/forms`.
20942
+ */
20943
+ id: string;
20944
+ /** @description The rail takes submissions at all. */
20945
+ is_submit_available: boolean;
20946
+ /** @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. */
20947
+ can_submit: boolean;
20948
+ /** @description The wallet's application on the rail; null before the first submission. */
20949
+ application: {
20950
+ /**
20951
+ * @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.
20952
+ * @example PENDING
20953
+ * @enum {string}
20954
+ */
20955
+ status: "APPROVED" | "DECLINED" | "PENDING" | "PROCESSING" | "HOLD" | "NEEDS_ATTENTION" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | "WAITING_ON_REVIEW";
20956
+ /** @description A neutral text for the status. */
20957
+ message: string | null;
20958
+ terms_confirmed: boolean;
20959
+ } | null;
20960
+ form: components["schemas"]["KycFormsTargetForm"];
20961
+ }[];
20962
+ /** @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. */
20963
+ programs: {
20964
+ /**
20965
+ * Format: uuid
20966
+ * @description The `programs` value for `GET …/forms`.
20967
+ */
20968
+ id: string;
20969
+ name: string;
20970
+ /**
20971
+ * @description The cardholder KYC bar of the program: `minimal` and `basic` are typed in, `declared` and `full` end in the identity check.
20972
+ * @enum {string}
20973
+ */
20974
+ level: "minimal" | "basic" | "declared" | "full";
20975
+ /** @description The card form ends in the identity check (the document or the face is required). */
20976
+ needs_identity_verification: boolean;
20977
+ form: components["schemas"]["KycFormsTargetForm"];
20978
+ }[];
20979
+ };
18935
20980
  };
18936
- WalletKycRailResponse: {
20981
+ KycFormsTypeTargets: {
18937
20982
  /** @example true */
18938
20983
  success: boolean;
18939
- data: components["schemas"]["WalletKycRail"];
20984
+ /** @example {
20985
+ * "type": "business",
20986
+ * "rails": [
20987
+ * {
20988
+ * "id": "0a1b2c3d-4e5f-4061-8293-a4b5c6d7e8f9",
20989
+ * "is_submit_available": true,
20990
+ * "account_programs": [
20991
+ * {
20992
+ * "id": "5e6f7081-9a0b-4c1d-8e2f-a3b4c5d6e7f8",
20993
+ * "name": "EUR account"
20994
+ * }
20995
+ * ],
20996
+ * "card_program_ids": []
20997
+ * },
20998
+ * {
20999
+ * "id": "1b2c3d4e-5f60-4172-93a4-b5c6d7e8f901",
21000
+ * "is_submit_available": true,
21001
+ * "account_programs": [],
21002
+ * "card_program_ids": [
21003
+ * "2c3d4e5f-6071-4283-a4b5-c6d7e8f90123"
21004
+ * ]
21005
+ * }
21006
+ * ],
21007
+ * "programs": []
21008
+ * } */
21009
+ data: {
21010
+ /** @enum {string} */
21011
+ type: "individual" | "business";
21012
+ /** @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. */
21013
+ rails: {
21014
+ /**
21015
+ * Format: uuid
21016
+ * @description The `rails` value for `GET …/forms`.
21017
+ */
21018
+ id: string;
21019
+ /** @description The rail takes submissions at all. */
21020
+ is_submit_available: boolean;
21021
+ /** @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. */
21022
+ account_programs: {
21023
+ /** Format: uuid */
21024
+ id: string;
21025
+ name: string;
21026
+ }[];
21027
+ /** @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). */
21028
+ card_program_ids: string[];
21029
+ }[];
21030
+ /** @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. */
21031
+ programs: {
21032
+ /**
21033
+ * Format: uuid
21034
+ * @description The `programs` value for `GET …/forms`.
21035
+ */
21036
+ id: string;
21037
+ name: string;
21038
+ /**
21039
+ * Format: uuid
21040
+ * @description The rail that makes the program visible.
21041
+ */
21042
+ rail_id: string;
21043
+ /**
21044
+ * @description The cardholder KYC bar of the program: `minimal` and `basic` are typed in, `declared` and `full` end in the identity check.
21045
+ * @enum {string}
21046
+ */
21047
+ level: "minimal" | "basic" | "declared" | "full";
21048
+ /** @description The card form ends in the identity check (the document or the face is required). */
21049
+ needs_identity_verification: boolean;
21050
+ }[];
21051
+ };
21052
+ };
21053
+ /** @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. `KYC_TERMS_NOT_ACCEPTED`: `terms` — and no `fields`. */
21054
+ KycFormsErrorDetails: {
21055
+ fields?: {
21056
+ [key: string]: string[];
21057
+ } | string[];
21058
+ /**
21059
+ * @description The ids of the terms documents of the form left out of `accepted_terms`.
21060
+ * @example [
21061
+ * "0c1d2e3f-4a5b-4c6d-8e7f-90a1b2c3d4e5"
21062
+ * ]
21063
+ */
21064
+ terms?: string[];
21065
+ };
21066
+ /** @description The error envelope of the KYC forms: `ErrorResponse` with the `details` of the field errors spelled out. */
21067
+ KycFormsErrorResponse: components["schemas"]["ErrorResponse"] & {
21068
+ error?: {
21069
+ details?: components["schemas"]["KycFormsErrorDetails"];
21070
+ };
18940
21071
  };
18941
21072
  };
18942
21073
  responses: {
18943
- /** @description Authentication credentials are missing or invalid */
21074
+ /** @description `UNAUTHORIZED` — authentication credentials are missing or invalid (the standard error envelope) */
18944
21075
  UnauthorizedError: {
18945
21076
  headers: {
18946
21077
  [name: string]: unknown;
18947
21078
  };
18948
21079
  content: {
18949
- "application/json": {
18950
- error?: {
18951
- /** @example UNAUTHORIZED */
18952
- code?: string;
18953
- /** @example Authorization header is missing */
18954
- message?: string;
18955
- };
18956
- };
21080
+ /** @example {
21081
+ * "success": false,
21082
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21083
+ * "error": {
21084
+ * "code": "UNAUTHORIZED",
21085
+ * "message": "Authorization header is missing"
21086
+ * }
21087
+ * } */
21088
+ "application/json": components["schemas"]["ErrorResponse"];
21089
+ };
21090
+ };
21091
+ /** @description `ACCESS_DENIED` — the user has no permission to access this resource (the standard error envelope) */
21092
+ ForbiddenError: {
21093
+ headers: {
21094
+ [name: string]: unknown;
21095
+ };
21096
+ content: {
21097
+ /** @example {
21098
+ * "success": false,
21099
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21100
+ * "error": {
21101
+ * "code": "ACCESS_DENIED",
21102
+ * "message": "You don't have permission to access this resource"
21103
+ * }
21104
+ * } */
21105
+ "application/json": components["schemas"]["ErrorResponse"];
21106
+ };
21107
+ };
21108
+ /** @description `NOT_FOUND` — the requested resource was not found (the standard error envelope) */
21109
+ NotFoundError: {
21110
+ headers: {
21111
+ [name: string]: unknown;
21112
+ };
21113
+ content: {
21114
+ /** @example {
21115
+ * "success": false,
21116
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21117
+ * "error": {
21118
+ * "code": "NOT_FOUND",
21119
+ * "message": "Resource not found"
21120
+ * }
21121
+ * } */
21122
+ "application/json": components["schemas"]["ErrorResponse"];
21123
+ };
21124
+ };
21125
+ /** @description `RAIL_NOT_FOUND` — no such rail on the wallet's tenant, or an archived rail the wallet is not approved on */
21126
+ WalletKycRailNotFound: {
21127
+ headers: {
21128
+ [name: string]: unknown;
21129
+ };
21130
+ content: {
21131
+ /** @example {
21132
+ * "success": false,
21133
+ * "correlationId": "8f14e45f-ceea-4e67-a7a2-5f5a1f0b9c1d",
21134
+ * "error": {
21135
+ * "code": "RAIL_NOT_FOUND",
21136
+ * "message": "KYC rail not found"
21137
+ * }
21138
+ * } */
21139
+ "application/json": components["schemas"]["ErrorResponse"];
21140
+ };
21141
+ };
21142
+ /** @description `VALIDATION_ERROR` — `rail_id` is not a UUID (a message only) */
21143
+ WalletKycRailBadId: {
21144
+ headers: {
21145
+ [name: string]: unknown;
21146
+ };
21147
+ content: {
21148
+ "application/json": components["schemas"]["ErrorResponse"];
18957
21149
  };
18958
21150
  };
18959
- /** @description User does not have permission to access this resource */
18960
- ForbiddenError: {
21151
+ /** @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 */
21152
+ KycFormsFieldErrors: {
18961
21153
  headers: {
18962
21154
  [name: string]: unknown;
18963
21155
  };
18964
21156
  content: {
18965
- "application/json": {
18966
- error?: {
18967
- /** @example ACCESS_DENIED */
18968
- code?: string;
18969
- /** @example You don't have permission to access this resource */
18970
- message?: string;
18971
- };
18972
- };
21157
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
18973
21158
  };
18974
21159
  };
18975
- /** @description The requested resource was not found */
18976
- NotFoundError: {
21160
+ /** @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, `accepted_terms` not a list of at most 200 uuids), an id in `accepted_terms` that is not a terms document of this form, and a path id that is not a uuid; `KYC_TERMS_NOT_ACCEPTED` — `accepted_terms` leaves out a terms document of the form, `details.terms` lists the ids left out, nothing is written; `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 */
21161
+ KycFormsSubmitErrors: {
18977
21162
  headers: {
18978
21163
  [name: string]: unknown;
18979
21164
  };
18980
21165
  content: {
18981
- "application/json": {
18982
- error?: {
18983
- /** @example NOT_FOUND */
18984
- code?: string;
18985
- /** @example Resource not found */
18986
- message?: string;
18987
- };
18988
- };
21166
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
21167
+ };
21168
+ };
21169
+ /** @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 */
21170
+ KycFormsConditionsCycle: {
21171
+ headers: {
21172
+ [name: string]: unknown;
21173
+ };
21174
+ content: {
21175
+ "application/json": components["schemas"]["KycFormsErrorResponse"];
21176
+ };
21177
+ };
21178
+ /** @description `SERVICE_UNAVAILABLE` — the locking service is unavailable, the operation cannot be done safely; retry later */
21179
+ KycFormsLockUnavailable: {
21180
+ headers: {
21181
+ [name: string]: unknown;
21182
+ };
21183
+ content: {
21184
+ "application/json": components["schemas"]["ErrorResponse"];
21185
+ };
21186
+ };
21187
+ /** @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) */
21188
+ KycFormsBadRequest: {
21189
+ headers: {
21190
+ [name: string]: unknown;
21191
+ };
21192
+ content: {
21193
+ "application/json": components["schemas"]["ErrorResponse"];
21194
+ };
21195
+ };
21196
+ /** @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 */
21197
+ KycFormsAccessDenied: {
21198
+ headers: {
21199
+ [name: string]: unknown;
21200
+ };
21201
+ content: {
21202
+ "application/json": components["schemas"]["ErrorResponse"];
21203
+ };
21204
+ };
21205
+ /** @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. */
21206
+ KycFormsOwnerInviteConflict: {
21207
+ headers: {
21208
+ [name: string]: unknown;
21209
+ };
21210
+ content: {
21211
+ "application/json": components["schemas"]["ErrorResponse"];
21212
+ };
21213
+ };
21214
+ /** @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`. */
21215
+ KycFormsOwnerErrors: {
21216
+ headers: {
21217
+ [name: string]: unknown;
21218
+ };
21219
+ content: {
21220
+ "application/json": components["schemas"]["ErrorResponse"];
21221
+ };
21222
+ };
21223
+ /** @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). */
21224
+ KycFormsOwnerNotFound: {
21225
+ headers: {
21226
+ [name: string]: unknown;
21227
+ };
21228
+ content: {
21229
+ "application/json": components["schemas"]["ErrorResponse"];
21230
+ };
21231
+ };
21232
+ /** @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. */
21233
+ KycFormsOwnerConflict: {
21234
+ headers: {
21235
+ [name: string]: unknown;
21236
+ };
21237
+ content: {
21238
+ "application/json": components["schemas"]["ErrorResponse"];
18989
21239
  };
18990
21240
  };
18991
21241
  };
@@ -19016,6 +21266,24 @@ export interface components {
19016
21266
  KycRailsWalletId: string;
19017
21267
  /** @description `kyc_rails.id` of the wallet's tenant */
19018
21268
  KycRailId: string;
21269
+ /** @description `kyc_entity.id` of the caller, or of an entity linked to a wallet the caller owns or administers */
21270
+ KycFormsEntityId: string;
21271
+ /** @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`. */
21272
+ KycFormsRails: string[];
21273
+ /** @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`. */
21274
+ KycFormsPrograms: string[];
21275
+ /** @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`. */
21276
+ KycFormsWalletId: string;
21277
+ /** @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`. */
21278
+ KycFormsTargetsWalletId: string;
21279
+ /** @description The `id` of a file in the draft (`saved: false`) */
21280
+ KycFormsUploadId: string;
21281
+ /** @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. */
21282
+ KycFormsLocale: string;
21283
+ /** @description Language of the texts when `locale` is not given. A language outside the tenant's list is served in English. */
21284
+ KycFormsAcceptLanguage: string;
21285
+ /** @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`). */
21286
+ KycFormsOwnerId: string;
19019
21287
  };
19020
21288
  requestBodies: never;
19021
21289
  headers: never;