Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions openapi/SOURCE.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
"verification.json": {
"url": "https://docs.didit.me/openapi-25.json",
"sha256": "99198089e59db66a2eb3fa2a17c9475a2dafce62ee25ed8998eaf00fb2108406",
"fetched_at": "2026-11-09T06:51:54Z"
"fetched_at": "2026-11-09T19:33:11Z"
},
"account.json": {
"url": "https://docs.didit.me/openapi-auth.json",
"sha256": "ef403603543b119fed4300d08e15b8ec0a13de9fabdfdc02866f61f817d2a1f0",
"fetched_at": "2026-11-09T06:51:54Z"
"sha256": "403daf72045fdf90d14a86a8bb7eb75938454520b92441c7c294ed09acdff703",
"fetched_at": "2026-11-09T19:33:11Z"
},
"webhook-vectors.json": {
"generator": "product-automations scripts/server-sdks/make_vectors.py (seeded 2026-10-17)",
Expand All @@ -16,6 +16,6 @@
"authentication.json": {
"url": "https://docs.didit.me/openapi-authentication.json",
"sha256": "3987984647bfcaa4b5462c8d60cd3c53894bf7585a38109e0cc813292b2416fe",
"fetched_at": "2026-11-09T06:51:54Z"
"fetched_at": "2026-11-09T19:33:11Z"
}
}
51 changes: 49 additions & 2 deletions openapi/account.json
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@
"/programmatic/verify-email/": {
"post": {
"summary": "Verify Email and Issue Credentials",
"description": "Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`.",
"description": "Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`. An account that already has an authenticator app or a passkey gets the same second-factor step as the login instead: `2fa_required: true` and a `temp_token`, with no tokens and no application keys.",
"operationId": "programmatic_verify_email",
"x-didit-sdk": {
"resource": "account",
Expand Down Expand Up @@ -280,7 +280,7 @@
},
"responses": {
"200": {
"description": "Email verified. The response contains tokens for this auth API plus the brand-new application's `client_id` and `api_key`. Persist the `api_key` securely — it is the long-lived credential used by every verification API call.",
"description": "Email verified. The response contains tokens for this auth API plus the brand-new application's `client_id` and `api_key`. Persist the `api_key` securely — it is the long-lived credential used by every verification API call. When the account already has an authenticator app or a passkey, the response carries `2fa_required: true`, a `temp_token`, `has_authenticator` and `has_passkeys` instead of tokens and application keys: finish the sign-in with the second factor, then read the organization and its applications from `/organizations/me/`.",
"content": {
"application/json": {
"schema": {
Expand All @@ -304,6 +304,15 @@
"data_location": "eu"
}
}
},
"SecondFactorRequired": {
"summary": "The account already has an authenticator app or a passkey",
"value": {
"2fa_required": true,
"temp_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"has_passkeys": false,
"has_authenticator": true
}
}
}
}
Expand Down Expand Up @@ -360,6 +369,27 @@
}
}
},
"403": {
"description": "The account was recovered and must set up a new sign-in method first. No tokens are issued; a link to do that was emailed to the account's address.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RecoverySetupRequiredError"
},
"examples": {
"RecoverySetupRequired": {
"summary": "Recovered account with no sign-in method yet",
"value": {
"recovery_setup_required": true,
"setup_link_sent": true,
"message": "You recovered your account. Open the link we emailed you to set up a new sign-in method.",
"code": "recovery_setup_required"
}
}
}
}
}
},
"429": {
"description": "The service is momentarily checking as many passwords or codes as it can at once. Sent with a `Retry-After: 5` header; retry after the indicated number of seconds.",
"content": {
Expand Down Expand Up @@ -2160,6 +2190,23 @@
},
"application": {
"$ref": "#/components/schemas/ApplicationCredentialsSummary"
},
"2fa_required": {
"type": "boolean",
"description": "Present and `true` when the account already has an authenticator app or a passkey. The response then carries `temp_token` instead of tokens and application keys.",
"example": true
},
"temp_token": {
"type": "string",
"description": "Short-lived token for the second-factor step, sent only with `2fa_required`. It is not an access token."
},
"has_authenticator": {
"type": "boolean",
"description": "With `2fa_required`: whether the account has an authenticator app."
},
"has_passkeys": {
"type": "boolean",
"description": "With `2fa_required`: whether the account has a passkey."
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions src/didit/resources/account/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def verify_email(
) -> VerifyEmailResponse:
"""Verify Email and Issue Credentials.

Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`.
Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`. An account that already has an authenticator app or a passkey gets the same second-factor step as the login instead: `2fa_required: true` and a `temp_token`, with no tokens and no application keys.

``POST /programmatic/verify-email/``

Expand Down Expand Up @@ -324,7 +324,7 @@ async def verify_email(
) -> VerifyEmailResponse:
"""Verify Email and Issue Credentials.

Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`.
Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`. An account that already has an authenticator app or a passkey gets the same second-factor step as the login instead: `2fa_required: true` and a `temp_token`, with no tokens and no application keys.

``POST /programmatic/verify-email/``

Expand Down
14 changes: 14 additions & 0 deletions src/didit/types/components/verify_email_response.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Code generated by codegen from openapi/*.json. DO NOT EDIT.
from __future__ import annotations

from pydantic import Field

from didit._models import BaseModel
from didit.types.components.application_credentials_summary import ApplicationCredentialsSummary
from didit.types.components.organization_summary import OrganizationSummary
Expand All @@ -23,3 +25,15 @@ class VerifyEmailResponse(BaseModel):

application: ApplicationCredentialsSummary | None = None
"""Minimal application shape returned inline by `POST /programmatic/verify-email/`. Persist the `api_key` immediately."""

v_2fa_required: bool | None = Field(default=None, alias="2fa_required")
"""Present and `true` when the account already has an authenticator app or a passkey. The response then carries `temp_token` instead of tokens and application keys."""

temp_token: str | None = None
"""Short-lived token for the second-factor step, sent only with `2fa_required`. It is not an access token."""

has_authenticator: bool | None = None
"""With `2fa_required`: whether the account has an authenticator app."""

has_passkeys: bool | None = None
"""With `2fa_required`: whether the account has a passkey."""
Loading