squarefi-bff-api-module 1.36.46 → 1.36.48

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.
@@ -13,6 +13,29 @@ export declare const frontend: {
13
13
  list: ({ status, ...params }?: API.Frontend.Issuing.Cards.List.Request) => Promise<API.Frontend.Issuing.Cards.List.Response>;
14
14
  deposit: ({ card_id, ...data }: API.Frontend.Issuing.Cards.Deposit.Request) => Promise<API.Frontend.Issuing.Cards.Deposit.Response>;
15
15
  withdraw: ({ card_id, ...data }: API.Frontend.Issuing.Cards.Withdraw.Request) => Promise<API.Frontend.Issuing.Cards.Withdraw.Response>;
16
+ getById: ({ card_id, }: API.Frontend.Issuing.Cards.Get.Request) => Promise<API.Frontend.Issuing.Cards.Get.Response>;
17
+ /** Rename (and other editable card fields). */
18
+ update: ({ card_id, ...data }: API.Frontend.Issuing.Cards.Update.Request) => Promise<API.Frontend.Issuing.Cards.Update.Response>;
19
+ /** Terminal, unlike freeze — a closed card cannot be reopened. */
20
+ close: ({ card_id, }: API.Frontend.Issuing.Cards.Close.Request) => Promise<API.Frontend.Issuing.Cards.Close.Response>;
21
+ freeze: ({ card_id, }: API.Frontend.Issuing.Cards.Freeze.Request) => Promise<API.Frontend.Issuing.Cards.Freeze.Response>;
22
+ unfreeze: ({ card_id, }: API.Frontend.Issuing.Cards.Unfreeze.Request) => Promise<API.Frontend.Issuing.Cards.Unfreeze.Response>;
23
+ limits: {
24
+ update: ({ card_id, ...data }: API.Frontend.Issuing.Cards.Limits.Request) => Promise<API.Frontend.Issuing.Cards.Limits.Response>;
25
+ };
26
+ /**
27
+ * PLAINTEXT PAN/CVV — server-to-server only. In a browser or mobile client use
28
+ * `sensitiveEncrypted` instead, so the card number never travels readable.
29
+ */
30
+ sensitive: ({ card_id, }: API.Frontend.Issuing.Cards.Sensitive.Request) => Promise<API.Frontend.Issuing.Cards.Sensitive.Response>;
31
+ /**
32
+ * PAN/CVV over the encrypted channel: generates an AES-256 key, sends it encrypted to
33
+ * the server's RSA public key (`SERVER_PUBLIC_KEY_BASE64`) and decrypts the answer —
34
+ * the same exchange as the legacy `issuing.cards.sensitiveData.encrypted.secretKey`,
35
+ * against the frontend route.
36
+ */
37
+ sensitiveEncrypted: ({ card_id, }: API.Frontend.Issuing.Cards.SensitiveEncrypted.Request) => Promise<API.Frontend.Issuing.Cards.SensitiveEncrypted.Response>;
38
+ transactions: ({ card_id, ...params }: API.Frontend.Issuing.Cards.Transactions.Request) => Promise<API.Frontend.Issuing.Cards.Transactions.Response>;
16
39
  create: (data: API.Frontend.Issuing.Cards.Create.Request) => Promise<API.Frontend.Issuing.Cards.Create.Response>;
17
40
  };
18
41
  cardholders: {
@@ -32,6 +55,8 @@ export declare const frontend: {
32
55
  subAccounts: {
33
56
  getAll: (params?: API.Frontend.Issuing.SubAccounts.List.Request) => Promise<API.Frontend.Issuing.SubAccounts.List.Response>;
34
57
  getById: ({ sub_account_id, }: API.Frontend.Issuing.SubAccounts.Get.Request) => Promise<API.Frontend.Issuing.SubAccounts.Get.Response>;
58
+ create: (data: API.Frontend.Issuing.SubAccounts.Create.Request) => Promise<API.Frontend.Issuing.SubAccounts.Create.Response>;
59
+ transactions: ({ sub_account_id, ...params }: API.Frontend.Issuing.SubAccounts.Transactions.Request) => Promise<API.Frontend.Issuing.SubAccounts.Transactions.Response>;
35
60
  deposit: ({ sub_account_id, ...data }: API.Frontend.Issuing.SubAccounts.Deposit.Request) => Promise<API.Frontend.Issuing.SubAccounts.Deposit.Response>;
36
61
  withdraw: ({ sub_account_id, ...data }: API.Frontend.Issuing.SubAccounts.Withdraw.Request) => Promise<API.Frontend.Issuing.SubAccounts.Withdraw.Response>;
37
62
  };
@@ -1,4 +1,5 @@
1
1
  import { apiClientV1, apiClientV1Frontend } from '../utils/apiClientFactory';
2
+ import { makeSecureRequest } from '../utils/encrypt';
2
3
  export const frontend = {
3
4
  access: {
4
5
  keys: {
@@ -29,6 +30,38 @@ export const frontend = {
29
30
  // first through `cardholders.*` — an unlinked user gets `400 CARDHOLDER_NOT_LINKED`).
30
31
  // Issuing fee / initial top-up follow the group tariff; pass `currency_id` (and optionally
31
32
  // `initial_topup`) whenever the tariff carries money.
33
+ getById: ({ card_id, }) => apiClientV1Frontend.getRequest(`/frontend/issuing/cards/${card_id}`),
34
+ /** Rename (and other editable card fields). */
35
+ update: ({ card_id, ...data }) => apiClientV1Frontend.patchRequest(`/frontend/issuing/cards/${card_id}`, { data }),
36
+ /** Terminal, unlike freeze — a closed card cannot be reopened. */
37
+ close: ({ card_id, }) => apiClientV1Frontend.deleteRequest(`/frontend/issuing/cards/${card_id}`),
38
+ freeze: ({ card_id, }) => apiClientV1Frontend.putRequest(`/frontend/issuing/cards/${card_id}/freeze`),
39
+ unfreeze: ({ card_id, }) => apiClientV1Frontend.putRequest(`/frontend/issuing/cards/${card_id}/unfreeze`),
40
+ limits: {
41
+ update: ({ card_id, ...data }) => apiClientV1Frontend.putRequest(`/frontend/issuing/cards/${card_id}/limits`, { data }),
42
+ },
43
+ /**
44
+ * PLAINTEXT PAN/CVV — server-to-server only. In a browser or mobile client use
45
+ * `sensitiveEncrypted` instead, so the card number never travels readable.
46
+ */
47
+ sensitive: ({ card_id, }) => apiClientV1Frontend.getRequest(`/frontend/issuing/cards/${card_id}/sensitive`),
48
+ /**
49
+ * PAN/CVV over the encrypted channel: generates an AES-256 key, sends it encrypted to
50
+ * the server's RSA public key (`SERVER_PUBLIC_KEY_BASE64`) and decrypts the answer —
51
+ * the same exchange as the legacy `issuing.cards.sensitiveData.encrypted.secretKey`,
52
+ * against the frontend route.
53
+ */
54
+ sensitiveEncrypted: async ({ card_id, }) => {
55
+ const serverPublicKey = process.env.SERVER_PUBLIC_KEY_BASE64;
56
+ if (!serverPublicKey) {
57
+ throw new Error('SERVER_PUBLIC_KEY_BASE64 is not set');
58
+ }
59
+ return makeSecureRequest({
60
+ callback: (props) => apiClientV1Frontend.postRequest(`/frontend/issuing/cards/${card_id}/sensitive/secretkey`, { data: props }),
61
+ publicKey: serverPublicKey,
62
+ });
63
+ },
64
+ transactions: ({ card_id, ...params }) => apiClientV1Frontend.getRequest(`/frontend/issuing/cards/${card_id}/transactions`, { params }),
32
65
  create: (data) => apiClientV1Frontend.postRequest('/frontend/issuing/cards', {
33
66
  data,
34
67
  }),
@@ -85,6 +118,8 @@ export const frontend = {
85
118
  // sub-accounts — prefer that over `getById`, whose shape varies with the vendor.
86
119
  getAll: (params = {}) => apiClientV1Frontend.getRequest('/frontend/issuing/sub-accounts', { params }),
87
120
  getById: ({ sub_account_id, }) => apiClientV1Frontend.getRequest(`/frontend/issuing/sub-accounts/${sub_account_id}`),
121
+ create: (data) => apiClientV1Frontend.postRequest('/frontend/issuing/sub-accounts', { data }),
122
+ transactions: ({ sub_account_id, ...params }) => apiClientV1Frontend.getRequest(`/frontend/issuing/sub-accounts/${sub_account_id}/transactions`, { params }),
88
123
  deposit: ({ sub_account_id, ...data }) => apiClientV1Frontend.postRequest(`/frontend/issuing/sub-accounts/${sub_account_id}/deposit`, { data }),
89
124
  // Concurrent withdrawals on the same sub-account are rejected with `409`. The currency is
90
125
  // taken from the sub-account, so only the amount is needed.
@@ -2058,6 +2058,8 @@ export interface paths {
2058
2058
  wallet_id?: string;
2059
2059
  /** @description Filter cards by program ID */
2060
2060
  program_id?: string;
2061
+ /** @description Only cards drawing from this sub-account. */
2062
+ sub_account_id?: string;
2061
2063
  /** @description Filter cards by program sub-account type (prepaid or balance) */
2062
2064
  sub_account_type?: "prepaid" | "balance";
2063
2065
  /** @description Filter cards by status (matches issuing_cards.card_status).
@@ -2595,6 +2597,89 @@ export interface paths {
2595
2597
  patch?: never;
2596
2598
  trace?: never;
2597
2599
  };
2600
+ "/frontend/issuing/cards/{card_id}/sensitive/secretkey": {
2601
+ parameters: {
2602
+ query?: never;
2603
+ header?: never;
2604
+ path?: never;
2605
+ cookie?: never;
2606
+ };
2607
+ get?: never;
2608
+ put?: never;
2609
+ /**
2610
+ * Get card sensitive data over an encrypted channel
2611
+ * @description PAN / CVV without ever putting them in a readable response body — prefer this
2612
+ * over `GET /sensitive` in any browser or mobile client.
2613
+ *
2614
+ * The client generates a 32-byte AES-256 key, encrypts it to the server's RSA
2615
+ * public key (`RSA-OAEP`; `PKCS1` is accepted for older clients) and sends it
2616
+ * base64-encoded as `encrypted_key`. The response carries the card data
2617
+ * AES-256-CBC encrypted with that same key, plus the `iv` used.
2618
+ *
2619
+ * Decrypting `data` with the key and IV yields
2620
+ * `{ success, data: { card_number, cvv, expiry_month, expiry_year, security_code }, timestamp }`.
2621
+ *
2622
+ * **Access**: ADMIN on the card's wallet, or the scoped `user` role on their OWN card.
2623
+ *
2624
+ */
2625
+ post: {
2626
+ parameters: {
2627
+ query?: never;
2628
+ header?: never;
2629
+ path: {
2630
+ card_id: string;
2631
+ };
2632
+ cookie?: never;
2633
+ };
2634
+ requestBody: {
2635
+ content: {
2636
+ "application/json": {
2637
+ /** @description Base64 of the AES-256 key encrypted to the server's RSA public key. */
2638
+ encrypted_key: string;
2639
+ };
2640
+ };
2641
+ };
2642
+ responses: {
2643
+ /** @description Encrypted sensitive data */
2644
+ 200: {
2645
+ headers: {
2646
+ [name: string]: unknown;
2647
+ };
2648
+ content: {
2649
+ "application/json": {
2650
+ /** @example true */
2651
+ success: boolean;
2652
+ /** @example true */
2653
+ encrypted: boolean;
2654
+ /** @description Base64 AES-256-CBC ciphertext of the sensitive-data envelope. */
2655
+ data: string;
2656
+ /** @description Base64 IV used for the AES encryption. */
2657
+ iv: string;
2658
+ };
2659
+ };
2660
+ };
2661
+ /** @description Missing or undecryptable `encrypted_key`, or a key that is not 32 bytes */
2662
+ 400: {
2663
+ headers: {
2664
+ [name: string]: unknown;
2665
+ };
2666
+ content?: never;
2667
+ };
2668
+ /** @description Server key not configured, or encryption failed */
2669
+ 500: {
2670
+ headers: {
2671
+ [name: string]: unknown;
2672
+ };
2673
+ content?: never;
2674
+ };
2675
+ };
2676
+ };
2677
+ delete?: never;
2678
+ options?: never;
2679
+ head?: never;
2680
+ patch?: never;
2681
+ trace?: never;
2682
+ };
2598
2683
  "/frontend/issuing/cards/{card_id}/freeze": {
2599
2684
  parameters: {
2600
2685
  query?: never;
@@ -12257,11 +12342,12 @@ export interface components {
12257
12342
  [key: string]: unknown;
12258
12343
  } | null;
12259
12344
  };
12260
- /** @description Sub-account funding a card — the subset of `fiat_accounts` columns joined onto each card. */
12345
+ /** @description Sub-account funding a card — the `fiat_accounts` row joined onto each card, with the same `currency` / `issuing_program` / `account_details` enrichment `GET /sub-accounts` applies, so a card page can drive top-up and render balances without a second request. */
12261
12346
  IssuingCardSubAccount: {
12262
12347
  /** Format: uuid */
12263
12348
  id: string;
12264
12349
  nick_name?: string | null;
12350
+ /** @description Live balance from the issuing ledger (falls back to the cached column). */
12265
12351
  balance?: number | null;
12266
12352
  /** @enum {string} */
12267
12353
  type: "balance" | "prepaid";
@@ -12275,6 +12361,11 @@ export interface components {
12275
12361
  * @description crypto.uuid of the account currency
12276
12362
  */
12277
12363
  account_currency: string;
12364
+ currency?: components["schemas"]["CurrencyRef"];
12365
+ /** @description Program embed (carries `order_types`, which the top-up flow reads); null when program_id is null. */
12366
+ issuing_program?: components["schemas"]["IssuingProgram"] | null;
12367
+ /** @description Bank details from the vendor meta; empty string `""` when none are available. */
12368
+ account_details?: components["schemas"]["BankAccountDetails"] | "";
12278
12369
  /** Format: uuid */
12279
12370
  program_id?: string | null;
12280
12371
  /** Format: uuid */
@@ -672,6 +672,13 @@ export declare namespace API {
672
672
  }
673
673
  namespace Issuing {
674
674
  type CardsRoot = pathsV1Frontend['/frontend/issuing/cards'];
675
+ type CardRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}'];
676
+ type CardFreezeRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/freeze'];
677
+ type CardUnfreezeRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/unfreeze'];
678
+ type CardLimitsRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/limits'];
679
+ type CardSensitiveRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/sensitive'];
680
+ type CardTransactionsRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/transactions'];
681
+ type SubAccountTransactionsRoot = pathsV1Frontend['/frontend/issuing/sub-accounts/{sub_account_id}/transactions'];
675
682
  type CardDepositRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/deposit'];
676
683
  type CardWithdrawRoot = pathsV1Frontend['/frontend/issuing/cards/{card_id}/withdraw'];
677
684
  type SubAccountDepositRoot = pathsV1Frontend['/frontend/issuing/sub-accounts/{sub_account_id}/deposit'];
@@ -711,6 +718,17 @@ export declare namespace API {
711
718
  };
712
719
  type Response = SubAccountRoot['get']['responses']['200']['content']['application/json'];
713
720
  }
721
+ export namespace Create {
722
+ type Request = SubAccountsRoot['post']['requestBody']['content']['application/json'];
723
+ type Response = SubAccountsRoot['post']['responses']['201']['content']['application/json'];
724
+ }
725
+ export namespace Transactions {
726
+ type Request = {
727
+ sub_account_id: string;
728
+ } & NonNullable<SubAccountTransactionsRoot['get']['parameters']['query']>;
729
+ type Response = SubAccountTransactionsRoot['get']['responses']['200']['content']['application/json'];
730
+ type Transaction = NonNullable<Response['data']>[number];
731
+ }
714
732
  export namespace Deposit {
715
733
  type Request = {
716
734
  sub_account_id: string;
@@ -731,6 +749,74 @@ export declare namespace API {
731
749
  type Response = CardsRoot['get']['responses']['200']['content']['application/json'];
732
750
  type Card = NonNullable<Response['data']>[number];
733
751
  }
752
+ namespace Get {
753
+ type Request = {
754
+ card_id: string;
755
+ };
756
+ type Response = CardRoot['get']['responses']['200']['content']['application/json'];
757
+ type Card = NonNullable<Response['data']>;
758
+ }
759
+ /** Rename (and other editable card fields). */
760
+ namespace Update {
761
+ type Request = {
762
+ card_id: string;
763
+ } & CardRoot['patch']['requestBody']['content']['application/json'];
764
+ type Response = CardRoot['patch']['responses']['200']['content']['application/json'];
765
+ }
766
+ /** Close the card — terminal, unlike freeze. */
767
+ namespace Close {
768
+ type Request = {
769
+ card_id: string;
770
+ };
771
+ type Response = CardRoot['delete']['responses']['200']['content']['application/json'];
772
+ }
773
+ namespace Freeze {
774
+ type Request = {
775
+ card_id: string;
776
+ };
777
+ type Response = CardFreezeRoot['put']['responses']['200']['content']['application/json'];
778
+ }
779
+ namespace Unfreeze {
780
+ type Request = {
781
+ card_id: string;
782
+ };
783
+ type Response = CardUnfreezeRoot['put']['responses']['200']['content']['application/json'];
784
+ }
785
+ namespace Limits {
786
+ type Request = {
787
+ card_id: string;
788
+ } & CardLimitsRoot['put']['requestBody']['content']['application/json'];
789
+ type Response = CardLimitsRoot['put']['responses']['200']['content']['application/json'];
790
+ }
791
+ /**
792
+ * Card PAN/CVV in PLAINTEXT. Server-to-server only — a browser or mobile client
793
+ * should use `SensitiveEncrypted`, which never puts the PAN in a readable body.
794
+ */
795
+ namespace Sensitive {
796
+ type Request = {
797
+ card_id: string;
798
+ };
799
+ type Response = CardSensitiveRoot['get']['responses']['200']['content']['application/json'];
800
+ }
801
+ /**
802
+ * Card PAN/CVV over an end-to-end encrypted channel: the client's AES-256 key is
803
+ * sent encrypted to the server's RSA public key, and the answer comes back
804
+ * encrypted with that same key. The SDK does the key exchange and the decryption,
805
+ * so the caller just receives the decrypted payload.
806
+ */
807
+ namespace SensitiveEncrypted {
808
+ type Request = {
809
+ card_id: string;
810
+ };
811
+ type Response = API.Cards.SensitiveData;
812
+ }
813
+ namespace Transactions {
814
+ type Request = {
815
+ card_id: string;
816
+ } & NonNullable<CardTransactionsRoot['get']['parameters']['query']>;
817
+ type Response = CardTransactionsRoot['get']['responses']['200']['content']['application/json'];
818
+ type Transaction = NonNullable<Response['data']>[number];
819
+ }
734
820
  namespace Create {
735
821
  type Request = Omit<CardsRoot['post']['requestBody']['content']['application/json'], 'cardholder_id'> & {
736
822
  cardholder_id?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squarefi-bff-api-module",
3
- "version": "1.36.46",
3
+ "version": "1.36.48",
4
4
  "description": "Squarefi BFF API client module",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",