Skip to content

[grid] add SMS OTP auth API#617

Draft
DhruvPareek wants to merge 2 commits into
mainfrom
dp/grid-sms-otp-openapi
Draft

[grid] add SMS OTP auth API#617
DhruvPareek wants to merge 2 commits into
mainfrom
dp/grid-sms-otp-openapi

Conversation

@DhruvPareek

@DhruvPareek DhruvPareek commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Overview

  • Add SMS_OTP as a first-class auth method discriminator.
  • Add SMS OTP create and verify request schemas.
  • Document SMS OTP behavior for credential create, challenge, and verify endpoints.
  • Document duplicate SMS OTP registration as 400 Error400 with code SMS_OTP_CREDENTIAL_ALREADY_EXISTS.
  • Regenerate the root and Mintlify OpenAPI specs from openapi/.

Endpoint Shape After This Change

No endpoint path or header changes. This adds SMS_OTP as another discriminator branch in the existing Embedded Wallet Auth credential flows.

POST /auth/credentials now accepts an SMS OTP create request:

{
  "type": "SMS_OTP",
  "accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
}

The unsigned add-credential request still returns 202 AuthSignedRequestChallenge:

{
  "type": "SMS_OTP",
  "payloadToSign": "...",
  "requestId": "Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21",
  "expiresAt": "2026-04-08T15:35:00Z"
}

The signed retry returns 201 AuthMethodResponse:

{
  "id": "AuthMethod:019542f5-b3e7-1d02-0000-000000000001",
  "accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002",
  "type": "SMS_OTP",
  "nickname": "+14155550123",
  "otpEncryptionTargetBundle": "{...}",
  "createdAt": "2026-04-08T15:30:01Z",
  "updatedAt": "2026-04-08T15:30:01Z"
}

If the target wallet already has an SMS OTP credential, POST /auth/credentials returns 400 Error400:

{
  "status": 400,
  "code": "SMS_OTP_CREDENTIAL_ALREADY_EXISTS",
  "message": "This wallet already has an SMS_OTP credential. Delete the existing one via DELETE /auth/credentials/{id} before adding a new phone number."
}

POST /auth/credentials/{id}/challenge treats SMS OTP like email OTP: the request body can be empty, and the response is 200 AuthMethodResponse with type: "SMS_OTP" plus a fresh otpEncryptionTargetBundle.

{}

POST /auth/credentials/{id}/verify now accepts an SMS OTP verify request:

{
  "type": "SMS_OTP",
  "encryptedOtpBundle": "{\"encappedPublic\":\"...\",\"ciphertext\":\"...\"}"
}

The first verify leg returns 202 AuthSignedRequestChallenge; the signed retry sends the same body with Grid-Wallet-Signature and Request-Id, then returns 200 AuthSession. SMS OTP sessions omit encryptedSessionSigningKey because the client keeps the TEK private key.

{
  "id": "Session:019542f5-b3e7-1d02-0000-000000000003",
  "accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002",
  "type": "SMS_OTP",
  "nickname": "+14155550123",
  "expiresAt": "2026-04-08T16:30:01Z"
}

Downstream

  • lightsparkdev/webdev#29296 — regenerate the vendored grid-api client/spec output.
  • lightsparkdev/webdev#29299 — key pending OTPs by auth method.
  • lightsparkdev/webdev#29300 — add Turnkey SMS OTP primitives.
  • lightsparkdev/webdev#29301 — implement SMS OTP create/add handler logic.
  • lightsparkdev/webdev#29302 — cover SMS OTP create/add flows.
  • lightsparkdev/webdev#29249 — add SMS OTP challenge, verify, and delete behavior.

Test Plan

  • make build
  • make lint (passes; existing warning output remains)

@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Jun 26, 2026 12:06am
grid-wallet-demo Ignored Ignored Preview Jun 26, 2026 12:06am

Request Review

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

This PR will update the grid SDKs with the following commit messages.

cli

fix(types): correct auth-credential-verify-request type to map[string]any

csharp

feat(api): add SMS OTP authentication method to credentials

go

feat(api): add SMS_OTP credential type to auth credentials

kotlin

feat(api): add SMS_OTP credential type to auth credentials

openapi

feat(api): add SMS_OTP credential type to auth credentials

php

feat(api): add SMS_OTP credential support to auth credentials

python

feat(api): add SMS_OTP credential type to auth

ruby

feat(api): add SMS_OTP authentication method to auth credentials

typescript

feat(api): add SMS_OTP credential type to auth credentials

Edit this comment to update them. They will appear in their respective SDK's changelogs.

⚠️ grid-openapi studio · code · diff

Your SDK build had at least one "warning" diagnostic, which is a regression from the base state.
generate ⚠️ (prev: generate ✅)

New diagnostics (1 warning)
⚠️ Parameter/DuplicateNames: Duplicate parameters were renamed: `type`
grid-ruby studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

grid-go studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@e3c0e0d8dacdce0464133da3dab6bd57830f4967
New diagnostics (2 note)
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
grid-typescript studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

npm install https://pkg.stainless.com/s/grid-typescript/2c8ac0cd6a926b16405841d52a5e29b00d57a5f8/dist.tar.gz
⚠️ grid-kotlin studio · code · diff

Your SDK build had at least one "warning" diagnostic, which is a regression from the base state.
generate ⚠️ (prev: generate ✅) → build ✅lint ✅test ❗ (prev: test ✅)

New diagnostics (1 warning, 2 note)
⚠️ Parameter/DuplicateNames: Duplicate parameters were renamed: `type`
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
grid-python studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ❗test ❗

pip install https://pkg.stainless.com/s/grid-python/99198089c7b704b43877cff8ec4d088167134950/grid-0.0.1-py3-none-any.whl
grid-csharp studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ⚠️build ❗lint ✅test ❗

New diagnostics (3 note)
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Name/Renamed: 262 names were renamed due to language constraints, so fallback names will be used instead.
grid-php studio · code · diff

Your SDK build had at least one new note diagnostic, which is a regression from the base state.
generate ✅lint ✅test ✅

New diagnostics (2 note)
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
💡 Schema/EnumHasOneMember: Confirm intentional use of `enum` with single member.
grid-cli studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ❗lint ❗test ❗


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-06-26 00:10:59 UTC

@DhruvPareek DhruvPareek force-pushed the dp/grid-sms-otp-openapi branch from f5862f7 to ed1398a Compare June 25, 2026 22:49
@github-actions github-actions Bot added the breaking-change Introduces a breaking change to the OpenAPI spec label Jun 25, 2026
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

This PR introduces breaking changes to openapi.yaml:

API Changelog 2025-10-13 vs. 2026-06-25

API Changes

GET /agents

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /agents/approvals

  • ⚠️ removed the required property data/items/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property data/items/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/device-codes/{code}/redeem

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /agents/me/actions

  • ⚠️ removed the required property data/items/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property data/items/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status

GET /agents/me/actions/{actionId}

  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status

GET /agents/me/external-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/me/external-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/me/quotes

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/me/quotes/{quoteId}/execute

  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /agents/me/transactions

  • ⚠️ removed the required property data/items/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property data/items/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /agents/me/transactions/{transactionId}

  • ⚠️ removed the required property oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status

POST /agents/me/transfer-in

  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/me/transfer-out

  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ removed the request property remittanceInformation
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /agents/{agentId}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/{agentId}/actions/{actionId}/approve

  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/{agentId}/actions/{actionId}/reject

  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /agents/{agentId}/device-codes

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /agents/{agentId}/policy

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /auth/credentials

  • ⚠️ added the new SMS_OTP enum value to the data/items/type response property for the response status 200
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /auth/credentials

  • ⚠️ added the new SMS_OTP enum value to the allOf[#/components/schemas/AuthMethod]/type response property for the response status 201
  • ⚠️ added the new SMS_OTP enum value to the allOf[subschema #2]/type response property for the response status 202
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

DELETE /auth/credentials/{id}

  • ⚠️ added the new SMS_OTP enum value to the allOf[subschema #2]/type response property for the response status 202
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /auth/credentials/{id}/challenge

  • ⚠️ added the new SMS_OTP enum value to the oneOf[subschema #1: Auth Method Response]/allOf[#/components/schemas/AuthMethod]/type response property for the response status 200
  • ⚠️ added the new SMS_OTP enum value to the oneOf[subschema #2: Passkey Auth Challenge]/allOf[#/components/schemas/AuthMethod]/type response property for the response status 200
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /auth/credentials/{id}/verify

  • ⚠️ added the new SMS_OTP enum value to the allOf[#/components/schemas/AuthMethod]/type response property for the response status 200
  • ⚠️ added the new SMS_OTP enum value to the allOf[subschema #2]/type response property for the response status 202
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /auth/delegated-keys

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /auth/delegated-keys

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

DELETE /auth/delegated-keys/{id}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /auth/sessions

  • ⚠️ added the new SMS_OTP enum value to the data/items/allOf[#/components/schemas/AuthMethod]/type response property for the response status 200
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

DELETE /auth/sessions/{id}

  • ⚠️ added the new SMS_OTP enum value to the allOf[subschema #2]/type response property for the response status 202
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /auth/sessions/{id}/refresh

  • ⚠️ added the new SMS_OTP enum value to the allOf[#/components/schemas/AuthMethod]/type response property for the response status 201
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /beneficial-owners

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /beneficial-owners

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /beneficial-owners/{beneficialOwnerId}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /cards

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /cards

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /cards/{id}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /config

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /crypto/estimate-withdrawal-fee

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /customers

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /customers

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /customers/external-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /customers/external-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /customers/internal-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /customers/{customerId}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /customers/{customerId}/kyc-link

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /customers/{customerId}/verify-email/confirm

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /customers/{customerId}/verify-phone/confirm

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /discoveries

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /documents

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /documents

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PUT /documents/{documentId}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /exchange-rates

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

PATCH /internal-accounts/{id}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /internal-accounts/{id}/export

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /invitations

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /invitations/{invitationCode}/cancel

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /invitations/{invitationCode}/claim

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /platform/external-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /platform/external-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /platform/internal-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /quotes

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /quotes/{quoteId}/execute

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /receiver/external-account/{accountId}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /receiver/uma/{receiverUmaAddress}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/cards/{id}/simulate/authorization

  • ⚠️ removed the required property direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/cards/{id}/simulate/clearing

  • ⚠️ removed the required property direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/cards/{id}/simulate/return

  • ⚠️ removed the required property direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/internal-accounts/{accountId}/fund

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/send

  • ⚠️ removed the required property allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/uma/receive

  • ⚠️ removed the required property allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /sandbox/webhooks/test

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /stablecoin-provider-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /stablecoin-provider-accounts

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /tokens

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /tokens

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

DELETE /tokens/{tokenId}

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /transactions

  • ⚠️ removed the required property data/items/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property data/items/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /transactions/{transactionId}

  • ⚠️ removed the required property oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status

POST /transactions/{transactionId}/approve

  • ⚠️ removed the required property allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /transactions/{transactionId}/confirm

  • ⚠️ removed the required property oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ removed the required property oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /transactions/{transactionId}/reject

  • ⚠️ removed the required property allOf[#/components/schemas/Transaction]/direction from the response with the 200 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /transfer-in

  • ⚠️ removed the required property oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ removed the required property oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /transfer-out

  • ⚠️ removed the required property oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ removed the required property oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction from the response with the 201 status
  • ⚠️ removed the request property remittanceInformation
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

GET /verifications

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST /verifications

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:agent-action

  • ⚠️ removed the request property allOf[subschema #2]/data/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction
  • ⚠️ removed the request property allOf[subschema #2]/data/transaction/allOf[#/components/schemas/TransactionOneOf]/oneOf[subschema #2: Outgoing Transaction]/allOf[#/components/schemas/Transaction]/direction

POST webhook:bulk-upload

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:card-funding-source-change

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:card-state-change

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:customer-update

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:incoming-payment

  • ⚠️ removed the request property allOf[subschema #2]/data/allOf[subschema #1: Incoming Transaction]/allOf[#/components/schemas/Transaction]/direction
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:internal-account-status

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:invitation-claimed

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:outgoing-payment

  • ⚠️ removed the request property allOf[subschema #2]/data/allOf[#/components/schemas/Transaction]/direction
  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:test-webhook

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

POST webhook:verification-update

  • ⚠️ added the new SMS_OTP_CREDENTIAL_ALREADY_EXISTS enum value to the code response property for the response status 400

Detected by oasdiff. This PR will need approval from an API reviewer before merge.

@DhruvPareek DhruvPareek force-pushed the dp/grid-sms-otp-openapi branch from ed1398a to 0119e58 Compare June 25, 2026 23:13
@DhruvPareek DhruvPareek marked this pull request as ready for review June 25, 2026 23:54
@DhruvPareek DhruvPareek marked this pull request as draft June 25, 2026 23:56
@DhruvPareek DhruvPareek marked this pull request as ready for review June 25, 2026 23:56

Copy link
Copy Markdown
Contributor Author

this comment is expected and shouldnt matter because nobody is using this stuff yet

@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds SMS_OTP as a first-class auth method discriminator across the Embedded Wallet Auth credential flows, introducing two new schemas (SmsOtpCredentialCreateRequest, SmsOtpCredentialVerifyRequest) and updating all affected path definitions, discriminator mappings, and error codes. The bundled root and Mintlify specs are regenerated from the source openapi/ directory.

  • New SMS_OTP discriminator branch added to AuthCredentialCreateRequestOneOf, AuthCredentialVerifyRequestOneOf, AuthCredentialResponseOneOf, AuthMethodType, and Error400 (SMS_OTP_CREDENTIAL_ALREADY_EXISTS).
  • All three auth credential path files updated with SMS OTP descriptions, request body examples, and response documentation covering the create → challenge → verify two-leg flow.
  • AuthSession, AuthSignedRequestChallenge, AuthMethodResponse, and AuthCredentialChallengeRequest schemas updated to explicitly include SMS_OTP alongside EMAIL_OTP in field descriptions.

Confidence Score: 5/5

Safe to merge — all schema changes are additive, discriminator mappings are consistent, and the generated bundles match the source.

The change is purely additive OpenAPI documentation. New schemas are correctly structured using the same allOf composition pattern as the existing email OTP schemas. Discriminator mappings, required fields, enum values, and error codes are all internally consistent. No existing schemas are broken.

No files require special attention. Minor documentation gaps (missing examples) are noted in inline comments but do not affect correctness.

Important Files Changed

Filename Overview
openapi/components/schemas/auth/AuthMethodType.yaml Added SMS_OTP to the enum and description; all four credential types are now documented.
openapi/components/schemas/auth/AuthCredentialCreateRequestOneOf.yaml Added SMS_OTP → SmsOtpCredentialCreateRequest to both the oneOf list and discriminator mapping; consistent with the existing pattern.
openapi/components/schemas/auth/AuthCredentialVerifyRequestOneOf.yaml Added SMS_OTP → SmsOtpCredentialVerifyRequest to oneOf and discriminator mapping; mirrors the create-request pattern correctly.
openapi/components/schemas/auth/AuthCredentialResponseOneOf.yaml Added SMS_OTP → AuthMethodResponse discriminator mapping so the challenge endpoint correctly routes SMS OTP responses to the same schema as email OTP.
openapi/components/schemas/errors/Error400.yaml Added SMS_OTP_CREDENTIAL_ALREADY_EXISTS to both the markdown description table and the string enum, keeping the two in sync.
openapi/paths/auth/auth_credentials.yaml Updated POST description and 201/202/400 responses to cover SMS OTP; added smsOtp request body and 201/202 examples. GET list example still omits SMS_OTP credential.
openapi/paths/auth/auth_credentials_{id}_challenge.yaml Updated description and request body to include SMS OTP; 200 response examples still omit smsOtp (noted in prior review comment).
openapi/paths/auth/auth_credentials_{id}_verify.yaml Updated description and request body examples for SMS OTP; 202 response example and smsOtpSignedRetry request body example are missing, leaving the two-leg flow asymmetrically documented.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant Grid as Grid API

    Note over Client,Grid: Step 1 — Register SMS OTP credential
    Client->>Grid: "POST /auth/credentials {type:SMS_OTP, accountId}"
    Grid-->>Client: 202 AuthSignedRequestChallenge (payloadToSign, requestId)
    Client->>Grid: POST /auth/credentials [Grid-Wallet-Signature, Request-Id]
    Grid-->>Client: "201 AuthMethod (SMS_OTP, nickname=+E.164, otpEncryptionTargetBundle)"
    Note over Grid: OTP sent to phone number on signed retry

    Note over Client,Grid: Step 2 — Challenge (if needed)
    Client->>Grid: "POST /auth/credentials/{id}/challenge {}"
    Grid-->>Client: 200 AuthMethodResponse (fresh otpEncryptionTargetBundle)
    Note over Grid: New OTP sent to phone

    Note over Client,Grid: Step 3 — Verify (two-leg OTP flow)
    Client->>Client: Generate TEK keypair
    Client->>Client: "HPKE-encrypt {otp_code, TEK.public} → encryptedOtpBundle"
    Client->>Grid: "POST /auth/credentials/{id}/verify {type:SMS_OTP, encryptedOtpBundle}"
    Grid-->>Client: 202 AuthSignedRequestChallenge (verificationToken as payloadToSign)
    Client->>Client: Sign verificationToken with TEK private key
    Client->>Grid: "POST /auth/credentials/{id}/verify [Grid-Wallet-Signature, Request-Id]"
    Grid-->>Client: 200 AuthSession (no encryptedSessionSigningKey — client holds TEK)
Loading
%%{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 Client
    participant Grid as Grid API

    Note over Client,Grid: Step 1 — Register SMS OTP credential
    Client->>Grid: "POST /auth/credentials {type:SMS_OTP, accountId}"
    Grid-->>Client: 202 AuthSignedRequestChallenge (payloadToSign, requestId)
    Client->>Grid: POST /auth/credentials [Grid-Wallet-Signature, Request-Id]
    Grid-->>Client: "201 AuthMethod (SMS_OTP, nickname=+E.164, otpEncryptionTargetBundle)"
    Note over Grid: OTP sent to phone number on signed retry

    Note over Client,Grid: Step 2 — Challenge (if needed)
    Client->>Grid: "POST /auth/credentials/{id}/challenge {}"
    Grid-->>Client: 200 AuthMethodResponse (fresh otpEncryptionTargetBundle)
    Note over Grid: New OTP sent to phone

    Note over Client,Grid: Step 3 — Verify (two-leg OTP flow)
    Client->>Client: Generate TEK keypair
    Client->>Client: "HPKE-encrypt {otp_code, TEK.public} → encryptedOtpBundle"
    Client->>Grid: "POST /auth/credentials/{id}/verify {type:SMS_OTP, encryptedOtpBundle}"
    Grid-->>Client: 202 AuthSignedRequestChallenge (verificationToken as payloadToSign)
    Client->>Client: Sign verificationToken with TEK private key
    Client->>Grid: "POST /auth/credentials/{id}/verify [Grid-Wallet-Signature, Request-Id]"
    Grid-->>Client: 200 AuthSession (no encryptedSessionSigningKey — client holds TEK)
Loading

Reviews (2): Last reviewed commit: "docs(grid): address SMS OTP auth OpenAPI..." | Re-trigger Greptile

@DhruvPareek DhruvPareek marked this pull request as draft June 26, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Introduces a breaking change to the OpenAPI spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant