@stable_sea/sdk 0.2.19 → 0.2.21

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.
package/README.md CHANGED
@@ -21,7 +21,7 @@ import { createStableSeaClient } from "@stable_sea/sdk";
21
21
  const client = createStableSeaClient({
22
22
  apiKey: process.env.STABLE_SEA_API_KEY!,
23
23
  baseUrl: process.env.STABLE_SEA_BASE_URL!,
24
- version: "2026-10-15",
24
+ version: "2026-10-16",
25
25
  });
26
26
  ```
27
27
 
@@ -53,6 +53,14 @@ keys and rotations reuse that data.
53
53
  WTGXX supports standard and instant settlement. FLTTX supports standard
54
54
  settlement; instant orders are refused in both production and sandbox.
55
55
 
56
+ Every fund order names the network it settles on, `ethereum` or `stellar`. The
57
+ API never applies a business's default network. A BTC order settles on no network
58
+ and must not name one. The generated `network` type is optional because BTC shares
59
+ the request, so the server enforces both rules: a fund order without a network
60
+ fails with `network_required`, and a BTC order with one fails with
61
+ `network_not_applicable`. Sandbox settles on `ethereum`. Instant settlement is
62
+ available on `ethereum` only.
63
+
56
64
  ## Member administration and personal actions
57
65
 
58
66
  Use `createStableSeaSessionClient` for onboarding, legal documents, your profile
@@ -92,6 +100,14 @@ automatically. See the [member guide](https://docs.stablesea.com/api/#member-ses
92
100
  for sign-in, session lifecycle and attachment retrieval, and the
93
101
  [member reference](https://docs.stablesea.com/api/member-reference/) for fields.
94
102
 
103
+ Read the business's networks at `GET /identity/business/networks`, available to
104
+ any member. Choose them at `POST /identity/business/networks`, which needs the
105
+ Manage Permissions permission and takes the business from the session. Turning a
106
+ network off is refused while the business holds funds or has pending activity
107
+ there, and a network the business is not eligible for cannot be turned on. This
108
+ setting decides which networks the business may use, including for API orders. It
109
+ never supplies the network of an order, which always names its own.
110
+
95
111
  List members at `GET /identity/members` and manage invitations at
96
112
  `/identity/members/invites`. Creation returns invitation details, never the
97
113
  redemption token delivered to the invitee. Invitation acceptance uses the
@@ -126,6 +142,12 @@ Use the member client before issuing an API key. Signup uses the existing
126
142
  business-email/OTP flow. After account and authenticator setup, sign in and select
127
143
  your business using the same session flow as Terminal.
128
144
 
145
+ Where the signup bot challenge is on, `GET /identity/bot_challenge_settings`
146
+ answers `required: true`, and the screener submit and code resend refuse a
147
+ request without a Cloudflare Turnstile `challenge_token` (`bot_challenge_required`,
148
+ `bot_challenge_failed`). Turnstile issues tokens only to its widget on a hostname
149
+ the site key allows.
150
+
129
151
  Read `/onboarding/status` and `/compliance/kyb/fields` to discover the current
130
152
  requirements and saved answers. Review registry proposals before confirming
131
153
  prefilled answers. Draft writes retain their native revision checks: send the
@@ -363,6 +385,15 @@ its first chart refresh. The document's captured financial figures remain readab
363
385
  should accept the new value, and code that keyed a Solana balance by its
364
386
  `unknown` row should expect the `solana` row instead.
365
387
 
388
+ ## October 16 API contract
389
+
390
+ Update to the latest SDK before placing fund orders. `POST /v1/orders` takes a
391
+ `network` for every fund order and refuses it for BTC, and every order read returns
392
+ `network` (`null` for BTC). The HTTP request pin is `2026-10-16`; the retired
393
+ `2026-10-15` pin returns `400 unsupported_api_version`. An order whose network the
394
+ business turned off, or cannot settle on, ends `failed` with `network_not_in_use`
395
+ or `network_not_eligible`.
396
+
366
397
  ## October 11 API contract
367
398
 
368
399
  Update to the latest SDK before using the revised contract. Send bank removal
@@ -370,7 +401,7 @@ with `client.DELETE("/v1/bank_accounts/{id}")`, without a body or idempotency ke
370
401
  Read bank and wallet operation `status` instead of `state`. Retrieve issued
371
402
  statement content with `GET /v1/statements/{id}`; the `/content` route is retired.
372
403
 
373
- The HTTP request pin is `2026-10-15`. The retired pin returns
404
+ The HTTP request pin is `2026-10-16`. The retired pin returns
374
405
  `400 unsupported_api_version`. Existing API keys remain valid; stored key and
375
406
  thin-event/webhook versions are preserved.
376
407
 
@@ -537,7 +537,7 @@ export interface paths {
537
537
  put?: never;
538
538
  /**
539
539
  * Place an order
540
- * @description Creates an order for the authenticated business and returns it as `pending`. BTC orders require both `investments:write` and `investments:btc_write` and use standard settlement. The BTC quote is indicative; execution uses the current native price and fees. Execution is asynchronous and uses the same authorization checks and trading engine as Terminal. Retrieve the order to follow it through `executing` to `filled` or `failed`.
540
+ * @description Creates an order for the authenticated business and returns it as `pending`. A fund order must name the `network` it settles on, `ethereum` or `stellar`; the API never applies a business's default network. A business that has turned that network off, or is not eligible for it, gets a failed order with a `failure_code` naming why. BTC orders require both `investments:write` and `investments:btc_write`, use standard settlement and settle on no network, so they must not name one. The BTC quote is indicative; execution uses the current native price and fees. Execution is asynchronous and uses the same authorization checks and trading engine as Terminal. Retrieve the order to follow it through `executing` to `filled` or `failed`.
541
541
  *
542
542
  * Fund orders check the quoted NAV at execution. Price changes and insufficient express liquidity can cause execution to fail. The failed order includes a reason. While the quote remains valid, an express refusal can be submitted as a new standard order.
543
543
  *
@@ -655,7 +655,9 @@ export interface paths {
655
655
  * Price a trade
656
656
  * @description Returns an indicative price for BTC or a fund. Quotes have no ID and cannot be retrieved later. BTC prices use the latest unexpired native quote; reading one does not extend its expiry. Calculated BTC quote amounts are rounded to at most 18 decimal places. Actual trade amounts are determined at execution. BTC quotes include `platform_fee_usdc`, `fee_bps`, `net_usdc` and the `net_estimated_quantity` after the buy fee. `minimum_amount_usd` states the BTC order minimum. A BTC quote does not guarantee the execution price. Fund orders include the quoted NAV.
657
657
  *
658
- * `express` describes the commission, order limit, estimated quantity and settlement estimate for express settlement. These terms do not guarantee available liquidity. An express order may fail at execution; while the quote remains valid, you can submit a new standard order using the same quoted price. Standard settlement changes the commission and delivered quantity, not the quoted price.
658
+ * `express` describes the commission, order limit, estimated quantity and settlement estimate for express settlement. These terms do not guarantee available liquidity. An express order may fail at execution; while the quote remains valid, you can submit a new standard order using the same quoted price. Standard settlement changes the commission and delivered quantity, not the quoted price. Express terms apply to Ethereum orders.
659
+ *
660
+ * The price does not depend on the network an order settles on, so a quote takes none. The order names it.
659
661
  */
660
662
  get: operations["quotes.quote"];
661
663
  put?: never;
@@ -1489,7 +1491,7 @@ export interface components {
1489
1491
  /** @enum {string} */
1490
1492
  payment_rail: "onchain_ethereum" | "onchain_stellar" | "onchain_solana";
1491
1493
  /** @enum {string} */
1492
- symbol?: "USDC" | "XLM";
1494
+ symbol?: "USDC" | "XLM" | "YLDS";
1493
1495
  };
1494
1496
  ExternalWalletHolding: {
1495
1497
  /** @description The quantity held, in the token's own units. Exact, never rounded, and always above zero. */
@@ -1606,7 +1608,7 @@ export interface components {
1606
1608
  observed_ts: string;
1607
1609
  };
1608
1610
  /** @enum {string} */
1609
- HTTPAPIVersion: "2026-10-15";
1611
+ HTTPAPIVersion: "2026-10-16";
1610
1612
  List: {
1611
1613
  data: components["schemas"]["Resource"][];
1612
1614
  has_more: boolean;
@@ -1672,6 +1674,11 @@ export interface components {
1672
1674
  /** @description The order id. Stable for the life of the order and safe to store. */
1673
1675
  id: string;
1674
1676
  livemode: boolean;
1677
+ /**
1678
+ * @description The network the order settles on, as the request named it. Null for BTC, which settles on no network.
1679
+ * @enum {string|null}
1680
+ */
1681
+ network: "ethereum" | "stellar" | null;
1675
1682
  /** @enum {string} */
1676
1683
  object: "order";
1677
1684
  quoted_price: string;
@@ -1691,10 +1698,15 @@ export interface components {
1691
1698
  * @enum {string}
1692
1699
  */
1693
1700
  direction: "buy" | "sell";
1701
+ /**
1702
+ * @description The network a fund order settles on. Required for a fund order and refused for BTC, which settles on no network. The API never applies a business's default network.
1703
+ * @enum {string}
1704
+ */
1705
+ network?: "ethereum" | "stellar";
1694
1706
  /** @description The price_per_unit from GET /v1/quotes. Fund execution checks the NAV; BTC uses an indicative price and executes at the current native price. */
1695
1707
  quoted_price: string;
1696
1708
  /**
1697
- * @description Settlement mode. Express (instant) carries a commission the standard path does not; see the express terms on GET /v1/quotes. Express draws on a shared reserve, so an express order can be refused at execution and the order reaches a failed state naming why — re-place it as standard against the same unexpired quote.
1709
+ * @description Settlement mode. Express (instant) carries a commission the standard path does not; see the express terms on GET /v1/quotes. Express draws on a shared reserve, so an express order can be refused at execution and the order reaches a failed state naming why — re-place it as standard against the same unexpired quote. Express settles on ethereum only.
1698
1710
  * @enum {string}
1699
1711
  */
1700
1712
  settlement: "standard" | "instant";
@@ -839,6 +839,50 @@ export interface paths {
839
839
  patch?: never;
840
840
  trace?: never;
841
841
  };
842
+ "/identity/bot_challenge_settings": {
843
+ parameters: {
844
+ query?: never;
845
+ header?: never;
846
+ path?: never;
847
+ cookie?: never;
848
+ };
849
+ /**
850
+ * Get bot challenge settings
851
+ * @description Reports whether the signup screener submit and the signup code resend require a bot-challenge token, and the public site key to render the challenge widget with. Public.
852
+ */
853
+ get: operations["identity.bot_challenge_settings.get"];
854
+ put?: never;
855
+ post?: never;
856
+ delete?: never;
857
+ options?: never;
858
+ head?: never;
859
+ patch?: never;
860
+ trace?: never;
861
+ };
862
+ "/identity/business/networks": {
863
+ parameters: {
864
+ query?: never;
865
+ header?: never;
866
+ path?: never;
867
+ cookie?: never;
868
+ };
869
+ /**
870
+ * Get the networks a business uses
871
+ * @description Returns every network with whether the business is eligible for it, whether it is in use, which is the default, what it carries, and what the business holds there. Any member of the business can read it. A network that holds funds or has pending transactions carries turn_off_blocked.
872
+ */
873
+ get: operations["identity.business.networks.get"];
874
+ put?: never;
875
+ /**
876
+ * Set the networks a business uses
877
+ * @description Replaces the networks in use and the default network for every member and API key of the business. Requires Manage Permissions. A change applies immediately, with no two-factor code; turning a network on grants no rail. Turning off a network that holds funds or has pending transactions is refused with network_holds_funds, and with network_holdings_unavailable when what it holds cannot be checked; a network the business is not eligible for with network_not_eligible, and an invalid set with invalid_networks. Saving what is already saved changes nothing and records nothing.
878
+ */
879
+ post: operations["identity.business.networks.set"];
880
+ delete?: never;
881
+ options?: never;
882
+ head?: never;
883
+ patch?: never;
884
+ trace?: never;
885
+ };
842
886
  "/identity/business_invites/{group_id}/step_2": {
843
887
  parameters: {
844
888
  query?: never;
@@ -1684,7 +1728,7 @@ export interface paths {
1684
1728
  put?: never;
1685
1729
  /**
1686
1730
  * Resend signup OTP
1687
- * @description Re-issues the OTP for an in-flight screener session by re-running registration step 1 for the supplied business email, minting a fresh OTP and re-delivering the email. Acknowledges the same way for an address that already has an account, which is then emailed a sign-in prompt rather than a code: this endpoint never reveals whether an address is registered.
1731
+ * @description Re-issues the OTP for an in-flight screener session by re-running registration step 1 for the supplied business email, minting a fresh OTP and re-delivering the email. Acknowledges the same way for an address that already has an account, which is then emailed a sign-in prompt rather than a code: this endpoint never reveals whether an address is registered. While GET /identity/bot_challenge_settings answers required=true, a request without a valid challenge_token is refused (bot_challenge_required / bot_challenge_failed) before any email.
1688
1732
  */
1689
1733
  post: operations["signup.screener.resend_otp"];
1690
1734
  delete?: never;
@@ -1704,7 +1748,7 @@ export interface paths {
1704
1748
  put?: never;
1705
1749
  /**
1706
1750
  * Submit signup screener
1707
- * @description Validates the screener payload (business email + business name) and starts an identity registration session. Answers the same way for an address that already has an account, which is then emailed a sign-in prompt rather than a code: this endpoint never reveals whether an address is registered.
1751
+ * @description Validates the screener payload (business email + business name) and starts an identity registration session. Answers the same way for an address that already has an account, which is then emailed a sign-in prompt rather than a code: this endpoint never reveals whether an address is registered. While GET /identity/bot_challenge_settings answers required=true, a request without a valid challenge_token is refused (bot_challenge_required / bot_challenge_failed) before any email or CRM lead.
1708
1752
  */
1709
1753
  post: operations["signup.screener.submit"];
1710
1754
  delete?: never;
@@ -2467,6 +2511,52 @@ export interface components {
2467
2511
  /** @description Required for Live keys; omitted for Test keys */
2468
2512
  totp_code?: string;
2469
2513
  };
2514
+ SignupBotChallengeSettings: {
2515
+ /** @description Whether POST /signup/screener/submit and POST /signup/screener/resend_otp refuse a request without a valid challenge_token. */
2516
+ required: boolean;
2517
+ /** @description The public site key to render the challenge widget with. Empty when required is false. */
2518
+ site_key: string;
2519
+ };
2520
+ NetworksOutput: {
2521
+ networks: components["schemas"]["NetworksNetworkItem"][] | null;
2522
+ /** @description Whether this deployment accepts changes to the networks. */
2523
+ writes_enabled: boolean;
2524
+ };
2525
+ NetworksNetworkItem: {
2526
+ carries: components["schemas"]["NetworksCarriesView"];
2527
+ /** @description Whether the business's saved choice includes this network, eligible or not. */
2528
+ chosen: boolean;
2529
+ /** @description Whether this is the default network. At most one network is the default, and it is an enabled one. */
2530
+ default: boolean;
2531
+ /** @description Whether the business may use this network at all, from the rollout settings. Turning a network on never grants a rail. */
2532
+ eligible: boolean;
2533
+ /** @description Whether the business can use this network now: chosen and eligible. */
2534
+ enabled: boolean;
2535
+ /** @description The amounts held on this network, formatted for display, such as 10,000.00 USDC. Empty when none, and when holdings_unavailable. */
2536
+ held: string[] | null;
2537
+ /** @description True when what the network holds could not be read. Held and pending_transactions are then not an answer, and the network cannot be turned off. */
2538
+ holdings_unavailable: boolean;
2539
+ network: components["schemas"]["IdentityNetwork"];
2540
+ /** @description Whether a transaction is in flight on this network or a transfer approval for it is waiting. */
2541
+ pending_transactions: boolean;
2542
+ /** @description Why this enabled network cannot be turned off, worded for the person who sees it. Absent when it can be, and for a network that is not enabled. */
2543
+ turn_off_blocked?: string;
2544
+ };
2545
+ NetworksCarriesView: {
2546
+ /** @description Whether USDC can be received on this network. */
2547
+ deposits: boolean;
2548
+ /** @description Symbols of the funds that can be bought and sold with settlement on this network. BTC trades on no network and is never listed. */
2549
+ funds: string[] | null;
2550
+ /** @description Whether USDC can be sent on this network. */
2551
+ withdrawals: boolean;
2552
+ };
2553
+ /** @enum {string} */
2554
+ IdentityNetwork: "ethereum" | "stellar" | "solana";
2555
+ NetworksSetNetworksInput: {
2556
+ default_network: components["schemas"]["IdentityNetwork"];
2557
+ /** @description The networks to use. At least one, each listed once, each one the business is eligible for. */
2558
+ enabled_networks: components["schemas"]["IdentityNetwork"][] | null;
2559
+ };
2470
2560
  IdentityInviteStep2Input: {
2471
2561
  session_token?: string;
2472
2562
  };
@@ -2915,6 +3005,8 @@ export interface components {
2915
3005
  Success?: boolean;
2916
3006
  };
2917
3007
  SignupResendOTPInput: {
3008
+ /** @description The bot-challenge token the widget issued for the resend_otp action. Required while GET /identity/bot_challenge_settings answers required=true; ignored otherwise. Single use. */
3009
+ challenge_token?: string;
2918
3010
  email?: string;
2919
3011
  otp_session_id?: string;
2920
3012
  };
@@ -2923,6 +3015,8 @@ export interface components {
2923
3015
  };
2924
3016
  SignupScreenerSubmitInput: {
2925
3017
  business_name?: string;
3018
+ /** @description The bot-challenge token the widget issued for the signup action. Required while GET /identity/bot_challenge_settings answers required=true; ignored otherwise. Single use. */
3019
+ challenge_token?: string;
2926
3020
  email?: string;
2927
3021
  first_name?: string;
2928
3022
  last_name?: string;
@@ -5839,6 +5933,142 @@ export interface operations {
5839
5933
  };
5840
5934
  };
5841
5935
  };
5936
+ "identity.bot_challenge_settings.get": {
5937
+ parameters: {
5938
+ query?: never;
5939
+ header?: never;
5940
+ path?: never;
5941
+ cookie?: never;
5942
+ };
5943
+ requestBody?: never;
5944
+ responses: {
5945
+ /** @description OK */
5946
+ 200: {
5947
+ headers: {
5948
+ [name: string]: unknown;
5949
+ };
5950
+ content: {
5951
+ "application/json": components["schemas"]["SignupBotChallengeSettings"];
5952
+ };
5953
+ };
5954
+ /** @description Error response. */
5955
+ default: {
5956
+ headers: {
5957
+ [name: string]: unknown;
5958
+ };
5959
+ content: {
5960
+ "application/json": components["schemas"]["HttputilAPIError"];
5961
+ };
5962
+ };
5963
+ };
5964
+ };
5965
+ "identity.business.networks.get": {
5966
+ parameters: {
5967
+ query?: never;
5968
+ header?: never;
5969
+ path?: never;
5970
+ cookie?: never;
5971
+ };
5972
+ requestBody?: never;
5973
+ responses: {
5974
+ /** @description OK */
5975
+ 200: {
5976
+ headers: {
5977
+ [name: string]: unknown;
5978
+ };
5979
+ content: {
5980
+ "application/json": components["schemas"]["NetworksOutput"];
5981
+ };
5982
+ };
5983
+ /** @description Unauthorized */
5984
+ 401: {
5985
+ headers: {
5986
+ [name: string]: unknown;
5987
+ };
5988
+ content: {
5989
+ "application/json": components["schemas"]["HttputilAPIError"];
5990
+ };
5991
+ };
5992
+ /** @description Forbidden */
5993
+ 403: {
5994
+ headers: {
5995
+ [name: string]: unknown;
5996
+ };
5997
+ content: {
5998
+ "application/json": components["schemas"]["HttputilAPIError"];
5999
+ };
6000
+ };
6001
+ /** @description Error response. */
6002
+ default: {
6003
+ headers: {
6004
+ [name: string]: unknown;
6005
+ };
6006
+ content: {
6007
+ "application/json": components["schemas"]["HttputilAPIError"];
6008
+ };
6009
+ };
6010
+ };
6011
+ };
6012
+ "identity.business.networks.set": {
6013
+ parameters: {
6014
+ query?: never;
6015
+ header?: never;
6016
+ path?: never;
6017
+ cookie?: never;
6018
+ };
6019
+ requestBody?: {
6020
+ content: {
6021
+ "application/json": components["schemas"]["NetworksSetNetworksInput"];
6022
+ };
6023
+ };
6024
+ responses: {
6025
+ /** @description OK */
6026
+ 200: {
6027
+ headers: {
6028
+ [name: string]: unknown;
6029
+ };
6030
+ content: {
6031
+ "application/json": components["schemas"]["NetworksOutput"];
6032
+ };
6033
+ };
6034
+ /** @description Bad Request */
6035
+ 400: {
6036
+ headers: {
6037
+ [name: string]: unknown;
6038
+ };
6039
+ content: {
6040
+ "application/json": components["schemas"]["HttputilAPIError"];
6041
+ };
6042
+ };
6043
+ /** @description Unauthorized */
6044
+ 401: {
6045
+ headers: {
6046
+ [name: string]: unknown;
6047
+ };
6048
+ content: {
6049
+ "application/json": components["schemas"]["HttputilAPIError"];
6050
+ };
6051
+ };
6052
+ /** @description Forbidden */
6053
+ 403: {
6054
+ headers: {
6055
+ [name: string]: unknown;
6056
+ };
6057
+ content: {
6058
+ "application/json": components["schemas"]["HttputilAPIError"];
6059
+ };
6060
+ };
6061
+ /** @description Error response. */
6062
+ default: {
6063
+ headers: {
6064
+ [name: string]: unknown;
6065
+ };
6066
+ content: {
6067
+ "application/json": components["schemas"]["HttputilAPIError"];
6068
+ };
6069
+ };
6070
+ };
6071
+ };
5842
6072
  "identity.business_invites.step2": {
5843
6073
  parameters: {
5844
6074
  query?: never;
@@ -7893,6 +8123,33 @@ export interface operations {
7893
8123
  "application/json": components["schemas"]["SignupResendOTPAck"];
7894
8124
  };
7895
8125
  };
8126
+ /** @description Bad Request */
8127
+ 400: {
8128
+ headers: {
8129
+ [name: string]: unknown;
8130
+ };
8131
+ content: {
8132
+ "application/json": components["schemas"]["HttputilAPIError"];
8133
+ };
8134
+ };
8135
+ /** @description Too Many Requests */
8136
+ 429: {
8137
+ headers: {
8138
+ [name: string]: unknown;
8139
+ };
8140
+ content: {
8141
+ "application/json": components["schemas"]["HttputilAPIError"];
8142
+ };
8143
+ };
8144
+ /** @description Service Unavailable */
8145
+ 503: {
8146
+ headers: {
8147
+ [name: string]: unknown;
8148
+ };
8149
+ content: {
8150
+ "application/json": components["schemas"]["HttputilAPIError"];
8151
+ };
8152
+ };
7896
8153
  /** @description Error response. */
7897
8154
  default: {
7898
8155
  headers: {
@@ -7926,6 +8183,33 @@ export interface operations {
7926
8183
  "application/json": components["schemas"]["SignupScreenerSubmitOutput"];
7927
8184
  };
7928
8185
  };
8186
+ /** @description Bad Request */
8187
+ 400: {
8188
+ headers: {
8189
+ [name: string]: unknown;
8190
+ };
8191
+ content: {
8192
+ "application/json": components["schemas"]["HttputilAPIError"];
8193
+ };
8194
+ };
8195
+ /** @description Too Many Requests */
8196
+ 429: {
8197
+ headers: {
8198
+ [name: string]: unknown;
8199
+ };
8200
+ content: {
8201
+ "application/json": components["schemas"]["HttputilAPIError"];
8202
+ };
8203
+ };
8204
+ /** @description Service Unavailable */
8205
+ 503: {
8206
+ headers: {
8207
+ [name: string]: unknown;
8208
+ };
8209
+ content: {
8210
+ "application/json": components["schemas"]["HttputilAPIError"];
8211
+ };
8212
+ };
7929
8213
  /** @description Error response. */
7930
8214
  default: {
7931
8215
  headers: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable_sea/sdk",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [