From e60b5d81dfbe6ffbe7099e38dd4d0d92f47a9d35 Mon Sep 17 00:00:00 2001 From: Dhruv Pareek Date: Fri, 17 Apr 2026 17:31:14 -0700 Subject: [PATCH] feat: add POST /auth/credentials/{id}/challenge to resend EMAIL_OTP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resend an authentication credential challenge without rebuilding the credential. For `EMAIL_OTP`, this re-issues the OTP email so the user can call `POST /auth/credentials/{id}/verify` again after the previous code expired or was missed. **Endpoint defined** - `POST /auth/credentials/{id}/challenge` — no request body; `{id}` is the `AuthMethod.id` returned from `POST /auth/credentials` (same path-param semantics as `/verify`). Returns `AuthMethod` (200). **Response shape** - Reuses `AuthMethod` from the parent PR — `id`, `accountId`, `type`, `nickname`, `createdAt`, `updatedAt`. No session fields; verification still happens on `/verify`. **Stainless** - `challenge` method added to the `auth.credentials` resource in `.stainless/stainless.yml`. **Bundled** - `openapi/openapi.yaml` registers the new path; `openapi.yaml` and `mintlify/openapi.yaml` regenerated via `make build`. --- .stainless/stainless.yml | 1 + mintlify/openapi.yaml | 88 +++++++++++++++++++ openapi.yaml | 88 +++++++++++++++++++ .../components/schemas/errors/Error429.yaml | 26 ++++++ openapi/openapi.yaml | 2 + .../auth/auth_credentials_{id}_challenge.yaml | 70 +++++++++++++++ 6 files changed, 275 insertions(+) create mode 100644 openapi/components/schemas/errors/Error429.yaml create mode 100644 openapi/paths/auth/auth_credentials_{id}_challenge.yaml diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index aea5328d..bb7df08b 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -327,6 +327,7 @@ resources: methods: create: post /auth/credentials verify: post /auth/credentials/{id}/verify + challenge: post /auth/credentials/{id}/challenge models: auth_method_type: '#/components/schemas/AuthMethodType' auth_method: '#/components/schemas/AuthMethod' diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 152feb67..29a960a4 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -3878,6 +3878,67 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /auth/credentials/{id}/challenge: + post: + summary: Resend an authentication credential challenge + description: | + Re-issue the challenge for an existing authentication credential. + + For `EMAIL_OTP` credentials, this triggers a new one-time password email to the address on file. After the user receives the new OTP, call `POST /auth/credentials/{id}/verify` to complete verification and issue a session. + operationId: challengeAuthCredential + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the authentication credential to re-challenge (the `id` field of the `AuthMethod` returned from `POST /auth/credentials`). + required: true + schema: + type: string + responses: + '200': + description: Challenge re-issued for the authentication credential + content: + application/json: + schema: + $ref: '#/components/schemas/AuthMethod' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Authentication credential not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '429': + description: Too many requests. Returned with `RATE_LIMITED` when challenge re-issues are requested more frequently than the OTP rate limit allows. Clients should back off and retry after the interval indicated by the `Retry-After` response header. + headers: + Retry-After: + description: Number of seconds to wait before retrying the request. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error429' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' webhooks: incoming-payment: post: @@ -13327,6 +13388,33 @@ components: format: date-time description: Timestamp after which the session signing key is no longer valid. example: '2026-04-08T15:35:00Z' + Error429: + type: object + required: + - message + - status + - code + properties: + status: + type: integer + enum: + - 429 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | + enum: + - RATE_LIMITED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true WebhookType: type: string enum: diff --git a/openapi.yaml b/openapi.yaml index 152feb67..29a960a4 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -3878,6 +3878,67 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /auth/credentials/{id}/challenge: + post: + summary: Resend an authentication credential challenge + description: | + Re-issue the challenge for an existing authentication credential. + + For `EMAIL_OTP` credentials, this triggers a new one-time password email to the address on file. After the user receives the new OTP, call `POST /auth/credentials/{id}/verify` to complete verification and issue a session. + operationId: challengeAuthCredential + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the authentication credential to re-challenge (the `id` field of the `AuthMethod` returned from `POST /auth/credentials`). + required: true + schema: + type: string + responses: + '200': + description: Challenge re-issued for the authentication credential + content: + application/json: + schema: + $ref: '#/components/schemas/AuthMethod' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Authentication credential not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '429': + description: Too many requests. Returned with `RATE_LIMITED` when challenge re-issues are requested more frequently than the OTP rate limit allows. Clients should back off and retry after the interval indicated by the `Retry-After` response header. + headers: + Retry-After: + description: Number of seconds to wait before retrying the request. + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error429' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' webhooks: incoming-payment: post: @@ -13327,6 +13388,33 @@ components: format: date-time description: Timestamp after which the session signing key is no longer valid. example: '2026-04-08T15:35:00Z' + Error429: + type: object + required: + - message + - status + - code + properties: + status: + type: integer + enum: + - 429 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | + enum: + - RATE_LIMITED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true WebhookType: type: string enum: diff --git a/openapi/components/schemas/errors/Error429.yaml b/openapi/components/schemas/errors/Error429.yaml new file mode 100644 index 00000000..4ec38627 --- /dev/null +++ b/openapi/components/schemas/errors/Error429.yaml @@ -0,0 +1,26 @@ +type: object +required: + - message + - status + - code +properties: + status: + type: integer + enum: + - 429 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | + enum: + - RATE_LIMITED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 452f3838..b9b812d6 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -180,6 +180,8 @@ paths: $ref: paths/auth/auth_credentials.yaml /auth/credentials/{id}/verify: $ref: paths/auth/auth_credentials_{id}_verify.yaml + /auth/credentials/{id}/challenge: + $ref: paths/auth/auth_credentials_{id}_challenge.yaml webhooks: incoming-payment: $ref: webhooks/incoming-payment.yaml diff --git a/openapi/paths/auth/auth_credentials_{id}_challenge.yaml b/openapi/paths/auth/auth_credentials_{id}_challenge.yaml new file mode 100644 index 00000000..8c46aad1 --- /dev/null +++ b/openapi/paths/auth/auth_credentials_{id}_challenge.yaml @@ -0,0 +1,70 @@ +post: + summary: Resend an authentication credential challenge + description: > + Re-issue the challenge for an existing authentication credential. + + + For `EMAIL_OTP` credentials, this triggers a new one-time password email to + the address on file. After the user receives the new OTP, call + `POST /auth/credentials/{id}/verify` to complete verification and issue a + session. + operationId: challengeAuthCredential + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: >- + The id of the authentication credential to re-challenge (the `id` field + of the `AuthMethod` returned from `POST /auth/credentials`). + required: true + schema: + type: string + responses: + '200': + description: Challenge re-issued for the authentication credential + content: + application/json: + schema: + $ref: ../../components/schemas/auth/AuthMethod.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Authentication credential not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '429': + description: >- + Too many requests. Returned with `RATE_LIMITED` when challenge + re-issues are requested more frequently than the OTP rate limit + allows. Clients should back off and retry after the interval + indicated by the `Retry-After` response header. + headers: + Retry-After: + description: Number of seconds to wait before retrying the request. + schema: + type: integer + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error429.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml