Skip to content

[grid] add SMS OTP auth API#617

Merged
DhruvPareek merged 2 commits into
mainfrom
dp/grid-sms-otp-openapi
Jun 26, 2026
Merged

[grid] add SMS OTP auth API#617
DhruvPareek merged 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
⚠️ grid-openapi studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️

grid-ruby studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅build ✅lint ✅test ✅

⚠️ grid-go studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@3d70774f1af99b6d9fa78fa16f65517342f28b99
grid-typescript studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅build ✅lint ✅test ✅

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

Your SDK build had a failure in the test CI job, which is a regression from the base state.
generate ⚠️build ✅lint ✅test ❗

⚠️ grid-python studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

pip install https://pkg.stainless.com/s/grid-python/4158fab0905af5fa6f90ad3beba0f597496338f7/grid-0.0.1-py3-none-any.whl
⚠️ grid-csharp studio · code

Your SDK build had a failure in the build CI job, which is a regression from the base state.
generate ⚠️build ❗lint ✅test ❗

grid-php studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅lint ✅test ✅

⚠️ grid-cli studio · code

Your SDK build had a failure in the build CI job, which is a regression from the base state.
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 20:11:37 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 introduces SMS_OTP as a first-class auth method across the Embedded Wallet Auth API — adding new create and verify request schemas, updating all discriminator mappings, documenting the duplicate-registration error code, and regenerating the root and Mintlify OpenAPI bundles.

  • New SmsOtpCredentialCreateRequest and SmsOtpCredentialVerifyRequest schemas follow the same allOf composition pattern as their EmailOtp counterparts; the two-leg HPKE OTP flow, error codes, and session omission of encryptedSessionSigningKey are correctly documented throughout.
  • AuthMethodType, AuthCredentialCreateRequestOneOf, AuthCredentialVerifyRequestOneOf, AuthCredentialResponseOneOf, Error400, AuthMethodResponse, and AuthSession schemas are all consistently updated to include SMS_OTP.
  • A few example entries in the verify endpoint and the credential list response are missing SMS_OTP coverage (noted as P2 suggestions).

Confidence Score: 5/5

This is a documentation-only change that adds SMS OTP as a new auth method. All schema compositions, discriminator mappings, error codes, and flow descriptions are accurate and consistent with existing patterns.

The new SMS_OTP schemas follow the identical allOf composition and discriminator pattern established by EMAIL_OTP with no deviations. Error codes, session field omission, and two-leg flow documentation are all correct. The only gaps are missing example entries in a couple of response/request blocks, which do not affect schema correctness or API behavior.

auth_credentials_{id}_verify.yaml is missing a 202 smsOtp response example and a smsOtpSignedRetry request body example — purely documentation gaps that do not affect the schema.

Important Files Changed

Filename Overview
openapi/components/schemas/auth/SmsOtpCredentialCreateRequest.yaml New schema composing AuthCredentialCreateRequest + SmsOtpCredentialCreateRequestFields via allOf; mirrors the EmailOtp pattern exactly.
openapi/components/schemas/auth/SmsOtpCredentialVerifyRequestFields.yaml Requires type and encryptedOtpBundle; includes accurate description of the HPKE two-leg OTP flow and a well-formed example ciphertext blob.
openapi/components/schemas/auth/AuthCredentialCreateRequestOneOf.yaml Added SMS_OTP branch to the oneOf list and discriminator mapping; correctly references SmsOtpCredentialCreateRequest.
openapi/components/schemas/auth/AuthCredentialResponseOneOf.yaml Added SMS_OTP → AuthMethodResponse mapping in the challenge-response discriminator; correctly reuses AuthMethodResponse just as EMAIL_OTP does.
openapi/components/schemas/auth/AuthMethodType.yaml SMS_OTP added to the enum and its description; all downstream schemas that reference this type inherit the new value correctly.
openapi/components/schemas/errors/Error400.yaml SMS_OTP_CREDENTIAL_ALREADY_EXISTS added to both the description table and the enum; description text is accurate and consistent with EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS.
openapi/paths/auth/auth_credentials.yaml POST and GET credential endpoints fully updated for SMS OTP: new request/response examples, updated 201/202/400 descriptions; GET list example omits SMS_OTP credential (P2).
openapi/paths/auth/auth_credentials_{id}_challenge.yaml Challenge endpoint descriptions updated to include SMS OTP; 200 response examples still missing an smsOtp entry (flagged in a previous review comment).
openapi/paths/auth/auth_credentials_{id}_verify.yaml Verify endpoint descriptions and request body examples updated for SMS OTP; 202 response missing smsOtp example and request body missing smsOtpSignedRetry example (P2).
openapi/components/schemas/auth/AuthMethodResponse.yaml Updated description now correctly covers both EMAIL_OTP and SMS_OTP; otpEncryptionTargetBundle documentation is accurate for both OTP types.
openapi/components/schemas/auth/AuthSession.yaml Updated encryptedSessionSigningKey description to correctly state that SMS_OTP sessions omit this field for the same reason as EMAIL_OTP (client holds TEK private key).

Sequence Diagram

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

    Note over Client,Grid: POST /auth/credentials (Add SMS OTP)
    Client->>Grid: "POST /auth/credentials {type: SMS_OTP, accountId}"
    Grid-->>Client: "202 AuthSignedRequestChallenge {payloadToSign, requestId}"
    Client->>Grid: POST /auth/credentials (signed retry + Grid-Wallet-Signature + Request-Id)
    Grid-->>Client: "201 AuthMethodResponse {type: SMS_OTP, nickname, otpEncryptionTargetBundle}"

    Note over Client,Grid: POST /auth/credentials/{id}/challenge (Re-issue OTP)
    Client->>Grid: "POST /auth/credentials/{id}/challenge (empty body)"
    Grid-->>Client: "200 AuthMethodResponse {type: SMS_OTP, otpEncryptionTargetBundle}"

    Note over Client,Grid: POST /auth/credentials/{id}/verify (Login)
    Client->>Client: "HPKE-encrypt {otp_code, TEK_public_key} to encryptedOtpBundle"
    Client->>Grid: "POST /auth/credentials/{id}/verify {type: SMS_OTP, encryptedOtpBundle}"
    Grid-->>Client: "202 AuthSignedRequestChallenge {type: SMS_OTP, payloadToSign, requestId}"
    Client->>Client: Sign verificationToken with TEK private key
    Client->>Grid: "POST /auth/credentials/{id}/verify (signed retry)"
    Grid-->>Client: "200 AuthSession {type: SMS_OTP, nickname, expiresAt}"
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: POST /auth/credentials (Add SMS OTP)
    Client->>Grid: "POST /auth/credentials {type: SMS_OTP, accountId}"
    Grid-->>Client: "202 AuthSignedRequestChallenge {payloadToSign, requestId}"
    Client->>Grid: POST /auth/credentials (signed retry + Grid-Wallet-Signature + Request-Id)
    Grid-->>Client: "201 AuthMethodResponse {type: SMS_OTP, nickname, otpEncryptionTargetBundle}"

    Note over Client,Grid: POST /auth/credentials/{id}/challenge (Re-issue OTP)
    Client->>Grid: "POST /auth/credentials/{id}/challenge (empty body)"
    Grid-->>Client: "200 AuthMethodResponse {type: SMS_OTP, otpEncryptionTargetBundle}"

    Note over Client,Grid: POST /auth/credentials/{id}/verify (Login)
    Client->>Client: "HPKE-encrypt {otp_code, TEK_public_key} to encryptedOtpBundle"
    Client->>Grid: "POST /auth/credentials/{id}/verify {type: SMS_OTP, encryptedOtpBundle}"
    Grid-->>Client: "202 AuthSignedRequestChallenge {type: SMS_OTP, payloadToSign, requestId}"
    Client->>Client: Sign verificationToken with TEK private key
    Client->>Grid: "POST /auth/credentials/{id}/verify (signed retry)"
    Grid-->>Client: "200 AuthSession {type: SMS_OTP, nickname, expiresAt}"
Loading

Reviews (3): 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
@DhruvPareek DhruvPareek marked this pull request as ready for review June 26, 2026 18:27
@DhruvPareek DhruvPareek merged commit 4cf5e27 into main Jun 26, 2026
11 checks passed
@DhruvPareek DhruvPareek deleted the dp/grid-sms-otp-openapi branch June 26, 2026 20: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.

2 participants