release: 1.9.0#20
Conversation
|
🧪 Testing To try out this version of the SDK: Expires at: Sat, 01 Aug 2026 16:14:05 GMT |
6d92ed8 to
ddcf565
Compare
ddcf565 to
0bb0b25
Compare
0bb0b25 to
ca3e49f
Compare
ca3e49f to
47f7a2c
Compare
47f7a2c to
58f03d2
Compare
58f03d2 to
26db534
Compare
26db534 to
d258a43
Compare
d258a43 to
d09fc51
Compare
Greptile SummaryThis is the automated 1.9.0 release PR generated by Stainless, bundling approximately 25 commits of API additions, type reshaping, and bug fixes since 1.8.0. The release introduces encrypted SMS/OTP flows, CNY account support, payment-rail selection on transfer-out, new transaction fields, and a content-type header fix — but it also carries a significant volume of breaking TypeScript changes across public-facing resource types.
Confidence Score: 3/5Multiple TypeScript-breaking changes shipped in a minor version across core auth, customer, card, document, and shared-type modules — downstream TypeScript consumers will encounter compile errors without a corresponding major version bump. The release carries a large number of incompatible public-API type changes — method renames, required-field promotions, parameter-shape wrappings, and type repurposings — in a 1.8.x → 1.9.0 minor bump. Two new breaking changes not previously flagged are present:
|
| Filename | Overview |
|---|---|
| src/resources/auth/credentials.ts | Adds SMS_OTP credential type and encrypted OTP flow; CredentialVerifyParams.AuthCredentialVerifyRequest narrowed from unknown to SMS_OTP-specific interface, breaking EMAIL_OTP/OAUTH/PASSKEY verify() callers |
| src/resources/shared.ts | Removes publicly exported BusinessInfoUpdate interface; promotes bankName to required in BDT/COP/GHS/PKR accounts; inverts EurBeneficiary optionality (breaking). EgpBeneficiary makes address/countryOfResidence/phoneNumber optional (non-breaking relaxation). |
| src/resources/auth/sessions.ts | Breaking param-shape change: SessionRefreshParams.clientPublicKey wrapped inside AuthSessionRefreshRequest; existing callers silently send an empty body |
| src/resources/customers/customers.ts | Multiple breaking changes: generateKYCLink renamed to createKYCLink, CustomerListResponse repurposed as paginated wrapper, CustomerUpdateInternalAccountParams.privateEnabled silently dropped |
| src/resources/cards.ts | Multiple breaking type renames/removals: CardRetrieveResponse→Card, CardUpdateResponse/CardIssueResponse removed, CardListResponse repurposed as paginated wrapper, PENDING_ISSUE → PROCESSING in state enum |
| src/resources/documents.ts | Breaking param-shape change: upload() and replace() now extract body from nested request key; callers passing old flat shape send body: undefined silently |
| src/resources/transfer-out.ts | Adds paymentRail selection and remittanceInformation to TransferOutCreateParams.Destination; destination type changed from ExternalAccountReference to inline Destination with new optional fields (additive, non-breaking) |
| src/resources/transactions.ts | Adds direction and receiptDeliveryConfirmedAt to transaction types; OutgoingTransaction.refund type changed from local namespace type to SimulateAPI.Refund (sandbox import in production module) |
| src/resources/verifications.ts | VerificationListResponse repurposed as paginated wrapper with incompatible shape; old item-type consumers get TS compile errors |
| src/resources/webhooks.ts | TestWebhookWebhookEvent removed from public namespace and from UnwrapWebhookEvent union; replaced by semantically mismatched SandboxWebhooksAPI.TestWebhookRequest |
| src/resources/platform/external-accounts.ts | bankName promoted to required in BDT/COP/GHS/PKR interfaces; EgpAccountInfo drops required accountNumber; both are breaking TypeScript changes in a minor release |
| src/resources/customers/external-accounts.ts | Adds CNY_ACCOUNT support with CnyAccount interface; extends ExternalAccountInfoOneOf union; additive changes, well-structured |
| src/resources/quotes.ts | Adds SWIFT and CNY payment instructions, FAMILY_SUPPORT/SALARY_PAYMENT purpose enum values, and QuoteRequest type; additive changes |
| packages/mcp-server/src/local-docs-search.ts | Large churn updating embedded code examples to reflect API changes (CNY, SWIFT, SMS_OTP, remittanceInformation, payment rail selection) |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant C as Client
participant G as Grid API
Note over C,G: SMS OTP / EMAIL OTP Encrypted Flow (NEW in 1.9.0)
C->>G: POST /auth/credentials (register SMS_OTP)
G-->>C: "202 {payloadToSign, requestId}"
C->>C: Sign payloadToSign with existing credential keypair
C->>G: POST /auth/credentials (signed retry + Grid-Wallet-Signature + Request-Id)
G-->>C: "201 AuthMethodResponse {otpEncryptionTargetBundle}"
Note over C: Generate ephemeral TEK keypair (P-256)
C->>C: "HPKE-encrypt {otp_code, public_key} under otpEncryptionTargetBundle"
C->>G: "POST /auth/credentials/{id}/verify {type:'SMS_OTP', encryptedOtpBundle}"
G-->>C: "202 {payloadToSign (verificationToken), requestId}"
C->>C: Sign verificationToken with TEK private key
C->>G: "POST /auth/credentials/{id}/verify (signed retry + Grid-Wallet-Signature)"
G-->>C: "200 AuthSession {expiresAt} (no encryptedSessionSigningKey — client holds TEK)"
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant C as Client
participant G as Grid API
Note over C,G: SMS OTP / EMAIL OTP Encrypted Flow (NEW in 1.9.0)
C->>G: POST /auth/credentials (register SMS_OTP)
G-->>C: "202 {payloadToSign, requestId}"
C->>C: Sign payloadToSign with existing credential keypair
C->>G: POST /auth/credentials (signed retry + Grid-Wallet-Signature + Request-Id)
G-->>C: "201 AuthMethodResponse {otpEncryptionTargetBundle}"
Note over C: Generate ephemeral TEK keypair (P-256)
C->>C: "HPKE-encrypt {otp_code, public_key} under otpEncryptionTargetBundle"
C->>G: "POST /auth/credentials/{id}/verify {type:'SMS_OTP', encryptedOtpBundle}"
G-->>C: "202 {payloadToSign (verificationToken), requestId}"
C->>C: Sign verificationToken with TEK private key
C->>G: "POST /auth/credentials/{id}/verify (signed retry + Grid-Wallet-Signature)"
G-->>C: "200 AuthSession {expiresAt} (no encryptedSessionSigningKey — client holds TEK)"
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
src/resources/auth/credentials.ts:802-834
**`CredentialVerifyParams.AuthCredentialVerifyRequest` narrowed to SMS_OTP-only — breaks EMAIL_OTP, OAUTH, and PASSKEY callers**
In 1.8.0 `AuthCredentialVerifyRequestOneOf` was `type AuthCredentialVerifyRequestOneOf = unknown`, so callers of `client.auth.credentials.verify()` could pass any shape (EMAIL_OTP, OAUTH, or PASSKEY payloads). In 1.9.0 it is narrowed to `interface AuthCredentialVerifyRequestOneOf { encryptedOtpBundle: string; type: 'SMS_OTP' }`. Any caller supplying a PASSKEY assertion (`{ assertion: {...} }`) or an OAUTH token payload (`{ type: 'OAUTH', oidcToken: '...' }`) now receives a `TS2345` compile error because those shapes are not assignable to `type: 'SMS_OTP'`. The parameter should accept a broader union (or remain `unknown`) to accommodate all supported credential types through the single `verify()` method.
Reviews (30): Last reviewed commit: "release: 1.9.0" | Re-trigger Greptile
d09fc51 to
c1ef000
Compare
|
|
||
| export interface VerificationListResponse { | ||
| /** | ||
| * Unique identifier for this verification | ||
| */ | ||
| id: string; | ||
|
|
||
| /** | ||
| * When this verification was created | ||
| */ | ||
| createdAt: string; | ||
|
|
||
| /** | ||
| * The ID of the customer being verified | ||
| * List of verifications matching the filter criteria | ||
| */ | ||
| customerId: string; | ||
| data: Array<Verification>; | ||
|
|
||
| /** | ||
| * List of issues preventing verification from proceeding. Empty when | ||
| * verificationStatus is APPROVED or IN_PROGRESS. | ||
| * Indicates if more results are available beyond this page | ||
| */ | ||
| errors: Array<Shared.VerificationError>; | ||
| hasMore: boolean; | ||
|
|
||
| /** | ||
| * Current status of the KYC/KYB verification | ||
| * Cursor to retrieve the next page of results (only present if hasMore is true) | ||
| */ | ||
| verificationStatus: | ||
| | 'RESOLVE_ERRORS' | ||
| | 'PENDING_MANUAL_REVIEW' | ||
| | 'IN_PROGRESS' | ||
| | 'APPROVED' | ||
| | 'REJECTED' | ||
| | 'READY_FOR_VERIFICATION'; | ||
| nextCursor?: string; | ||
|
|
||
| /** | ||
| * When this verification was last updated | ||
| * Total number of results matching the criteria |
There was a problem hiding this comment.
VerificationListResponse repurposed with an incompatible shape
VerificationListResponse previously described a single verification record (id, createdAt, customerId, errors, verificationStatus, updatedAt). It was the item type iterated over by the list() method. In this PR it is redefined as a paginated wrapper (data: Array<Verification>, hasMore, nextCursor, totalCount) while the list() method now yields Verification items directly.
Any TypeScript consumer that referenced Verifications.VerificationListResponse as the shape of a single verification will get a compile error because the fields no longer exist. Additionally, the new type is never returned by any method on Verifications, making it a semantic orphan in the public namespace.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/resources/verifications.ts
Line: 157-175
Comment:
**`VerificationListResponse` repurposed with an incompatible shape**
`VerificationListResponse` previously described a single verification record (`id`, `createdAt`, `customerId`, `errors`, `verificationStatus`, `updatedAt`). It was the item type iterated over by the `list()` method. In this PR it is redefined as a paginated wrapper (`data: Array<Verification>`, `hasMore`, `nextCursor`, `totalCount`) while the `list()` method now yields `Verification` items directly.
Any TypeScript consumer that referenced `Verifications.VerificationListResponse` as the shape of a single verification will get a compile error because the fields no longer exist. Additionally, the new type is never returned by any method on `Verifications`, making it a semantic orphan in the public namespace.
How can I resolve this? If you propose a fix, please make it concise.c1ef000 to
97bfb69
Compare
97bfb69 to
2072d7c
Compare
2072d7c to
dedcdbf
Compare
48ced55 to
c94a17d
Compare
|
|
||
| data: CardStateChangeWebhookEvent.Data; | ||
| data: CardsAPI.Card; | ||
|
|
||
| /** | ||
| * ISO 8601 timestamp of when the webhook was sent | ||
| */ | ||
| timestamp: string; |
There was a problem hiding this comment.
TestWebhookWebhookEvent removed — breaking type export and semantic mismatch in UnwrapWebhookEvent
TestWebhookWebhookEvent was a public export from the Webhooks namespace and a member of the UnwrapWebhookEvent discriminated union. It is removed here and replaced in the union by SandboxWebhooksAPI.TestWebhookRequest. Any consumer typing against Webhooks.TestWebhookWebhookEvent now gets a TS2305 compile error. Beyond the breakage, inserting a type named TestWebhookRequest (which reads as a request payload to trigger a test webhook) into a union of received webhook events is semantically misleading to readers of the public API surface.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/resources/webhooks.ts
Line: 240-246
Comment:
**`TestWebhookWebhookEvent` removed — breaking type export and semantic mismatch in `UnwrapWebhookEvent`**
`TestWebhookWebhookEvent` was a public export from the `Webhooks` namespace and a member of the `UnwrapWebhookEvent` discriminated union. It is removed here and replaced in the union by `SandboxWebhooksAPI.TestWebhookRequest`. Any consumer typing against `Webhooks.TestWebhookWebhookEvent` now gets a `TS2305` compile error. Beyond the breakage, inserting a type named `TestWebhookRequest` (which reads as a *request* payload to trigger a test webhook) into a union of *received* webhook events is semantically misleading to readers of the public API surface.
How can I resolve this? If you propose a fix, please make it concise.c94a17d to
abbf989
Compare
abbf989 to
745f7bb
Compare
745f7bb to
3be7dc8
Compare
3be7dc8 to
e238bba
Compare
e238bba to
86db62b
Compare
86db62b to
be0b3b3
Compare
be0b3b3 to
05e5310
Compare
05e5310 to
b4db0df
Compare
| export interface CredentialVerifyParams { | ||
| /** | ||
| * Body param | ||
| * Body param: Verify an SMS-OTP credential via the same secure two-leg flow as | ||
| * email OTP. The client HPKE-encrypts the OTP code (together with its public key) | ||
| * under the `otpEncryptionTargetBundle` returned from registration or | ||
| * `POST /auth/credentials/{id}/challenge`, submits the result here, and receives | ||
| * `202` with a `payloadToSign` carrying a `verificationToken` bound to the | ||
| * client's public key. The client signs that token with the matching private key | ||
| * and retries this request with `Grid-Wallet-Signature` + `Request-Id` headers to | ||
| * obtain the session. Plaintext OTP codes are never sent over the wire. | ||
| */ | ||
| AuthCredentialVerifyRequest: AuthCredentialVerifyRequestOneOf; | ||
|
|
||
| /** | ||
| * Header param: The `requestId` returned alongside the Grid-issued `challenge` | ||
| * from `POST /auth/credentials/{id}/challenge`, echoed back exactly here so Grid | ||
| * can correlate the assertion with the pending challenge. | ||
| * Header param: Full API-key stamp built over the prior `payloadToSign` with the | ||
| * TEK (Target Encryption Key) keypair the client generated for this login. | ||
| * Required on the signed retry that completes an `EMAIL_OTP` or `SMS_OTP` | ||
| * verification. Not used by `OAUTH` or `PASSKEY` verification, which complete in a | ||
| * single call. | ||
| */ | ||
| 'Grid-Wallet-Signature'?: string; | ||
|
|
||
| /** | ||
| * Header param: The `requestId` returned in a prior `202` response from this | ||
| * endpoint, echoed back exactly here so the server can correlate the signed retry | ||
| * with the issued challenge. Required on the signed retry that completes an | ||
| * `EMAIL_OTP` or `SMS_OTP` verification; must be paired with | ||
| * `Grid-Wallet-Signature`. For `PASSKEY` verification, the `requestId` issued from | ||
| * `POST /auth/credentials/{id}/challenge` is echoed here instead so the server can | ||
| * correlate the assertion with the pending challenge. | ||
| */ | ||
| 'Request-Id'?: string; | ||
| } |
There was a problem hiding this comment.
CredentialVerifyParams.AuthCredentialVerifyRequest narrowed to SMS_OTP-only — breaks EMAIL_OTP, OAUTH, and PASSKEY callers
In 1.8.0 AuthCredentialVerifyRequestOneOf was type AuthCredentialVerifyRequestOneOf = unknown, so callers of client.auth.credentials.verify() could pass any shape (EMAIL_OTP, OAUTH, or PASSKEY payloads). In 1.9.0 it is narrowed to interface AuthCredentialVerifyRequestOneOf { encryptedOtpBundle: string; type: 'SMS_OTP' }. Any caller supplying a PASSKEY assertion ({ assertion: {...} }) or an OAUTH token payload ({ type: 'OAUTH', oidcToken: '...' }) now receives a TS2345 compile error because those shapes are not assignable to type: 'SMS_OTP'. The parameter should accept a broader union (or remain unknown) to accommodate all supported credential types through the single verify() method.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/resources/auth/credentials.ts
Line: 802-834
Comment:
**`CredentialVerifyParams.AuthCredentialVerifyRequest` narrowed to SMS_OTP-only — breaks EMAIL_OTP, OAUTH, and PASSKEY callers**
In 1.8.0 `AuthCredentialVerifyRequestOneOf` was `type AuthCredentialVerifyRequestOneOf = unknown`, so callers of `client.auth.credentials.verify()` could pass any shape (EMAIL_OTP, OAUTH, or PASSKEY payloads). In 1.9.0 it is narrowed to `interface AuthCredentialVerifyRequestOneOf { encryptedOtpBundle: string; type: 'SMS_OTP' }`. Any caller supplying a PASSKEY assertion (`{ assertion: {...} }`) or an OAUTH token payload (`{ type: 'OAUTH', oidcToken: '...' }`) now receives a `TS2345` compile error because those shapes are not assignable to `type: 'SMS_OTP'`. The parameter should accept a broader union (or remain `unknown`) to accommodate all supported credential types through the single `verify()` method.
How can I resolve this? If you propose a fix, please make it concise.b4db0df to
a24ec24
Compare
a24ec24 to
e5a00e1
Compare
e5a00e1 to
f113094
Compare
f113094 to
3375f30
Compare
3375f30 to
1707778
Compare
Automated Release PR
1.9.0 (2026-07-02)
Full Changelog: v1.8.0...v1.9.0
Features
Bug Fixes
Chores
Documentation
This pull request is managed by Stainless's GitHub App.
The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.
For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.
🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions