squarefi-bff-api-module 1.36.35 → 1.36.37

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.
@@ -2930,6 +2930,29 @@ export interface paths {
2930
2930
  "application/json": components["schemas"]["ErrorResponse"];
2931
2931
  };
2932
2932
  };
2933
+ /** @description Card provider refused the top-up during the pre-flight allowance check
2934
+ * (`TOPUP_NOT_ALLOWED` / `TOPUP_AMOUNT_EXCEEDS_VENDOR_LIMIT`). No order
2935
+ * was created and the wallet was not debited.
2936
+ * */
2937
+ 409: {
2938
+ headers: {
2939
+ [name: string]: unknown;
2940
+ };
2941
+ content: {
2942
+ "application/json": components["schemas"]["ErrorResponse"];
2943
+ };
2944
+ };
2945
+ /** @description `TOPUP_CHECK_UNAVAILABLE` — the provider allowance check could not be
2946
+ * completed, so the top-up was refused rather than attempted.
2947
+ * */
2948
+ 503: {
2949
+ headers: {
2950
+ [name: string]: unknown;
2951
+ };
2952
+ content: {
2953
+ "application/json": components["schemas"]["ErrorResponse"];
2954
+ };
2955
+ };
2933
2956
  };
2934
2957
  };
2935
2958
  delete?: never;
@@ -3565,6 +3588,26 @@ export interface paths {
3565
3588
  };
3566
3589
  content?: never;
3567
3590
  };
3591
+ /** @description Conflict - the card provider refused the top-up during the pre-flight
3592
+ * allowance check (no order was created, the wallet was not debited):
3593
+ * - `TOPUP_NOT_ALLOWED` — provider does not allow a top-up for this account
3594
+ * - `TOPUP_AMOUNT_EXCEEDS_VENDOR_LIMIT` — amount is above the provider's cap
3595
+ * */
3596
+ 409: {
3597
+ headers: {
3598
+ [name: string]: unknown;
3599
+ };
3600
+ content?: never;
3601
+ };
3602
+ /** @description `TOPUP_CHECK_UNAVAILABLE` — the provider allowance check could not be
3603
+ * completed, so the top-up was refused rather than attempted. Retry later.
3604
+ * */
3605
+ 503: {
3606
+ headers: {
3607
+ [name: string]: unknown;
3608
+ };
3609
+ content?: never;
3610
+ };
3568
3611
  };
3569
3612
  };
3570
3613
  delete?: never;
@@ -4034,9 +4077,18 @@ export interface paths {
4034
4077
  };
4035
4078
  put?: never;
4036
4079
  /**
4037
- * Create cardholder
4038
- * @description Creates a new cardholder AND registers them at the vendor in one request.
4039
- * The `vendor_id` is resolved automatically from `issuing_program_id`.
4080
+ * Create cardholder draft
4081
+ * @description Creates a cardholder in `DRAFT` status. **No vendor is contacted here** — this is
4082
+ * step 1 of 3. The `vendor_id` is resolved automatically from `issuing_program_id`.
4083
+ *
4084
+ * **The three steps**:
4085
+ * 1. `POST /frontend/issuing/cardholders` — create the draft (this endpoint).
4086
+ * 2. `POST /frontend/issuing/cardholders/{cardholder_id}/documents` — upload the KYC
4087
+ * files as `multipart/form-data`, one request per file or all at once.
4088
+ * 3. `POST /frontend/issuing/cardholders/{cardholder_id}/submit` — register at the
4089
+ * vendor; the cardholder becomes `ACTIVE`.
4090
+ *
4091
+ * A draft cannot hold a card: card creation refuses anything that is not `ACTIVE`.
4040
4092
  *
4041
4093
  * **Authentication**: Bearer token with Authorization header and x-tenant-id header required
4042
4094
  *
@@ -4045,6 +4097,13 @@ export interface paths {
4045
4097
  *
4046
4098
  * **Uniqueness**: `email + wallet_id + issuing_program_id` must be unique (soft-deleted records excluded).
4047
4099
  *
4100
+ * **Two modes**:
4101
+ * - `user_data_id` mode: personal data + KYC documents are seeded from an existing
4102
+ * verified user (approved identity/face verification + Sumsub applicant required).
4103
+ * Manual fields only fill gaps. The Sumsub files are attached to the draft
4104
+ * immediately, so step 2 is usually unnecessary in this mode.
4105
+ * - Manual mode: `first_name`, `last_name`, `email`, `phone` are required.
4106
+ *
4048
4107
  */
4049
4108
  post: {
4050
4109
  parameters: {
@@ -4062,47 +4121,81 @@ export interface paths {
4062
4121
  */
4063
4122
  wallet_id: string;
4064
4123
  /**
4065
- * @description Cardholder's first name
4124
+ * Format: uuid
4125
+ * @description Seed personal data + KYC documents from this verified user (user_data.uuid).
4126
+ * When set, personal fields become optional and only fill gaps.
4127
+ *
4128
+ */
4129
+ user_data_id?: string;
4130
+ /**
4131
+ * @description Cardholder's first name (required in manual mode)
4066
4132
  * @example John
4067
4133
  */
4068
- first_name: string;
4134
+ first_name?: string;
4069
4135
  /**
4070
- * @description Cardholder's last name
4136
+ * @description Cardholder's last name (required in manual mode)
4071
4137
  * @example Doe
4072
4138
  */
4073
- last_name: string;
4139
+ last_name?: string;
4074
4140
  /**
4075
4141
  * Format: email
4076
- * @description Cardholder's email address
4142
+ * @description Cardholder's email address (required in manual mode)
4077
4143
  * @example john.doe@example.com
4078
4144
  */
4079
- email: string;
4145
+ email?: string;
4080
4146
  /**
4081
- * @description Cardholder's phone number in E.164 format (+ followed by 1-15 digits)
4147
+ * @description Cardholder's phone number in E.164 format (required in manual mode)
4082
4148
  * @example +14155552671
4083
4149
  */
4084
- phone: string;
4150
+ phone?: string;
4085
4151
  /**
4086
4152
  * Format: uuid
4087
4153
  * @description Issuing program ID (required). vendor_id is resolved from the program automatically.
4088
4154
  */
4089
4155
  issuing_program_id: string;
4090
- /**
4091
- * Format: uuid
4092
- * @description Sub-account ID (required for balance card vendors)
4093
- */
4094
- sub_account_id?: string;
4095
4156
  /**
4096
4157
  * Format: date
4097
- * @description Cardholder's date of birth
4158
+ * @description Cardholder's date of birth (YYYY-MM-DD)
4098
4159
  * @example 1990-01-15
4099
4160
  */
4100
- date_of_birth?: string;
4161
+ birth_date?: string;
4101
4162
  /**
4102
4163
  * @description Cardholder's nationality as ISO 3166-1 alpha-3 country code
4103
4164
  * @example USA
4104
4165
  */
4105
4166
  nationality?: string;
4167
+ /**
4168
+ * @description Cardholder's gender (required by some vendors)
4169
+ * @enum {string}
4170
+ */
4171
+ gender?: "M" | "F";
4172
+ /**
4173
+ * @description Relationship of the cardholder to the account holder
4174
+ * @enum {string}
4175
+ */
4176
+ cardholder_relationship?: "EMPLOYEE" | "CONTRACTOR";
4177
+ /**
4178
+ * @description Identity document type (KYC vendors)
4179
+ * @enum {string}
4180
+ */
4181
+ gov_id_type?: "passport" | "id_card" | "driving_license";
4182
+ /** @description Identity document number */
4183
+ gov_id_number?: string;
4184
+ /**
4185
+ * @description Issuing country of the identity document (2-3 letter code)
4186
+ * @example USA
4187
+ */
4188
+ gov_id_country?: string;
4189
+ /**
4190
+ * Format: date
4191
+ * @description Identity document issue date (YYYY-MM-DD)
4192
+ */
4193
+ gov_id_issuance_date?: string;
4194
+ /**
4195
+ * Format: date
4196
+ * @description Identity document expiry date (YYYY-MM-DD)
4197
+ */
4198
+ gov_id_expiration_date?: string;
4106
4199
  /** @description Cardholder's address */
4107
4200
  address?: {
4108
4201
  /**
@@ -4128,7 +4221,7 @@ export interface paths {
4128
4221
  };
4129
4222
  };
4130
4223
  responses: {
4131
- /** @description Cardholder created and registered at vendor successfully */
4224
+ /** @description Cardholder draft created (status DRAFT, not yet registered at the vendor) */
4132
4225
  201: {
4133
4226
  headers: {
4134
4227
  [name: string]: unknown;
@@ -4138,7 +4231,7 @@ export interface paths {
4138
4231
  /** @example true */
4139
4232
  success?: boolean;
4140
4233
  data?: components["schemas"]["IssuingCardholder"];
4141
- /** @example Cardholder created successfully */
4234
+ /** @example Cardholder draft created successfully */
4142
4235
  message?: string;
4143
4236
  };
4144
4237
  };
@@ -4352,6 +4445,19 @@ export interface paths {
4352
4445
  * @example USA
4353
4446
  */
4354
4447
  nationality?: string;
4448
+ /** @enum {string} */
4449
+ gender?: "M" | "F";
4450
+ /** @enum {string} */
4451
+ cardholder_relationship?: "EMPLOYEE" | "CONTRACTOR";
4452
+ /** @enum {string} */
4453
+ gov_id_type?: "passport" | "id_card" | "driving_license";
4454
+ gov_id_number?: string;
4455
+ /** @description 2-3 letter uppercase country code */
4456
+ gov_id_country?: string;
4457
+ /** Format: date */
4458
+ gov_id_issuance_date?: string;
4459
+ /** Format: date */
4460
+ gov_id_expiration_date?: string;
4355
4461
  address?: {
4356
4462
  line1?: string;
4357
4463
  line2?: string;
@@ -4404,40 +4510,51 @@ export interface paths {
4404
4510
  };
4405
4511
  trace?: never;
4406
4512
  };
4407
- "/frontend/kyc_persona/{wallet_id}/init": {
4513
+ "/frontend/issuing/cardholders/{cardholder_id}/submit": {
4408
4514
  parameters: {
4409
4515
  query?: never;
4410
4516
  header?: never;
4411
4517
  path?: never;
4412
4518
  cookie?: never;
4413
4519
  };
4520
+ get?: never;
4521
+ put?: never;
4414
4522
  /**
4415
- * Initialize Persona KYC session for a wallet
4416
- * @description Creates a Persona inquiry via the Auth API for the specified wallet and
4417
- * returns the hosted Persona URL. The caller's Bearer token is forwarded to
4418
- * the Auth API; access requires the caller to be a member of the wallet
4419
- * (ownership/membership is enforced by the standard wallet-access check).
4523
+ * Submit cardholder draft
4524
+ * @description Registers a `DRAFT` cardholder at the vendor and flips it to `ACTIVE` — step 3 of the
4525
+ * create flow. The vendor is resolved from the cardholder's issuing program.
4526
+ *
4527
+ * **Dossier check**: the submit is refused with `400
4528
+ * CARDHOLDER_SUBMISSION_INCOMPLETE` while the program's KYC level is not met.
4529
+ * `error.details.missing` lists every field and file still needed (e.g. `gender`,
4530
+ * `documents: selfie`), so the client can complete it and retry.
4531
+ *
4532
+ * **Retryable**: a failed submit leaves the draft untouched. Nothing is rolled back,
4533
+ * and the same endpoint can be called again once the dossier is complete.
4534
+ *
4535
+ * **Idempotency**: submitting an already-active cardholder returns `409
4536
+ * CARDHOLDER_NOT_DRAFT` rather than registering it twice.
4420
4537
  *
4421
4538
  * **Authentication**: Bearer token with x-tenant-id header required
4422
4539
  *
4423
- * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
4540
+ * **Access Control**: Cardholder must belong to the user's wallet (admin role)
4424
4541
  *
4425
4542
  */
4426
- get: {
4543
+ post: {
4427
4544
  parameters: {
4428
4545
  query: {
4429
- type: "individual" | "business";
4546
+ /** @description Wallet ID for access validation */
4547
+ wallet_id: string;
4430
4548
  };
4431
4549
  header?: never;
4432
4550
  path: {
4433
- /** @description Wallet UUID */
4434
- wallet_id: string;
4551
+ cardholder_id: string;
4435
4552
  };
4436
4553
  cookie?: never;
4437
4554
  };
4438
4555
  requestBody?: never;
4439
4556
  responses: {
4440
- /** @description Persona link generated successfully */
4557
+ /** @description Cardholder registered at the vendor and activated */
4441
4558
  200: {
4442
4559
  headers: {
4443
4560
  [name: string]: unknown;
@@ -4445,37 +4562,14 @@ export interface paths {
4445
4562
  content: {
4446
4563
  "application/json": {
4447
4564
  /** @example true */
4448
- success: boolean;
4449
- data: {
4450
- /**
4451
- * Format: uuid
4452
- * @description Echo of the wallet from the path
4453
- * @example eaf37846-3669-4b4a-9555-b27f75e023c1
4454
- */
4455
- wallet_id: string;
4456
- /**
4457
- * @description Persona inquiry ID returned by the Auth API
4458
- * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4459
- */
4460
- inquiry_id: string;
4461
- /**
4462
- * @description Persona session token, when upstream returns one — otherwise null
4463
- * @example null
4464
- */
4465
- session_id: string | null;
4466
- /**
4467
- * Format: uri
4468
- * @description Hosted Persona URL with `inquiry-id` (and `session-token` if `session_id` is present).
4469
- * Base host: `PERSONA_HOSTED_FLOW_URL` env, default `https://withpersona.com/verify`.
4470
- *
4471
- * @example https://withpersona.com/verify?inquiry-id=inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4472
- */
4473
- url: string;
4474
- };
4565
+ success?: boolean;
4566
+ data?: components["schemas"]["IssuingCardholder"];
4567
+ /** @example Cardholder submitted successfully */
4568
+ message?: string;
4475
4569
  };
4476
4570
  };
4477
4571
  };
4478
- /** @description Validation error (`type` missing or not in [individual, business]) */
4572
+ /** @description KYC dossier incomplete, or the program has no vendor configured */
4479
4573
  400: {
4480
4574
  headers: {
4481
4575
  [name: string]: unknown;
@@ -4484,179 +4578,220 @@ export interface paths {
4484
4578
  "application/json": components["schemas"]["ErrorResponse"];
4485
4579
  };
4486
4580
  };
4487
- /** @description Missing or invalid Bearer token */
4488
- 401: {
4581
+ /** @description Access denied to this cardholder */
4582
+ 403: {
4489
4583
  headers: {
4490
4584
  [name: string]: unknown;
4491
4585
  };
4492
- content: {
4493
- "application/json": components["schemas"]["ErrorResponse"];
4494
- };
4586
+ content?: never;
4495
4587
  };
4496
- /** @description Caller has no access to this wallet */
4497
- 403: {
4588
+ /** @description Cardholder not found */
4589
+ 404: {
4498
4590
  headers: {
4499
4591
  [name: string]: unknown;
4500
4592
  };
4501
- content: {
4502
- "application/json": components["schemas"]["ErrorResponse"];
4503
- };
4593
+ content?: never;
4504
4594
  };
4505
- /** @description Auth API responded 404 (wallet not found upstream) */
4506
- 404: {
4595
+ /** @description Cardholder is not a draft (already submitted) */
4596
+ 409: {
4507
4597
  headers: {
4508
4598
  [name: string]: unknown;
4509
4599
  };
4510
- content: {
4511
- "application/json": components["schemas"]["ErrorResponse"];
4512
- };
4600
+ content?: never;
4513
4601
  };
4514
- /** @description Auth API unavailable, timed out, or returned malformed payload */
4602
+ /** @description Vendor rejected the registration; the draft is kept */
4515
4603
  502: {
4516
4604
  headers: {
4517
4605
  [name: string]: unknown;
4518
4606
  };
4519
- content: {
4520
- "application/json": components["schemas"]["ErrorResponse"];
4521
- };
4607
+ content?: never;
4522
4608
  };
4523
4609
  };
4524
4610
  };
4525
- put?: never;
4526
- post?: never;
4527
4611
  delete?: never;
4528
4612
  options?: never;
4529
4613
  head?: never;
4530
4614
  patch?: never;
4531
4615
  trace?: never;
4532
4616
  };
4533
- "/frontend/kyc_persona/{wallet_id}/resume": {
4617
+ "/frontend/issuing/cardholder-documents": {
4534
4618
  parameters: {
4535
4619
  query?: never;
4536
4620
  header?: never;
4537
4621
  path?: never;
4538
4622
  cookie?: never;
4539
4623
  };
4624
+ get?: never;
4625
+ put?: never;
4540
4626
  /**
4541
- * Resume Persona KYC session for a wallet
4542
- * @description Resumes an existing Persona inquiry via the Auth API for the specified
4543
- * wallet and returns the hosted Persona URL. The caller's Bearer token is
4544
- * forwarded to the Auth API; access requires the caller to be a member of
4545
- * the wallet (ownership/membership is enforced by the standard wallet-access check).
4627
+ * Upload KYC document files
4628
+ * @description Uploads KYC files against a wallet via `multipart/form-data`, with no
4629
+ * cardholder involved — the upload step of the create flow runs before the
4630
+ * cardholder exists. The form field name is the document type (`selfie`,
4631
+ * `gov_id_front`, `gov_id_back`); one file per type, 5MB max each, formats
4632
+ * png/jpeg/pdf.
4633
+ *
4634
+ * Send one file per request so the UI can show progress per file and retry
4635
+ * a single file. The response returns an `id` per file; pass those ids to
4636
+ * `POST /frontend/issuing/cardholders/{cardholder_id}/documents` to attach
4637
+ * them to a draft.
4638
+ *
4639
+ * Do not set `Content-Type` manually — the browser must add the multipart
4640
+ * boundary itself, and the file has to be appended as a `File`/`Blob`, not
4641
+ * as a name or a base64 string.
4642
+ *
4643
+ * An upload that is never attached is deleted by a cleanup sweep.
4546
4644
  *
4547
4645
  * **Authentication**: Bearer token with x-tenant-id header required
4548
4646
  *
4549
- * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
4647
+ * **Access Control**: wallet admin role
4550
4648
  *
4551
4649
  */
4552
- get: {
4650
+ post: {
4553
4651
  parameters: {
4554
4652
  query: {
4555
- inquiry_id: string;
4556
- };
4557
- header?: never;
4558
- path: {
4559
- /** @description Wallet UUID */
4653
+ /** @description Wallet ID for access validation */
4560
4654
  wallet_id: string;
4561
4655
  };
4656
+ header?: never;
4657
+ path?: never;
4562
4658
  cookie?: never;
4563
4659
  };
4564
- requestBody?: never;
4660
+ requestBody: {
4661
+ content: {
4662
+ "multipart/form-data": {
4663
+ /**
4664
+ * Format: binary
4665
+ * @description Identity photo / selfie
4666
+ */
4667
+ selfie?: string;
4668
+ /**
4669
+ * Format: binary
4670
+ * @description Government ID, front side
4671
+ */
4672
+ gov_id_front?: string;
4673
+ /**
4674
+ * Format: binary
4675
+ * @description Government ID, back side
4676
+ */
4677
+ gov_id_back?: string;
4678
+ };
4679
+ };
4680
+ };
4565
4681
  responses: {
4566
- /** @description Persona link generated successfully */
4567
- 200: {
4682
+ /** @description Files stored; returns one upload per file */
4683
+ 201: {
4568
4684
  headers: {
4569
4685
  [name: string]: unknown;
4570
4686
  };
4571
4687
  content: {
4572
4688
  "application/json": {
4573
4689
  /** @example true */
4574
- success: boolean;
4575
- data: {
4576
- /**
4577
- * Format: uuid
4578
- * @description Echo of the wallet from the path
4579
- * @example eaf37846-3669-4b4a-9555-b27f75e023c1
4580
- */
4581
- wallet_id: string;
4582
- /**
4583
- * @description Persona inquiry ID returned by the Auth API (same as the one being resumed)
4584
- * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4585
- */
4586
- inquiry_id: string;
4587
- /**
4588
- * @description Persona session token, when upstream returns one — otherwise null
4589
- * @example null
4590
- */
4591
- session_id: string | null;
4592
- /**
4593
- * Format: uri
4594
- * @description Hosted Persona URL with `inquiry-id` (and `session-token` if `session_id` is present).
4595
- * Base host: `PERSONA_HOSTED_FLOW_URL` env, default `https://withpersona.com/verify`.
4596
- *
4597
- * @example https://withpersona.com/verify?inquiry-id=inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4598
- */
4599
- url: string;
4690
+ success?: boolean;
4691
+ /** @example Documents uploaded successfully */
4692
+ message?: string;
4693
+ data?: {
4694
+ documents?: {
4695
+ /** Format: uuid */
4696
+ id?: string;
4697
+ /** @enum {string} */
4698
+ type?: "selfie" | "gov_id_front" | "gov_id_back";
4699
+ filename?: string | null;
4700
+ content_type?: string;
4701
+ size?: number;
4702
+ /** Format: date-time */
4703
+ created_at?: string;
4704
+ }[];
4600
4705
  };
4601
4706
  };
4602
4707
  };
4603
4708
  };
4604
- /** @description Validation error (`inquiry_id` missing or empty) */
4709
+ /** @description No file parts, unsupported field/type, or a file exceeds 5MB */
4605
4710
  400: {
4606
4711
  headers: {
4607
4712
  [name: string]: unknown;
4608
4713
  };
4609
- content: {
4610
- "application/json": components["schemas"]["ErrorResponse"];
4611
- };
4612
- };
4613
- /** @description Missing or invalid Bearer token */
4614
- 401: {
4615
- headers: {
4616
- [name: string]: unknown;
4617
- };
4618
- content: {
4619
- "application/json": components["schemas"]["ErrorResponse"];
4620
- };
4714
+ content?: never;
4621
4715
  };
4622
- /** @description Caller has no access to this wallet */
4716
+ /** @description Access denied to this wallet */
4623
4717
  403: {
4624
4718
  headers: {
4625
4719
  [name: string]: unknown;
4626
4720
  };
4627
- content: {
4628
- "application/json": components["schemas"]["ErrorResponse"];
4629
- };
4630
- };
4631
- /** @description Auth API responded 404 (no such inquiry to resume) */
4632
- 404: {
4633
- headers: {
4634
- [name: string]: unknown;
4635
- };
4636
- content: {
4637
- "application/json": components["schemas"]["ErrorResponse"];
4638
- };
4721
+ content?: never;
4639
4722
  };
4640
- /** @description Auth API unavailable, timed out, or returned malformed payload */
4641
- 502: {
4642
- headers: {
4643
- [name: string]: unknown;
4723
+ };
4724
+ };
4725
+ delete?: never;
4726
+ options?: never;
4727
+ head?: never;
4728
+ patch?: never;
4729
+ trace?: never;
4730
+ };
4731
+ "/frontend/issuing/cardholder-documents/{document_id}": {
4732
+ parameters: {
4733
+ query?: never;
4734
+ header?: never;
4735
+ path?: never;
4736
+ cookie?: never;
4737
+ };
4738
+ get?: never;
4739
+ put?: never;
4740
+ post?: never;
4741
+ /**
4742
+ * Discard an uploaded file
4743
+ * @description Deletes an upload that has not been attached to a cardholder yet — the
4744
+ * "remove this file" action of the upload form. Attached documents are
4745
+ * refused with 409; replace them by attaching a new file of the same type.
4746
+ *
4747
+ * **Authentication**: Bearer token with x-tenant-id header required
4748
+ *
4749
+ * **Access Control**: wallet admin role
4750
+ *
4751
+ */
4752
+ delete: {
4753
+ parameters: {
4754
+ query: {
4755
+ /** @description Wallet ID for access validation */
4756
+ wallet_id: string;
4757
+ };
4758
+ header?: never;
4759
+ path: {
4760
+ document_id: string;
4761
+ };
4762
+ cookie?: never;
4763
+ };
4764
+ requestBody?: never;
4765
+ responses: {
4766
+ /** @description Upload discarded */
4767
+ 200: {
4768
+ headers: {
4769
+ [name: string]: unknown;
4644
4770
  };
4645
- content: {
4646
- "application/json": components["schemas"]["ErrorResponse"];
4771
+ content?: never;
4772
+ };
4773
+ /** @description Upload not found for this wallet */
4774
+ 404: {
4775
+ headers: {
4776
+ [name: string]: unknown;
4777
+ };
4778
+ content?: never;
4779
+ };
4780
+ /** @description Upload is already attached to a cardholder */
4781
+ 409: {
4782
+ headers: {
4783
+ [name: string]: unknown;
4647
4784
  };
4785
+ content?: never;
4648
4786
  };
4649
4787
  };
4650
4788
  };
4651
- put?: never;
4652
- post?: never;
4653
- delete?: never;
4654
4789
  options?: never;
4655
4790
  head?: never;
4656
4791
  patch?: never;
4657
4792
  trace?: never;
4658
4793
  };
4659
- "/frontend/kyc_verification/{wallet_id}/init": {
4794
+ "/frontend/issuing/cardholders/{cardholder_id}/documents": {
4660
4795
  parameters: {
4661
4796
  query?: never;
4662
4797
  header?: never;
@@ -4666,45 +4801,130 @@ export interface paths {
4666
4801
  get?: never;
4667
4802
  put?: never;
4668
4803
  /**
4669
- * Initialize KYC verification for a wallet
4670
- * @description Starts a provider-agnostic KYC data-collection flow for the wallet via
4671
- * the Auth API. The KYC provider (Persona, Sumsub, …) is resolved
4672
- * internally per tenant — the caller does not choose it. Returns the
4673
- * provider verification id plus an optional short-lived SDK token the
4674
- * client uses to launch the verification. The caller's Bearer token is
4675
- * forwarded to the Auth API.
4804
+ * Attach uploaded KYC documents to a cardholder
4805
+ * @description Attaches files already uploaded via
4806
+ * `POST /frontend/issuing/cardholder-documents` to this cardholder. The
4807
+ * body carries upload ids only — no file bytes travel here.
4676
4808
  *
4677
- * Provider-agnostic replacement for the deprecated
4678
- * `GET /frontend/kyc_persona/{wallet_id}/init`.
4809
+ * A document of a type the cardholder already has replaces the previous
4810
+ * one, and the superseded file is deleted. An upload can only be attached
4811
+ * once, and only to a cardholder in the wallet it was uploaded for.
4812
+ *
4813
+ * Documents are not pushed to the vendor here; they travel at
4814
+ * `POST /cardholders/{cardholder_id}/submit`.
4679
4815
  *
4680
4816
  * **Authentication**: Bearer token with x-tenant-id header required
4681
4817
  *
4682
- * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
4818
+ * **Access Control**: Cardholder must belong to the user's wallet (admin role)
4683
4819
  *
4684
4820
  */
4685
4821
  post: {
4686
4822
  parameters: {
4687
- query?: never;
4823
+ query: {
4824
+ /** @description Wallet ID for access validation */
4825
+ wallet_id: string;
4826
+ };
4688
4827
  header?: never;
4689
4828
  path: {
4690
- /** @description Wallet UUID */
4691
- wallet_id: string;
4829
+ cardholder_id: string;
4692
4830
  };
4693
4831
  cookie?: never;
4694
4832
  };
4695
4833
  requestBody: {
4696
4834
  content: {
4697
4835
  "application/json": {
4698
- /**
4699
- * @description KYC entity type
4700
- * @enum {string}
4701
- */
4702
- type: "individual" | "business";
4836
+ /** @description Ids returned by the upload endpoint */
4837
+ document_ids: string[];
4703
4838
  };
4704
4839
  };
4705
4840
  };
4706
4841
  responses: {
4707
- /** @description KYC verification initialized */
4842
+ /** @description Documents attached; returns the updated cardholder */
4843
+ 200: {
4844
+ headers: {
4845
+ [name: string]: unknown;
4846
+ };
4847
+ content: {
4848
+ "application/json": {
4849
+ /** @example true */
4850
+ success?: boolean;
4851
+ /** @example Documents attached successfully */
4852
+ message?: string;
4853
+ /** @description Updated cardholder with refreshed kyc_documents */
4854
+ data?: Record<string, never>;
4855
+ };
4856
+ };
4857
+ };
4858
+ /** @description document_ids missing, empty, or listing two files of one type */
4859
+ 400: {
4860
+ headers: {
4861
+ [name: string]: unknown;
4862
+ };
4863
+ content?: never;
4864
+ };
4865
+ /** @description Access denied to this cardholder */
4866
+ 403: {
4867
+ headers: {
4868
+ [name: string]: unknown;
4869
+ };
4870
+ content?: never;
4871
+ };
4872
+ /** @description Cardholder or upload id not found */
4873
+ 404: {
4874
+ headers: {
4875
+ [name: string]: unknown;
4876
+ };
4877
+ content?: never;
4878
+ };
4879
+ /** @description An upload is already attached to a cardholder */
4880
+ 409: {
4881
+ headers: {
4882
+ [name: string]: unknown;
4883
+ };
4884
+ content?: never;
4885
+ };
4886
+ };
4887
+ };
4888
+ delete?: never;
4889
+ options?: never;
4890
+ head?: never;
4891
+ patch?: never;
4892
+ trace?: never;
4893
+ };
4894
+ "/frontend/kyc_persona/{wallet_id}/init": {
4895
+ parameters: {
4896
+ query?: never;
4897
+ header?: never;
4898
+ path?: never;
4899
+ cookie?: never;
4900
+ };
4901
+ /**
4902
+ * Initialize Persona KYC session for a wallet
4903
+ * @description Creates a Persona inquiry via the Auth API for the specified wallet and
4904
+ * returns the hosted Persona URL. The caller's Bearer token is forwarded to
4905
+ * the Auth API; access requires the caller to be a member of the wallet
4906
+ * (ownership/membership is enforced by the standard wallet-access check).
4907
+ *
4908
+ * **Authentication**: Bearer token with x-tenant-id header required
4909
+ *
4910
+ * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
4911
+ *
4912
+ */
4913
+ get: {
4914
+ parameters: {
4915
+ query: {
4916
+ type: "individual" | "business";
4917
+ };
4918
+ header?: never;
4919
+ path: {
4920
+ /** @description Wallet UUID */
4921
+ wallet_id: string;
4922
+ };
4923
+ cookie?: never;
4924
+ };
4925
+ requestBody?: never;
4926
+ responses: {
4927
+ /** @description Persona link generated successfully */
4708
4928
  200: {
4709
4929
  headers: {
4710
4930
  [name: string]: unknown;
@@ -4717,20 +4937,27 @@ export interface paths {
4717
4937
  /**
4718
4938
  * Format: uuid
4719
4939
  * @description Echo of the wallet from the path
4940
+ * @example eaf37846-3669-4b4a-9555-b27f75e023c1
4720
4941
  */
4721
4942
  wallet_id: string;
4722
4943
  /**
4723
- * @description Provider that handled the flow (e.g. persona, sumsub)
4724
- * @example persona
4944
+ * @description Persona inquiry ID returned by the Auth API
4945
+ * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4725
4946
  */
4726
- provider_type: string;
4947
+ inquiry_id: string;
4727
4948
  /**
4728
- * @description Provider verification id — Persona: inquiryId, Sumsub: applicantId
4729
- * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4949
+ * @description Persona session token, when upstream returns one — otherwise null
4950
+ * @example null
4730
4951
  */
4731
- verification_id: string;
4732
- /** @description Short-lived SDK/session token when the provider mints one — otherwise null */
4733
- verification_token?: string | null;
4952
+ session_id: string | null;
4953
+ /**
4954
+ * Format: uri
4955
+ * @description Hosted Persona URL with `inquiry-id` (and `session-token` if `session_id` is present).
4956
+ * Base host: `PERSONA_HOSTED_FLOW_URL` env, default `https://withpersona.com/verify`.
4957
+ *
4958
+ * @example https://withpersona.com/verify?inquiry-id=inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4959
+ */
4960
+ url: string;
4734
4961
  };
4735
4962
  };
4736
4963
  };
@@ -4762,7 +4989,7 @@ export interface paths {
4762
4989
  "application/json": components["schemas"]["ErrorResponse"];
4763
4990
  };
4764
4991
  };
4765
- /** @description Wallet not found upstream */
4992
+ /** @description Auth API responded 404 (wallet not found upstream) */
4766
4993
  404: {
4767
4994
  headers: {
4768
4995
  [name: string]: unknown;
@@ -4771,7 +4998,7 @@ export interface paths {
4771
4998
  "application/json": components["schemas"]["ErrorResponse"];
4772
4999
  };
4773
5000
  };
4774
- /** @description Auth API unavailable, timed out, or returned a malformed payload */
5001
+ /** @description Auth API unavailable, timed out, or returned malformed payload */
4775
5002
  502: {
4776
5003
  headers: {
4777
5004
  [name: string]: unknown;
@@ -4782,40 +5009,38 @@ export interface paths {
4782
5009
  };
4783
5010
  };
4784
5011
  };
5012
+ put?: never;
5013
+ post?: never;
4785
5014
  delete?: never;
4786
5015
  options?: never;
4787
5016
  head?: never;
4788
5017
  patch?: never;
4789
5018
  trace?: never;
4790
5019
  };
4791
- "/frontend/kyc_verification/{wallet_id}/resume": {
5020
+ "/frontend/kyc_persona/{wallet_id}/resume": {
4792
5021
  parameters: {
4793
5022
  query?: never;
4794
5023
  header?: never;
4795
5024
  path?: never;
4796
5025
  cookie?: never;
4797
5026
  };
4798
- get?: never;
4799
- put?: never;
4800
5027
  /**
4801
- * Resume KYC verification for a wallet
4802
- * @description Resumes an existing provider-agnostic KYC data-collection flow for the
4803
- * wallet via the Auth API. The provider is resolved internally per tenant.
4804
- * `verification_ref` is the provider reference returned by init (Persona:
4805
- * `inquiry_id`, Sumsub: `applicant_id`). The caller's Bearer token is
4806
- * forwarded to the Auth API.
4807
- *
4808
- * Provider-agnostic replacement for the deprecated
4809
- * `GET /frontend/kyc_persona/{wallet_id}/resume`.
5028
+ * Resume Persona KYC session for a wallet
5029
+ * @description Resumes an existing Persona inquiry via the Auth API for the specified
5030
+ * wallet and returns the hosted Persona URL. The caller's Bearer token is
5031
+ * forwarded to the Auth API; access requires the caller to be a member of
5032
+ * the wallet (ownership/membership is enforced by the standard wallet-access check).
4810
5033
  *
4811
5034
  * **Authentication**: Bearer token with x-tenant-id header required
4812
5035
  *
4813
5036
  * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
4814
5037
  *
4815
5038
  */
4816
- post: {
5039
+ get: {
4817
5040
  parameters: {
4818
- query?: never;
5041
+ query: {
5042
+ inquiry_id: string;
5043
+ };
4819
5044
  header?: never;
4820
5045
  path: {
4821
5046
  /** @description Wallet UUID */
@@ -4823,19 +5048,9 @@ export interface paths {
4823
5048
  };
4824
5049
  cookie?: never;
4825
5050
  };
4826
- requestBody: {
4827
- content: {
4828
- "application/json": {
4829
- /**
4830
- * @description Provider verification reference (Persona: inquiry_id, Sumsub: applicant_id)
4831
- * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4832
- */
4833
- verification_ref: string;
4834
- };
4835
- };
4836
- };
5051
+ requestBody?: never;
4837
5052
  responses: {
4838
- /** @description KYC verification resumed */
5053
+ /** @description Persona link generated successfully */
4839
5054
  200: {
4840
5055
  headers: {
4841
5056
  [name: string]: unknown;
@@ -4848,25 +5063,32 @@ export interface paths {
4848
5063
  /**
4849
5064
  * Format: uuid
4850
5065
  * @description Echo of the wallet from the path
5066
+ * @example eaf37846-3669-4b4a-9555-b27f75e023c1
4851
5067
  */
4852
5068
  wallet_id: string;
4853
5069
  /**
4854
- * @description Provider that handled the flow (e.g. persona, sumsub)
4855
- * @example persona
5070
+ * @description Persona inquiry ID returned by the Auth API (same as the one being resumed)
5071
+ * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
4856
5072
  */
4857
- provider_type: string;
5073
+ inquiry_id: string;
4858
5074
  /**
4859
- * @description Provider verification id — Persona: inquiryId, Sumsub: applicantId
4860
- * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
5075
+ * @description Persona session token, when upstream returns one — otherwise null
5076
+ * @example null
4861
5077
  */
4862
- verification_id: string;
4863
- /** @description Short-lived SDK/session token when the provider mints one — otherwise null */
4864
- verification_token?: string | null;
5078
+ session_id: string | null;
5079
+ /**
5080
+ * Format: uri
5081
+ * @description Hosted Persona URL with `inquiry-id` (and `session-token` if `session_id` is present).
5082
+ * Base host: `PERSONA_HOSTED_FLOW_URL` env, default `https://withpersona.com/verify`.
5083
+ *
5084
+ * @example https://withpersona.com/verify?inquiry-id=inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
5085
+ */
5086
+ url: string;
4865
5087
  };
4866
5088
  };
4867
5089
  };
4868
5090
  };
4869
- /** @description Validation error (`verification_ref` missing or empty) */
5091
+ /** @description Validation error (`inquiry_id` missing or empty) */
4870
5092
  400: {
4871
5093
  headers: {
4872
5094
  [name: string]: unknown;
@@ -4893,7 +5115,141 @@ export interface paths {
4893
5115
  "application/json": components["schemas"]["ErrorResponse"];
4894
5116
  };
4895
5117
  };
4896
- /** @description No such verification to resume upstream */
5118
+ /** @description Auth API responded 404 (no such inquiry to resume) */
5119
+ 404: {
5120
+ headers: {
5121
+ [name: string]: unknown;
5122
+ };
5123
+ content: {
5124
+ "application/json": components["schemas"]["ErrorResponse"];
5125
+ };
5126
+ };
5127
+ /** @description Auth API unavailable, timed out, or returned malformed payload */
5128
+ 502: {
5129
+ headers: {
5130
+ [name: string]: unknown;
5131
+ };
5132
+ content: {
5133
+ "application/json": components["schemas"]["ErrorResponse"];
5134
+ };
5135
+ };
5136
+ };
5137
+ };
5138
+ put?: never;
5139
+ post?: never;
5140
+ delete?: never;
5141
+ options?: never;
5142
+ head?: never;
5143
+ patch?: never;
5144
+ trace?: never;
5145
+ };
5146
+ "/frontend/kyc_verification/{wallet_id}/init": {
5147
+ parameters: {
5148
+ query?: never;
5149
+ header?: never;
5150
+ path?: never;
5151
+ cookie?: never;
5152
+ };
5153
+ get?: never;
5154
+ put?: never;
5155
+ /**
5156
+ * Initialize KYC verification for a wallet
5157
+ * @description Starts a provider-agnostic KYC data-collection flow for the wallet via
5158
+ * the Auth API. The KYC provider (Persona, Sumsub, …) is resolved
5159
+ * internally per tenant — the caller does not choose it. Returns the
5160
+ * provider verification id plus an optional short-lived SDK token the
5161
+ * client uses to launch the verification. The caller's Bearer token is
5162
+ * forwarded to the Auth API.
5163
+ *
5164
+ * Provider-agnostic replacement for the deprecated
5165
+ * `GET /frontend/kyc_persona/{wallet_id}/init`.
5166
+ *
5167
+ * **Authentication**: Bearer token with x-tenant-id header required
5168
+ *
5169
+ * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
5170
+ *
5171
+ */
5172
+ post: {
5173
+ parameters: {
5174
+ query?: never;
5175
+ header?: never;
5176
+ path: {
5177
+ /** @description Wallet UUID */
5178
+ wallet_id: string;
5179
+ };
5180
+ cookie?: never;
5181
+ };
5182
+ requestBody: {
5183
+ content: {
5184
+ "application/json": {
5185
+ /**
5186
+ * @description KYC entity type
5187
+ * @enum {string}
5188
+ */
5189
+ type: "individual" | "business";
5190
+ };
5191
+ };
5192
+ };
5193
+ responses: {
5194
+ /** @description KYC verification initialized */
5195
+ 200: {
5196
+ headers: {
5197
+ [name: string]: unknown;
5198
+ };
5199
+ content: {
5200
+ "application/json": {
5201
+ /** @example true */
5202
+ success: boolean;
5203
+ data: {
5204
+ /**
5205
+ * Format: uuid
5206
+ * @description Echo of the wallet from the path
5207
+ */
5208
+ wallet_id: string;
5209
+ /**
5210
+ * @description Provider that handled the flow (e.g. persona, sumsub)
5211
+ * @example persona
5212
+ */
5213
+ provider_type: string;
5214
+ /**
5215
+ * @description Provider verification id — Persona: inquiryId, Sumsub: applicantId
5216
+ * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
5217
+ */
5218
+ verification_id: string;
5219
+ /** @description Short-lived SDK/session token when the provider mints one — otherwise null */
5220
+ verification_token?: string | null;
5221
+ };
5222
+ };
5223
+ };
5224
+ };
5225
+ /** @description Validation error (`type` missing or not in [individual, business]) */
5226
+ 400: {
5227
+ headers: {
5228
+ [name: string]: unknown;
5229
+ };
5230
+ content: {
5231
+ "application/json": components["schemas"]["ErrorResponse"];
5232
+ };
5233
+ };
5234
+ /** @description Missing or invalid Bearer token */
5235
+ 401: {
5236
+ headers: {
5237
+ [name: string]: unknown;
5238
+ };
5239
+ content: {
5240
+ "application/json": components["schemas"]["ErrorResponse"];
5241
+ };
5242
+ };
5243
+ /** @description Caller has no access to this wallet */
5244
+ 403: {
5245
+ headers: {
5246
+ [name: string]: unknown;
5247
+ };
5248
+ content: {
5249
+ "application/json": components["schemas"]["ErrorResponse"];
5250
+ };
5251
+ };
5252
+ /** @description Wallet not found upstream */
4897
5253
  404: {
4898
5254
  headers: {
4899
5255
  [name: string]: unknown;
@@ -4919,31 +5275,534 @@ export interface paths {
4919
5275
  patch?: never;
4920
5276
  trace?: never;
4921
5277
  };
4922
- "/frontend/mass-payouts/{wallet_id}": {
5278
+ "/frontend/kyc_verification/{wallet_id}/resume": {
5279
+ parameters: {
5280
+ query?: never;
5281
+ header?: never;
5282
+ path?: never;
5283
+ cookie?: never;
5284
+ };
5285
+ get?: never;
5286
+ put?: never;
5287
+ /**
5288
+ * Resume KYC verification for a wallet
5289
+ * @description Resumes an existing provider-agnostic KYC data-collection flow for the
5290
+ * wallet via the Auth API. The provider is resolved internally per tenant.
5291
+ * `verification_ref` is the provider reference returned by init (Persona:
5292
+ * `inquiry_id`, Sumsub: `applicant_id`). The caller's Bearer token is
5293
+ * forwarded to the Auth API.
5294
+ *
5295
+ * Provider-agnostic replacement for the deprecated
5296
+ * `GET /frontend/kyc_persona/{wallet_id}/resume`.
5297
+ *
5298
+ * **Authentication**: Bearer token with x-tenant-id header required
5299
+ *
5300
+ * **Access Control**: Any user with access to the wallet (scoped card-users excluded)
5301
+ *
5302
+ */
5303
+ post: {
5304
+ parameters: {
5305
+ query?: never;
5306
+ header?: never;
5307
+ path: {
5308
+ /** @description Wallet UUID */
5309
+ wallet_id: string;
5310
+ };
5311
+ cookie?: never;
5312
+ };
5313
+ requestBody: {
5314
+ content: {
5315
+ "application/json": {
5316
+ /**
5317
+ * @description Provider verification reference (Persona: inquiry_id, Sumsub: applicant_id)
5318
+ * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
5319
+ */
5320
+ verification_ref: string;
5321
+ };
5322
+ };
5323
+ };
5324
+ responses: {
5325
+ /** @description KYC verification resumed */
5326
+ 200: {
5327
+ headers: {
5328
+ [name: string]: unknown;
5329
+ };
5330
+ content: {
5331
+ "application/json": {
5332
+ /** @example true */
5333
+ success: boolean;
5334
+ data: {
5335
+ /**
5336
+ * Format: uuid
5337
+ * @description Echo of the wallet from the path
5338
+ */
5339
+ wallet_id: string;
5340
+ /**
5341
+ * @description Provider that handled the flow (e.g. persona, sumsub)
5342
+ * @example persona
5343
+ */
5344
+ provider_type: string;
5345
+ /**
5346
+ * @description Provider verification id — Persona: inquiryId, Sumsub: applicantId
5347
+ * @example inq_ABDNxhp9ZzD3yehivCbMVvmjwh5g5r
5348
+ */
5349
+ verification_id: string;
5350
+ /** @description Short-lived SDK/session token when the provider mints one — otherwise null */
5351
+ verification_token?: string | null;
5352
+ };
5353
+ };
5354
+ };
5355
+ };
5356
+ /** @description Validation error (`verification_ref` missing or empty) */
5357
+ 400: {
5358
+ headers: {
5359
+ [name: string]: unknown;
5360
+ };
5361
+ content: {
5362
+ "application/json": components["schemas"]["ErrorResponse"];
5363
+ };
5364
+ };
5365
+ /** @description Missing or invalid Bearer token */
5366
+ 401: {
5367
+ headers: {
5368
+ [name: string]: unknown;
5369
+ };
5370
+ content: {
5371
+ "application/json": components["schemas"]["ErrorResponse"];
5372
+ };
5373
+ };
5374
+ /** @description Caller has no access to this wallet */
5375
+ 403: {
5376
+ headers: {
5377
+ [name: string]: unknown;
5378
+ };
5379
+ content: {
5380
+ "application/json": components["schemas"]["ErrorResponse"];
5381
+ };
5382
+ };
5383
+ /** @description No such verification to resume upstream */
5384
+ 404: {
5385
+ headers: {
5386
+ [name: string]: unknown;
5387
+ };
5388
+ content: {
5389
+ "application/json": components["schemas"]["ErrorResponse"];
5390
+ };
5391
+ };
5392
+ /** @description Auth API unavailable, timed out, or returned a malformed payload */
5393
+ 502: {
5394
+ headers: {
5395
+ [name: string]: unknown;
5396
+ };
5397
+ content: {
5398
+ "application/json": components["schemas"]["ErrorResponse"];
5399
+ };
5400
+ };
5401
+ };
5402
+ };
5403
+ delete?: never;
5404
+ options?: never;
5405
+ head?: never;
5406
+ patch?: never;
5407
+ trace?: never;
5408
+ };
5409
+ "/frontend/mass-payouts/{wallet_id}": {
5410
+ parameters: {
5411
+ query?: never;
5412
+ header?: never;
5413
+ path?: never;
5414
+ cookie?: never;
5415
+ };
5416
+ /** List mass payouts of a wallet */
5417
+ get: {
5418
+ parameters: {
5419
+ query?: {
5420
+ status?: "DRAFT" | "PENDING_APPROVAL" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
5421
+ limit?: number;
5422
+ offset?: number;
5423
+ };
5424
+ header?: never;
5425
+ path: {
5426
+ /** @description Source wallet the batches belong to */
5427
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
5428
+ };
5429
+ cookie?: never;
5430
+ };
5431
+ requestBody?: never;
5432
+ responses: {
5433
+ /** @description Page of batches, newest first */
5434
+ 200: {
5435
+ headers: {
5436
+ [name: string]: unknown;
5437
+ };
5438
+ content: {
5439
+ "application/json": {
5440
+ /** @example true */
5441
+ success?: boolean;
5442
+ data?: {
5443
+ items?: components["schemas"]["MassPayout"][];
5444
+ total?: number;
5445
+ limit?: number;
5446
+ offset?: number;
5447
+ };
5448
+ };
5449
+ };
5450
+ };
5451
+ };
5452
+ };
5453
+ put?: never;
5454
+ /**
5455
+ * Create a mass payout draft
5456
+ * @description Creates a batch of payouts to existing counterparty destinations: one
5457
+ * source wallet, one currency, up to the tenant's batch-size limit of
5458
+ * recipients (default 100). The draft can be freely edited and
5459
+ * previewed; nothing moves until it is submitted and approved.
5460
+ * `virtual_account_id` is required only when the list contains banking
5461
+ * recipients. Requires an administrative role on the source wallet.
5462
+ *
5463
+ */
5464
+ post: {
5465
+ parameters: {
5466
+ query?: never;
5467
+ header?: never;
5468
+ path: {
5469
+ /** @description Source wallet the batches belong to */
5470
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
5471
+ };
5472
+ cookie?: never;
5473
+ };
5474
+ requestBody: {
5475
+ content: {
5476
+ "application/json": {
5477
+ /** Format: uuid */
5478
+ currency_id: string;
5479
+ /** Format: uuid */
5480
+ virtual_account_id?: string;
5481
+ name: string;
5482
+ items: components["schemas"]["MassPayoutItemInput"][];
5483
+ };
5484
+ };
5485
+ };
5486
+ responses: {
5487
+ /** @description Draft created */
5488
+ 200: {
5489
+ headers: {
5490
+ [name: string]: unknown;
5491
+ };
5492
+ content: {
5493
+ "application/json": {
5494
+ /** @example true */
5495
+ success?: boolean;
5496
+ data?: components["schemas"]["MassPayout"];
5497
+ };
5498
+ };
5499
+ };
5500
+ /** @description Validation error (including the batch-size limit) */
5501
+ 400: {
5502
+ headers: {
5503
+ [name: string]: unknown;
5504
+ };
5505
+ content: {
5506
+ "application/json": components["schemas"]["ErrorResponse"];
5507
+ };
5508
+ };
5509
+ /** @description Caller lacks permission on the source wallet */
5510
+ 403: {
5511
+ headers: {
5512
+ [name: string]: unknown;
5513
+ };
5514
+ content: {
5515
+ "application/json": components["schemas"]["ErrorResponse"];
5516
+ };
5517
+ };
5518
+ /** @description Rate limit exceeded */
5519
+ 429: {
5520
+ headers: {
5521
+ [name: string]: unknown;
5522
+ };
5523
+ content: {
5524
+ "application/json": components["schemas"]["ErrorResponse"];
5525
+ };
5526
+ };
5527
+ };
5528
+ };
5529
+ delete?: never;
5530
+ options?: never;
5531
+ head?: never;
5532
+ patch?: never;
5533
+ trace?: never;
5534
+ };
5535
+ "/frontend/mass-payouts/{wallet_id}/{id}": {
5536
+ parameters: {
5537
+ query?: never;
5538
+ header?: never;
5539
+ path?: never;
5540
+ cookie?: never;
5541
+ };
5542
+ /** Get a mass payout */
5543
+ get: {
5544
+ parameters: {
5545
+ query?: never;
5546
+ header?: never;
5547
+ path: {
5548
+ /** @description Source wallet the batches belong to */
5549
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
5550
+ id: components["parameters"]["MassPayoutId"];
5551
+ };
5552
+ cookie?: never;
5553
+ };
5554
+ requestBody?: never;
5555
+ responses: {
5556
+ /** @description Batch details with progress counters and total amount */
5557
+ 200: {
5558
+ headers: {
5559
+ [name: string]: unknown;
5560
+ };
5561
+ content: {
5562
+ "application/json": {
5563
+ /** @example true */
5564
+ success?: boolean;
5565
+ data?: components["schemas"]["MassPayout"];
5566
+ };
5567
+ };
5568
+ };
5569
+ /** @description Mass payout not found */
5570
+ 404: {
5571
+ headers: {
5572
+ [name: string]: unknown;
5573
+ };
5574
+ content: {
5575
+ "application/json": components["schemas"]["ErrorResponse"];
5576
+ };
5577
+ };
5578
+ };
5579
+ };
5580
+ /**
5581
+ * Edit a mass payout draft
5582
+ * @description Draft-only. `items` fully replaces the recipient list; `virtual_account_id: null` clears the source VA.
5583
+ */
5584
+ put: {
5585
+ parameters: {
5586
+ query?: never;
5587
+ header?: never;
5588
+ path: {
5589
+ /** @description Source wallet the batches belong to */
5590
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
5591
+ id: components["parameters"]["MassPayoutId"];
5592
+ };
5593
+ cookie?: never;
5594
+ };
5595
+ requestBody: {
5596
+ content: {
5597
+ "application/json": {
5598
+ name?: string;
5599
+ /** Format: uuid */
5600
+ virtual_account_id?: string | null;
5601
+ items?: components["schemas"]["MassPayoutItemInput"][];
5602
+ };
5603
+ };
5604
+ };
5605
+ responses: {
5606
+ /** @description Updated draft */
5607
+ 200: {
5608
+ headers: {
5609
+ [name: string]: unknown;
5610
+ };
5611
+ content: {
5612
+ "application/json": {
5613
+ /** @example true */
5614
+ success?: boolean;
5615
+ data?: components["schemas"]["MassPayout"];
5616
+ };
5617
+ };
5618
+ };
5619
+ /** @description Batch is not editable anymore (already submitted) */
5620
+ 409: {
5621
+ headers: {
5622
+ [name: string]: unknown;
5623
+ };
5624
+ content: {
5625
+ "application/json": components["schemas"]["ErrorResponse"];
5626
+ };
5627
+ };
5628
+ };
5629
+ };
5630
+ post?: never;
5631
+ delete?: never;
5632
+ options?: never;
5633
+ head?: never;
5634
+ patch?: never;
5635
+ trace?: never;
5636
+ };
5637
+ "/frontend/mass-payouts/{wallet_id}/{id}/items": {
5638
+ parameters: {
5639
+ query?: never;
5640
+ header?: never;
5641
+ path?: never;
5642
+ cookie?: never;
5643
+ };
5644
+ /**
5645
+ * List items of a mass payout
5646
+ * @description Items in upload order, paginated with limit/offset like the batch list.
5647
+ */
5648
+ get: {
5649
+ parameters: {
5650
+ query?: {
5651
+ limit?: number;
5652
+ offset?: number;
5653
+ };
5654
+ header?: never;
5655
+ path: {
5656
+ /** @description Source wallet the batches belong to */
5657
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
5658
+ id: components["parameters"]["MassPayoutId"];
5659
+ };
5660
+ cookie?: never;
5661
+ };
5662
+ requestBody?: never;
5663
+ responses: {
5664
+ /** @description Page of items */
5665
+ 200: {
5666
+ headers: {
5667
+ [name: string]: unknown;
5668
+ };
5669
+ content: {
5670
+ "application/json": {
5671
+ /** @example true */
5672
+ success?: boolean;
5673
+ data?: {
5674
+ items?: components["schemas"]["MassPayoutItem"][];
5675
+ total?: number;
5676
+ limit?: number;
5677
+ offset?: number;
5678
+ };
5679
+ };
5680
+ };
5681
+ };
5682
+ };
5683
+ };
5684
+ put?: never;
5685
+ post?: never;
5686
+ delete?: never;
5687
+ options?: never;
5688
+ head?: never;
5689
+ patch?: never;
5690
+ trace?: never;
5691
+ };
5692
+ "/frontend/mass-payouts/{wallet_id}/{id}/preview": {
5693
+ parameters: {
5694
+ query?: never;
5695
+ header?: never;
5696
+ path?: never;
5697
+ cookie?: never;
5698
+ };
5699
+ /**
5700
+ * Preview a mass payout
5701
+ * @description Dry-run before submitting: validates every recipient, estimates the fee
5702
+ * per item through the tenant's pricing, sums the total debit and checks
5703
+ * it against the wallet balance. Crypto payouts to on-platform addresses
5704
+ * may execute cheaper than estimated (they settle internally).
5705
+ *
5706
+ */
5707
+ get: {
5708
+ parameters: {
5709
+ query?: never;
5710
+ header?: never;
5711
+ path: {
5712
+ /** @description Source wallet the batches belong to */
5713
+ wallet_id: components["parameters"]["MassPayoutWalletId"];
5714
+ id: components["parameters"]["MassPayoutId"];
5715
+ };
5716
+ cookie?: never;
5717
+ };
5718
+ requestBody?: never;
5719
+ responses: {
5720
+ /** @description Validation report, fee estimates and balance check */
5721
+ 200: {
5722
+ headers: {
5723
+ [name: string]: unknown;
5724
+ };
5725
+ content: {
5726
+ "application/json": {
5727
+ /** @example true */
5728
+ success?: boolean;
5729
+ data?: {
5730
+ /** Format: uuid */
5731
+ id?: string;
5732
+ /** Format: uuid */
5733
+ currency_id?: string;
5734
+ total_items?: number;
5735
+ total_amount?: number;
5736
+ total_fees?: number;
5737
+ total_debit?: number;
5738
+ balance?: {
5739
+ available?: number;
5740
+ sufficient?: boolean;
5741
+ };
5742
+ valid_count?: number;
5743
+ invalid_count?: number;
5744
+ items?: {
5745
+ /** Format: uuid */
5746
+ item_id?: string;
5747
+ position?: number;
5748
+ /** Format: uuid */
5749
+ destination_id?: string;
5750
+ amount?: number;
5751
+ fee?: number;
5752
+ debit_amount?: number;
5753
+ result_amount?: number;
5754
+ }[];
5755
+ problems?: {
5756
+ /** Format: uuid */
5757
+ item_id?: string;
5758
+ position?: number;
5759
+ /** Format: uuid */
5760
+ destination_id?: string;
5761
+ error?: string;
5762
+ }[];
5763
+ };
5764
+ };
5765
+ };
5766
+ };
5767
+ };
5768
+ };
5769
+ put?: never;
5770
+ post?: never;
5771
+ delete?: never;
5772
+ options?: never;
5773
+ head?: never;
5774
+ patch?: never;
5775
+ trace?: never;
5776
+ };
5777
+ "/frontend/mass-payouts/{wallet_id}/{id}/submit": {
4923
5778
  parameters: {
4924
5779
  query?: never;
4925
5780
  header?: never;
4926
5781
  path?: never;
4927
5782
  cookie?: never;
4928
5783
  };
4929
- /** List mass payouts of a wallet */
4930
- get: {
5784
+ get?: never;
5785
+ put?: never;
5786
+ /**
5787
+ * Submit a mass payout for approval
5788
+ * @description DRAFT → PENDING_APPROVAL. Refused while any recipient is invalid — the
5789
+ * problems are returned in the error details so the rows can be fixed.
5790
+ *
5791
+ */
5792
+ post: {
4931
5793
  parameters: {
4932
- query?: {
4933
- status?: "DRAFT" | "PENDING_APPROVAL" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELED";
4934
- limit?: number;
4935
- offset?: number;
4936
- };
5794
+ query?: never;
4937
5795
  header?: never;
4938
5796
  path: {
4939
5797
  /** @description Source wallet the batches belong to */
4940
5798
  wallet_id: components["parameters"]["MassPayoutWalletId"];
5799
+ id: components["parameters"]["MassPayoutId"];
4941
5800
  };
4942
5801
  cookie?: never;
4943
5802
  };
4944
5803
  requestBody?: never;
4945
5804
  responses: {
4946
- /** @description Page of batches, newest first */
5805
+ /** @description Batch is awaiting approval */
4947
5806
  200: {
4948
5807
  headers: {
4949
5808
  [name: string]: unknown;
@@ -4952,26 +5811,53 @@ export interface paths {
4952
5811
  "application/json": {
4953
5812
  /** @example true */
4954
5813
  success?: boolean;
4955
- data?: {
4956
- items?: components["schemas"]["MassPayout"][];
4957
- total?: number;
4958
- limit?: number;
4959
- offset?: number;
4960
- };
5814
+ data?: components["schemas"]["MassPayout"];
4961
5815
  };
4962
5816
  };
4963
5817
  };
5818
+ /** @description Batch has invalid items (details carry the per-item problems) */
5819
+ 400: {
5820
+ headers: {
5821
+ [name: string]: unknown;
5822
+ };
5823
+ content: {
5824
+ "application/json": components["schemas"]["ErrorResponse"];
5825
+ };
5826
+ };
5827
+ /** @description Batch is not in DRAFT */
5828
+ 409: {
5829
+ headers: {
5830
+ [name: string]: unknown;
5831
+ };
5832
+ content: {
5833
+ "application/json": components["schemas"]["ErrorResponse"];
5834
+ };
5835
+ };
4964
5836
  };
4965
5837
  };
5838
+ delete?: never;
5839
+ options?: never;
5840
+ head?: never;
5841
+ patch?: never;
5842
+ trace?: never;
5843
+ };
5844
+ "/frontend/mass-payouts/{wallet_id}/{id}/approve": {
5845
+ parameters: {
5846
+ query?: never;
5847
+ header?: never;
5848
+ path?: never;
5849
+ cookie?: never;
5850
+ };
5851
+ get?: never;
4966
5852
  put?: never;
4967
5853
  /**
4968
- * Create a mass payout draft
4969
- * @description Creates a batch of payouts to existing counterparty destinations: one
4970
- * source wallet, one currency, up to the tenant's batch-size limit of
4971
- * recipients (default 100). The draft can be freely edited and
4972
- * previewed; nothing moves until it is submitted and approved.
4973
- * `virtual_account_id` is required only when the list contains banking
4974
- * recipients. Requires an administrative role on the source wallet.
5854
+ * Approve a mass payout
5855
+ * @description PENDING_APPROVAL → PROCESSING and starts the asynchronous execution:
5856
+ * every item becomes a regular order (created and approved through the
5857
+ * standard order flow, funds are debited per order). Requires an
5858
+ * administrative wallet role and a recent second-factor verification — a stale one is rejected
5859
+ * with `TWO_FACTOR_REVERIFICATION_REQUIRED`. Execution continues past
5860
+ * failed items; progress is visible through the batch counters.
4975
5861
  *
4976
5862
  */
4977
5863
  post: {
@@ -4981,23 +5867,13 @@ export interface paths {
4981
5867
  path: {
4982
5868
  /** @description Source wallet the batches belong to */
4983
5869
  wallet_id: components["parameters"]["MassPayoutWalletId"];
5870
+ id: components["parameters"]["MassPayoutId"];
4984
5871
  };
4985
5872
  cookie?: never;
4986
5873
  };
4987
- requestBody: {
4988
- content: {
4989
- "application/json": {
4990
- /** Format: uuid */
4991
- currency_id: string;
4992
- /** Format: uuid */
4993
- virtual_account_id?: string;
4994
- name: string;
4995
- items: components["schemas"]["MassPayoutItemInput"][];
4996
- };
4997
- };
4998
- };
5874
+ requestBody?: never;
4999
5875
  responses: {
5000
- /** @description Draft created */
5876
+ /** @description Execution started */
5001
5877
  200: {
5002
5878
  headers: {
5003
5879
  [name: string]: unknown;
@@ -5010,16 +5886,7 @@ export interface paths {
5010
5886
  };
5011
5887
  };
5012
5888
  };
5013
- /** @description Validation error (including the batch-size limit) */
5014
- 400: {
5015
- headers: {
5016
- [name: string]: unknown;
5017
- };
5018
- content: {
5019
- "application/json": components["schemas"]["ErrorResponse"];
5020
- };
5021
- };
5022
- /** @description Caller lacks permission on the source wallet */
5889
+ /** @description Second-factor verification is stale or the caller lacks permission */
5023
5890
  403: {
5024
5891
  headers: {
5025
5892
  [name: string]: unknown;
@@ -5028,8 +5895,8 @@ export interface paths {
5028
5895
  "application/json": components["schemas"]["ErrorResponse"];
5029
5896
  };
5030
5897
  };
5031
- /** @description Rate limit exceeded */
5032
- 429: {
5898
+ /** @description Batch is not awaiting approval */
5899
+ 409: {
5033
5900
  headers: {
5034
5901
  [name: string]: unknown;
5035
5902
  };
@@ -5045,15 +5912,20 @@ export interface paths {
5045
5912
  patch?: never;
5046
5913
  trace?: never;
5047
5914
  };
5048
- "/frontend/mass-payouts/{wallet_id}/{id}": {
5915
+ "/frontend/mass-payouts/{wallet_id}/{id}/cancel": {
5049
5916
  parameters: {
5050
5917
  query?: never;
5051
5918
  header?: never;
5052
5919
  path?: never;
5053
5920
  cookie?: never;
5054
5921
  };
5055
- /** Get a mass payout */
5056
- get: {
5922
+ get?: never;
5923
+ put?: never;
5924
+ /**
5925
+ * Cancel a mass payout
5926
+ * @description Allowed from DRAFT and PENDING_APPROVAL. A PROCESSING batch cannot be canceled — payouts are already executing.
5927
+ */
5928
+ post: {
5057
5929
  parameters: {
5058
5930
  query?: never;
5059
5931
  header?: never;
@@ -5066,7 +5938,7 @@ export interface paths {
5066
5938
  };
5067
5939
  requestBody?: never;
5068
5940
  responses: {
5069
- /** @description Batch details with progress counters and total amount */
5941
+ /** @description Batch canceled */
5070
5942
  200: {
5071
5943
  headers: {
5072
5944
  [name: string]: unknown;
@@ -5079,8 +5951,8 @@ export interface paths {
5079
5951
  };
5080
5952
  };
5081
5953
  };
5082
- /** @description Mass payout not found */
5083
- 404: {
5954
+ /** @description Batch can no longer be canceled */
5955
+ 409: {
5084
5956
  headers: {
5085
5957
  [name: string]: unknown;
5086
5958
  };
@@ -5090,11 +5962,26 @@ export interface paths {
5090
5962
  };
5091
5963
  };
5092
5964
  };
5965
+ delete?: never;
5966
+ options?: never;
5967
+ head?: never;
5968
+ patch?: never;
5969
+ trace?: never;
5970
+ };
5971
+ "/frontend/mass-payouts/{wallet_id}/{id}/report.csv": {
5972
+ parameters: {
5973
+ query?: never;
5974
+ header?: never;
5975
+ path?: never;
5976
+ cookie?: never;
5977
+ };
5093
5978
  /**
5094
- * Edit a mass payout draft
5095
- * @description Draft-only. `items` fully replaces the recipient list; `virtual_account_id: null` clears the source VA.
5979
+ * Download the mass payout report (CSV)
5980
+ * @description Streaming CSV: recipient, amount, item status, the linked order and its
5981
+ * current status, and the failure reason for every unsuccessful payout.
5982
+ *
5096
5983
  */
5097
- put: {
5984
+ get: {
5098
5985
  parameters: {
5099
5986
  query?: never;
5100
5987
  header?: never;
@@ -5105,32 +5992,19 @@ export interface paths {
5105
5992
  };
5106
5993
  cookie?: never;
5107
5994
  };
5108
- requestBody: {
5109
- content: {
5110
- "application/json": {
5111
- name?: string;
5112
- /** Format: uuid */
5113
- virtual_account_id?: string | null;
5114
- items?: components["schemas"]["MassPayoutItemInput"][];
5115
- };
5116
- };
5117
- };
5995
+ requestBody?: never;
5118
5996
  responses: {
5119
- /** @description Updated draft */
5997
+ /** @description CSV file */
5120
5998
  200: {
5121
5999
  headers: {
5122
6000
  [name: string]: unknown;
5123
6001
  };
5124
6002
  content: {
5125
- "application/json": {
5126
- /** @example true */
5127
- success?: boolean;
5128
- data?: components["schemas"]["MassPayout"];
5129
- };
6003
+ "text/csv": string;
5130
6004
  };
5131
6005
  };
5132
- /** @description Batch is not editable anymore (already submitted) */
5133
- 409: {
6006
+ /** @description Mass payout not found */
6007
+ 404: {
5134
6008
  headers: {
5135
6009
  [name: string]: unknown;
5136
6010
  };
@@ -5140,6 +6014,7 @@ export interface paths {
5140
6014
  };
5141
6015
  };
5142
6016
  };
6017
+ put?: never;
5143
6018
  post?: never;
5144
6019
  delete?: never;
5145
6020
  options?: never;
@@ -5147,7 +6022,7 @@ export interface paths {
5147
6022
  patch?: never;
5148
6023
  trace?: never;
5149
6024
  };
5150
- "/frontend/mass-payouts/{wallet_id}/{id}/items": {
6025
+ "/frontend/notification-preferences": {
5151
6026
  parameters: {
5152
6027
  query?: never;
5153
6028
  header?: never;
@@ -5155,26 +6030,19 @@ export interface paths {
5155
6030
  cookie?: never;
5156
6031
  };
5157
6032
  /**
5158
- * List items of a mass payout
5159
- * @description Items in upload order, paginated with limit/offset like the batch list.
6033
+ * Effective delivery-channel preferences
6034
+ * @description Full channel list with defaults applied. `IN_APP` is always enabled (cannot be disabled).
5160
6035
  */
5161
6036
  get: {
5162
6037
  parameters: {
5163
- query?: {
5164
- limit?: number;
5165
- offset?: number;
5166
- };
6038
+ query?: never;
5167
6039
  header?: never;
5168
- path: {
5169
- /** @description Source wallet the batches belong to */
5170
- wallet_id: components["parameters"]["MassPayoutWalletId"];
5171
- id: components["parameters"]["MassPayoutId"];
5172
- };
6040
+ path?: never;
5173
6041
  cookie?: never;
5174
6042
  };
5175
6043
  requestBody?: never;
5176
6044
  responses: {
5177
- /** @description Page of items */
6045
+ /** @description Effective preference per channel. */
5178
6046
  200: {
5179
6047
  headers: {
5180
6048
  [name: string]: unknown;
@@ -5184,17 +6052,58 @@ export interface paths {
5184
6052
  /** @example true */
5185
6053
  success?: boolean;
5186
6054
  data?: {
5187
- items?: components["schemas"]["MassPayoutItem"][];
5188
- total?: number;
5189
- limit?: number;
5190
- offset?: number;
6055
+ preferences?: components["schemas"]["NotificationPreference"][];
5191
6056
  };
5192
6057
  };
5193
6058
  };
5194
6059
  };
6060
+ 401: components["responses"]["UnauthorizedError"];
6061
+ };
6062
+ };
6063
+ /**
6064
+ * Update delivery-channel preferences
6065
+ * @description Bulk upsert. Disabling `IN_APP` is rejected with 400 (`INBOX_CHANNEL_LOCKED`). Changes apply from the next delivery.
6066
+ */
6067
+ put: {
6068
+ parameters: {
6069
+ query?: never;
6070
+ header?: never;
6071
+ path?: never;
6072
+ cookie?: never;
6073
+ };
6074
+ requestBody: {
6075
+ content: {
6076
+ "application/json": {
6077
+ preferences: components["schemas"]["NotificationPreference"][];
6078
+ };
6079
+ };
6080
+ };
6081
+ responses: {
6082
+ /** @description Effective preference list after the update. */
6083
+ 200: {
6084
+ headers: {
6085
+ [name: string]: unknown;
6086
+ };
6087
+ content: {
6088
+ "application/json": {
6089
+ /** @example true */
6090
+ success?: boolean;
6091
+ data?: {
6092
+ preferences?: components["schemas"]["NotificationPreference"][];
6093
+ };
6094
+ };
6095
+ };
6096
+ };
6097
+ /** @description Invalid body (`VALIDATION_ERROR`) or an attempt to disable `IN_APP` (`INBOX_CHANNEL_LOCKED`). */
6098
+ 400: {
6099
+ headers: {
6100
+ [name: string]: unknown;
6101
+ };
6102
+ content?: never;
6103
+ };
6104
+ 401: components["responses"]["UnauthorizedError"];
5195
6105
  };
5196
6106
  };
5197
- put?: never;
5198
6107
  post?: never;
5199
6108
  delete?: never;
5200
6109
  options?: never;
@@ -5202,35 +6111,30 @@ export interface paths {
5202
6111
  patch?: never;
5203
6112
  trace?: never;
5204
6113
  };
5205
- "/frontend/mass-payouts/{wallet_id}/{id}/preview": {
6114
+ "/frontend/notifications": {
5206
6115
  parameters: {
5207
6116
  query?: never;
5208
6117
  header?: never;
5209
6118
  path?: never;
5210
6119
  cookie?: never;
5211
6120
  };
5212
- /**
5213
- * Preview a mass payout
5214
- * @description Dry-run before submitting: validates every recipient, estimates the fee
5215
- * per item through the tenant's pricing, sums the total debit and checks
5216
- * it against the wallet balance. Crypto payouts to on-platform addresses
5217
- * may execute cheaper than estimated (they settle internally).
5218
- *
5219
- */
6121
+ /** List the notification inbox (newest first, cursor pagination) */
5220
6122
  get: {
5221
6123
  parameters: {
5222
- query?: never;
5223
- header?: never;
5224
- path: {
5225
- /** @description Source wallet the batches belong to */
5226
- wallet_id: components["parameters"]["MassPayoutWalletId"];
5227
- id: components["parameters"]["MassPayoutId"];
6124
+ query?: {
6125
+ /** @description Opaque cursor from a previous page (`next_cursor`). Omit for the first page. */
6126
+ cursor?: string;
6127
+ limit?: number;
6128
+ unread_only?: "true" | "false";
6129
+ wallet_id?: string;
5228
6130
  };
6131
+ header?: never;
6132
+ path?: never;
5229
6133
  cookie?: never;
5230
6134
  };
5231
6135
  requestBody?: never;
5232
6136
  responses: {
5233
- /** @description Validation report, fee estimates and balance check */
6137
+ /** @description Page of notifications; `next_cursor` is null on the final page. */
5234
6138
  200: {
5235
6139
  headers: {
5236
6140
  [name: string]: unknown;
@@ -5240,43 +6144,20 @@ export interface paths {
5240
6144
  /** @example true */
5241
6145
  success?: boolean;
5242
6146
  data?: {
5243
- /** Format: uuid */
5244
- id?: string;
5245
- /** Format: uuid */
5246
- currency_id?: string;
5247
- total_items?: number;
5248
- total_amount?: number;
5249
- total_fees?: number;
5250
- total_debit?: number;
5251
- balance?: {
5252
- available?: number;
5253
- sufficient?: boolean;
5254
- };
5255
- valid_count?: number;
5256
- invalid_count?: number;
5257
- items?: {
5258
- /** Format: uuid */
5259
- item_id?: string;
5260
- position?: number;
5261
- /** Format: uuid */
5262
- destination_id?: string;
5263
- amount?: number;
5264
- fee?: number;
5265
- debit_amount?: number;
5266
- result_amount?: number;
5267
- }[];
5268
- problems?: {
5269
- /** Format: uuid */
5270
- item_id?: string;
5271
- position?: number;
5272
- /** Format: uuid */
5273
- destination_id?: string;
5274
- error?: string;
5275
- }[];
6147
+ items?: components["schemas"]["NotificationView"][];
6148
+ next_cursor?: string | null;
5276
6149
  };
5277
6150
  };
5278
6151
  };
5279
6152
  };
6153
+ /** @description Invalid query (`VALIDATION_ERROR`) or a broken cursor (`NOTIFICATION_CURSOR_INVALID`). */
6154
+ 400: {
6155
+ headers: {
6156
+ [name: string]: unknown;
6157
+ };
6158
+ content?: never;
6159
+ };
6160
+ 401: components["responses"]["UnauthorizedError"];
5280
6161
  };
5281
6162
  };
5282
6163
  put?: never;
@@ -5287,35 +6168,24 @@ export interface paths {
5287
6168
  patch?: never;
5288
6169
  trace?: never;
5289
6170
  };
5290
- "/frontend/mass-payouts/{wallet_id}/{id}/submit": {
6171
+ "/frontend/notifications/unread-count": {
5291
6172
  parameters: {
5292
6173
  query?: never;
5293
6174
  header?: never;
5294
6175
  path?: never;
5295
6176
  cookie?: never;
5296
6177
  };
5297
- get?: never;
5298
- put?: never;
5299
- /**
5300
- * Submit a mass payout for approval
5301
- * @description DRAFT → PENDING_APPROVAL. Refused while any recipient is invalid — the
5302
- * problems are returned in the error details so the rows can be fixed.
5303
- *
5304
- */
5305
- post: {
6178
+ /** Unread notifications count (badge) */
6179
+ get: {
5306
6180
  parameters: {
5307
6181
  query?: never;
5308
6182
  header?: never;
5309
- path: {
5310
- /** @description Source wallet the batches belong to */
5311
- wallet_id: components["parameters"]["MassPayoutWalletId"];
5312
- id: components["parameters"]["MassPayoutId"];
5313
- };
6183
+ path?: never;
5314
6184
  cookie?: never;
5315
6185
  };
5316
6186
  requestBody?: never;
5317
6187
  responses: {
5318
- /** @description Batch is awaiting approval */
6188
+ /** @description Current unread count. */
5319
6189
  200: {
5320
6190
  headers: {
5321
6191
  [name: string]: unknown;
@@ -5324,37 +6194,25 @@ export interface paths {
5324
6194
  "application/json": {
5325
6195
  /** @example true */
5326
6196
  success?: boolean;
5327
- data?: components["schemas"]["MassPayout"];
6197
+ data?: {
6198
+ /** @example 3 */
6199
+ count?: number;
6200
+ };
5328
6201
  };
5329
6202
  };
5330
6203
  };
5331
- /** @description Batch has invalid items (details carry the per-item problems) */
5332
- 400: {
5333
- headers: {
5334
- [name: string]: unknown;
5335
- };
5336
- content: {
5337
- "application/json": components["schemas"]["ErrorResponse"];
5338
- };
5339
- };
5340
- /** @description Batch is not in DRAFT */
5341
- 409: {
5342
- headers: {
5343
- [name: string]: unknown;
5344
- };
5345
- content: {
5346
- "application/json": components["schemas"]["ErrorResponse"];
5347
- };
5348
- };
6204
+ 401: components["responses"]["UnauthorizedError"];
5349
6205
  };
5350
6206
  };
6207
+ put?: never;
6208
+ post?: never;
5351
6209
  delete?: never;
5352
6210
  options?: never;
5353
6211
  head?: never;
5354
6212
  patch?: never;
5355
6213
  trace?: never;
5356
6214
  };
5357
- "/frontend/mass-payouts/{wallet_id}/{id}/approve": {
6215
+ "/frontend/notifications/mark-read": {
5358
6216
  parameters: {
5359
6217
  query?: never;
5360
6218
  header?: never;
@@ -5364,29 +6222,25 @@ export interface paths {
5364
6222
  get?: never;
5365
6223
  put?: never;
5366
6224
  /**
5367
- * Approve a mass payout
5368
- * @description PENDING_APPROVAL → PROCESSING and starts the asynchronous execution:
5369
- * every item becomes a regular order (created and approved through the
5370
- * standard order flow, funds are debited per order). Requires an
5371
- * administrative wallet role and a recent second-factor verification — a stale one is rejected
5372
- * with `TWO_FACTOR_REVERIFICATION_REQUIRED`. Execution continues past
5373
- * failed items; progress is visible through the batch counters.
5374
- *
6225
+ * Mark specific notifications as read
6226
+ * @description Idempotent — already-read ids are not counted. Other tabs/devices sync via the realtime `notifications.read` event.
5375
6227
  */
5376
6228
  post: {
5377
6229
  parameters: {
5378
6230
  query?: never;
5379
6231
  header?: never;
5380
- path: {
5381
- /** @description Source wallet the batches belong to */
5382
- wallet_id: components["parameters"]["MassPayoutWalletId"];
5383
- id: components["parameters"]["MassPayoutId"];
5384
- };
6232
+ path?: never;
5385
6233
  cookie?: never;
5386
6234
  };
5387
- requestBody?: never;
6235
+ requestBody: {
6236
+ content: {
6237
+ "application/json": {
6238
+ notification_ids: string[];
6239
+ };
6240
+ };
6241
+ };
5388
6242
  responses: {
5389
- /** @description Execution started */
6243
+ /** @description Number of notifications actually transitioned to read. */
5390
6244
  200: {
5391
6245
  headers: {
5392
6246
  [name: string]: unknown;
@@ -5395,28 +6249,21 @@ export interface paths {
5395
6249
  "application/json": {
5396
6250
  /** @example true */
5397
6251
  success?: boolean;
5398
- data?: components["schemas"]["MassPayout"];
6252
+ data?: {
6253
+ /** @example 2 */
6254
+ updated?: number;
6255
+ };
5399
6256
  };
5400
6257
  };
5401
6258
  };
5402
- /** @description Second-factor verification is stale or the caller lacks permission */
5403
- 403: {
5404
- headers: {
5405
- [name: string]: unknown;
5406
- };
5407
- content: {
5408
- "application/json": components["schemas"]["ErrorResponse"];
5409
- };
5410
- };
5411
- /** @description Batch is not awaiting approval */
5412
- 409: {
6259
+ /** @description Invalid body (`VALIDATION_ERROR`). */
6260
+ 400: {
5413
6261
  headers: {
5414
6262
  [name: string]: unknown;
5415
6263
  };
5416
- content: {
5417
- "application/json": components["schemas"]["ErrorResponse"];
5418
- };
6264
+ content?: never;
5419
6265
  };
6266
+ 401: components["responses"]["UnauthorizedError"];
5420
6267
  };
5421
6268
  };
5422
6269
  delete?: never;
@@ -5425,7 +6272,7 @@ export interface paths {
5425
6272
  patch?: never;
5426
6273
  trace?: never;
5427
6274
  };
5428
- "/frontend/mass-payouts/{wallet_id}/{id}/cancel": {
6275
+ "/frontend/notifications/mark-all-read": {
5429
6276
  parameters: {
5430
6277
  query?: never;
5431
6278
  header?: never;
@@ -5434,24 +6281,17 @@ export interface paths {
5434
6281
  };
5435
6282
  get?: never;
5436
6283
  put?: never;
5437
- /**
5438
- * Cancel a mass payout
5439
- * @description Allowed from DRAFT and PENDING_APPROVAL. A PROCESSING batch cannot be canceled — payouts are already executing.
5440
- */
6284
+ /** Mark every unread notification as read */
5441
6285
  post: {
5442
6286
  parameters: {
5443
6287
  query?: never;
5444
6288
  header?: never;
5445
- path: {
5446
- /** @description Source wallet the batches belong to */
5447
- wallet_id: components["parameters"]["MassPayoutWalletId"];
5448
- id: components["parameters"]["MassPayoutId"];
5449
- };
6289
+ path?: never;
5450
6290
  cookie?: never;
5451
6291
  };
5452
6292
  requestBody?: never;
5453
6293
  responses: {
5454
- /** @description Batch canceled */
6294
+ /** @description Number of notifications actually transitioned to read. */
5455
6295
  200: {
5456
6296
  headers: {
5457
6297
  [name: string]: unknown;
@@ -5460,19 +6300,14 @@ export interface paths {
5460
6300
  "application/json": {
5461
6301
  /** @example true */
5462
6302
  success?: boolean;
5463
- data?: components["schemas"]["MassPayout"];
6303
+ data?: {
6304
+ /** @example 5 */
6305
+ updated?: number;
6306
+ };
5464
6307
  };
5465
6308
  };
5466
6309
  };
5467
- /** @description Batch can no longer be canceled */
5468
- 409: {
5469
- headers: {
5470
- [name: string]: unknown;
5471
- };
5472
- content: {
5473
- "application/json": components["schemas"]["ErrorResponse"];
5474
- };
5475
- };
6310
+ 401: components["responses"]["UnauthorizedError"];
5476
6311
  };
5477
6312
  };
5478
6313
  delete?: never;
@@ -5481,54 +6316,60 @@ export interface paths {
5481
6316
  patch?: never;
5482
6317
  trace?: never;
5483
6318
  };
5484
- "/frontend/mass-payouts/{wallet_id}/{id}/report.csv": {
6319
+ "/frontend/notifications/realtime-token": {
5485
6320
  parameters: {
5486
6321
  query?: never;
5487
6322
  header?: never;
5488
6323
  path?: never;
5489
6324
  cookie?: never;
5490
6325
  };
6326
+ get?: never;
6327
+ put?: never;
5491
6328
  /**
5492
- * Download the mass payout report (CSV)
5493
- * @description Streaming CSV: recipient, amount, item status, the linked order and its
5494
- * current status, and the failure reason for every unsuccessful payout.
6329
+ * Issue a realtime subscription token
6330
+ * @description Subscribe-only token for the realtime SDK (`authCallback`). `channels`
6331
+ * lists the exact channel names the token grants — the personal channel
6332
+ * plus one per accessible wallet. Tokens expire after ~1 hour; the SDK
6333
+ * re-requests through the same endpoint.
5495
6334
  *
5496
6335
  */
5497
- get: {
6336
+ post: {
5498
6337
  parameters: {
5499
6338
  query?: never;
5500
6339
  header?: never;
5501
- path: {
5502
- /** @description Source wallet the batches belong to */
5503
- wallet_id: components["parameters"]["MassPayoutWalletId"];
5504
- id: components["parameters"]["MassPayoutId"];
5505
- };
6340
+ path?: never;
5506
6341
  cookie?: never;
5507
6342
  };
5508
6343
  requestBody?: never;
5509
6344
  responses: {
5510
- /** @description CSV file */
6345
+ /** @description Token, expiry and the granted channel names. */
5511
6346
  200: {
5512
6347
  headers: {
5513
6348
  [name: string]: unknown;
5514
6349
  };
5515
6350
  content: {
5516
- "text/csv": string;
6351
+ "application/json": {
6352
+ /** @example true */
6353
+ success?: boolean;
6354
+ data?: {
6355
+ token?: string;
6356
+ /** Format: date-time */
6357
+ expires_at?: string;
6358
+ channels?: string[];
6359
+ };
6360
+ };
5517
6361
  };
5518
6362
  };
5519
- /** @description Mass payout not found */
5520
- 404: {
6363
+ 401: components["responses"]["UnauthorizedError"];
6364
+ /** @description Realtime delivery is disabled for this deployment (`REALTIME_DISABLED`). */
6365
+ 503: {
5521
6366
  headers: {
5522
6367
  [name: string]: unknown;
5523
6368
  };
5524
- content: {
5525
- "application/json": components["schemas"]["ErrorResponse"];
5526
- };
6369
+ content?: never;
5527
6370
  };
5528
6371
  };
5529
6372
  };
5530
- put?: never;
5531
- post?: never;
5532
6373
  delete?: never;
5533
6374
  options?: never;
5534
6375
  head?: never;
@@ -10843,6 +11684,65 @@ export interface paths {
10843
11684
  patch?: never;
10844
11685
  trace?: never;
10845
11686
  };
11687
+ "/frontend/notifications/test": {
11688
+ parameters: {
11689
+ query?: never;
11690
+ header?: never;
11691
+ path?: never;
11692
+ cookie?: never;
11693
+ };
11694
+ get?: never;
11695
+ put?: never;
11696
+ /**
11697
+ * Send mock notification events (development only)
11698
+ * @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. Nothing is stored — the mock does not appear in the inbox. Available only on development deployments.
11699
+ */
11700
+ post: {
11701
+ parameters: {
11702
+ query?: {
11703
+ /** @description Accessible wallet whose channel receives the mock `data.changed` signal */
11704
+ wallet_id?: string;
11705
+ };
11706
+ header?: never;
11707
+ path?: never;
11708
+ cookie?: never;
11709
+ };
11710
+ requestBody?: {
11711
+ content: {
11712
+ "application/json": {
11713
+ /** @description Push notification text */
11714
+ message?: string;
11715
+ };
11716
+ };
11717
+ };
11718
+ responses: {
11719
+ /** @description Mock events published */
11720
+ 200: {
11721
+ headers: {
11722
+ [name: string]: unknown;
11723
+ };
11724
+ content: {
11725
+ "application/json": {
11726
+ /** @example true */
11727
+ success?: boolean;
11728
+ data?: {
11729
+ /** Format: uuid */
11730
+ notification_id?: string;
11731
+ /** Format: uuid */
11732
+ signaled_wallet_id?: string | null;
11733
+ };
11734
+ };
11735
+ };
11736
+ };
11737
+ 401: components["responses"]["UnauthorizedError"];
11738
+ };
11739
+ };
11740
+ delete?: never;
11741
+ options?: never;
11742
+ head?: never;
11743
+ patch?: never;
11744
+ trace?: never;
11745
+ };
10846
11746
  }
10847
11747
  export type webhooks = Record<string, never>;
10848
11748
  export interface components {
@@ -11146,6 +12046,14 @@ export interface components {
11146
12046
  /** @enum {string|null} */
11147
12047
  form_factor?: "PHYSICAL" | "VIRTUAL" | null;
11148
12048
  tokenizable: boolean;
12049
+ /** @description What a cardholder on this program must carry. Set per program in the vendor config, so it can change without a release — read it instead of hardcoding the form. */
12050
+ cardholder_requirements?: {
12051
+ /** @enum {string} */
12052
+ level?: "minimal" | "basic" | "full";
12053
+ /** @description Required field names; address fields are dotted (address.line1) */
12054
+ required?: string[];
12055
+ required_documents?: ("gov_id_front" | "gov_id_back" | "selfie")[];
12056
+ };
11149
12057
  /** Format: uuid */
11150
12058
  account_currency: string;
11151
12059
  card_limit: number;
@@ -11297,8 +12205,6 @@ export interface components {
11297
12205
  currency: components["schemas"]["CurrencyRef"];
11298
12206
  /** @description Program embed; null when program_id is null */
11299
12207
  issuing_program?: components["schemas"]["IssuingProgram"] | null;
11300
- /** @description Bank details persisted on fiat_accounts; null when absent */
11301
- bank_account_details?: components["schemas"]["BankAccountDetails"] | null;
11302
12208
  /** @description Bank details from the external API meta; empty string `""` when none are available. */
11303
12209
  account_details: components["schemas"]["BankAccountDetails"] | "";
11304
12210
  /** Format: date-time */
@@ -11345,7 +12251,7 @@ export interface components {
11345
12251
  /** Format: date-time */
11346
12252
  updated_at?: string;
11347
12253
  };
11348
- /** @description Card / sub-account transaction (GET /cards/{card_id}/transactions and GET /sub-accounts/{sub_account_id}/transactions). Fields pass through from the issuing vendor. */
12254
+ /** @description Card / sub-account transaction (GET /cards/{card_id}/transactions and GET /sub-accounts/{sub_account_id}/transactions). */
11349
12255
  IssuingTransaction: {
11350
12256
  /** @description Transaction id in the issuing vendor */
11351
12257
  vendor_transaction_id?: string;
@@ -11353,7 +12259,7 @@ export interface components {
11353
12259
  last4?: string;
11354
12260
  /** @example APPROVED */
11355
12261
  status?: string;
11356
- /** @example PURCHASE */
12262
+ /** @example CLEARING */
11357
12263
  transaction_type?: string;
11358
12264
  /** @example Purchase */
11359
12265
  group?: string;
@@ -11625,7 +12531,13 @@ export interface components {
11625
12531
  * @description Source wallet UUID
11626
12532
  */
11627
12533
  wallet_id: string;
12534
+ /** @description Amount to send, in `from_currency_id` units. With `is_reverse: true` — the amount the recipient must receive, in destination-currency units. */
11628
12535
  amount: number;
12536
+ /**
12537
+ * @description When true, `amount` is the receive-amount and the debited amount is grossed up with fees.
12538
+ * @default false
12539
+ */
12540
+ is_reverse: boolean;
11629
12541
  /** Format: uuid */
11630
12542
  from_currency_id: string;
11631
12543
  /** Format: uuid */
@@ -11650,7 +12562,13 @@ export interface components {
11650
12562
  * @description Source wallet UUID
11651
12563
  */
11652
12564
  wallet_id: string;
12565
+ /** @description Amount to send, in `from_currency_id` units. With `is_reverse: true` — the amount the recipient must receive, in destination-currency units. */
11653
12566
  amount: number;
12567
+ /**
12568
+ * @description When true, `amount` is the receive-amount and the debited amount is grossed up with fees.
12569
+ * @default false
12570
+ */
12571
+ is_reverse: boolean;
11654
12572
  /** Format: uuid */
11655
12573
  from_currency_id: string;
11656
12574
  /** Format: uuid */
@@ -11672,8 +12590,13 @@ export interface components {
11672
12590
  FrontendExchangeOrderRequest: {
11673
12591
  /** Format: uuid */
11674
12592
  wallet_id: string;
11675
- /** @description Amount to exchange (in source currency) */
12593
+ /** @description Amount to exchange, in `from_currency_id` units. With `is_reverse: true` — the amount to receive, in `to_currency_id` units. */
11676
12594
  amount: number;
12595
+ /**
12596
+ * @description When true, `amount` is the receive-amount and the debited amount is grossed up with fees.
12597
+ * @default false
12598
+ */
12599
+ is_reverse: boolean;
11677
12600
  /**
11678
12601
  * Format: uuid
11679
12602
  * @description Source currency UUID
@@ -11856,6 +12779,25 @@ export interface components {
11856
12779
  destination_id: string;
11857
12780
  amount: number;
11858
12781
  };
12782
+ NotificationView: {
12783
+ /** Format: uuid */
12784
+ id: string;
12785
+ /** @enum {string} */
12786
+ type: "DEPOSIT_RECEIVED" | "TRANSFER_RECEIVED" | "ORDER_STATUS_CHANGED" | "KYC_STATUS_CHANGED";
12787
+ /** @description Structured fact snapshot; the client renders the presentation. Shape depends on `type`; evolution is additive-only. */
12788
+ payload: Record<string, never>;
12789
+ /** Format: uuid */
12790
+ wallet_id: string | null;
12791
+ /** Format: date-time */
12792
+ read_at: string | null;
12793
+ /** Format: date-time */
12794
+ created_at: string;
12795
+ };
12796
+ NotificationPreference: {
12797
+ /** @enum {string} */
12798
+ channel: "IN_APP" | "PUSH";
12799
+ enabled: boolean;
12800
+ };
11859
12801
  };
11860
12802
  responses: {
11861
12803
  /** @description Authentication credentials are missing or invalid */