Skip to main content

Account settings by Account API

What is Logto Account API​

The Logto Account API is a comprehensive set of APIs that gives end users direct API access without needing to go through the Management API. Here are the highlights:

  • Direct access: The Account API empowers end users to directly access and manage their own account profiles without requiring the relay of Management API.
  • User profile and identities management: Users can fully manage their profiles and security settings, including the ability to update identity information like email, phone, and password, as well as manage social connections. MFA and SSO support are coming soon.
  • Global access control: Admins have full, global control over access settings and can customize each field.
  • Seamless authorization: Authorization is easier than ever! Simply use client.getAccessToken() to obtain an opaque access token for OP (Logto), and attach it to the Authorization header as Bearer <access_token>.

With the Logto Account API, you can build a custom account management system like a profile page that is fully integrated with Logto.

Some frequent use cases are listed below:

  • Retrieve user profile
  • Update user profile
  • Update user password
  • Update user identities including email, phone, and social connections
  • Manage MFA factors (verifications)
  • Manage user sessions
  • Manage user authorized apps (grants)

To learn more about the available APIs, please visit Logto Account API Reference and Logto Verification API Reference.

note:

SSO account viewing and account deletion features are currently available through the Logto Management APIs. See Account settings by Management API for implementation details.

How to enable Account API​

Navigate to Console > Sign-in & account > Account center.

The Account API is off by default, so its access controls are locked. Toggle Enable Account API to switch it on.

Once enabled, configure the Recent authentication window (from 1 to 120 minutes; 10 minutes by default) and per-field permissions for identifiers, profile data, and third-party token access. Each field supports Off, ReadOnly, or Edit; the default is Off.

  1. Security fields:
    • Fields include: primary email, primary phone, social identities, password, passkeys, MFA, and personal access tokens.
    • Sensitive operations require recent user authentication from a first-party application—an access token whose acr satisfies urn:logto:acr:1fa within the configured recent authentication window (see OIDC step-up authentication).
    • To use WebAuthn passkeys for MFA, add your front-end app domains to WebAuthn Related Origins so the account center and sign-in experience can share passkeys. See Link a new WebAuthn passkey.
  2. Profile fields:
    • Fields include: username, name, avatar, profile (other standard profile attributes), and custom data.
    • End users can edit these without additional verification, except username, which also requires recent user authentication.
  3. Secret vault:
    • For OIDC or OAuth social and enterprise connectors, Logto secret vault securely stores third-party access and refresh tokens after authentication. Apps can then call external APIs, such as syncing Google Calendar events, without prompting users to sign in again. Token retrieval becomes available automatically once the Account API is enabled.
  4. Session management:
    • When enabled, users can view and manage their active sessions, including device information and last sign-in time. Users can also revoke sessions to log out from specific devices.
    • This same Sessions field permission also controls user authorized apps (grants) APIs (view and revoke grants).
    • Accessing session and grant management requires the same recent user authentication as security fields.

How to access Account API​

note:

To ensure the access token has the appropriate permissions, make sure you have properly configured the corresponding scopes in your Logto config.

For example, for the POST /api/my-account/primary-email API, you need to configure the email scope; for the POST /api/my-account/primary-phone API, you need to configure the phone scope.

import { type LogtoConfig, UserScope } from '@logto/js';

const config: LogtoConfig = {
// ...other options
// Add proper scopes that fit your use cases.
scopes: [
UserScope.Email, // For `{POST,DELETE} /api/my-account/primary-email` APIs
UserScope.Phone, // For `{POST,DELETE} /api/my-account/primary-phone` APIs
UserScope.CustomData, // To manage custom data
UserScope.Address, // To manage address
UserScope.Identities, // For identity and MFA related APIs
UserScope.Profile, // To manage user profile
UserScope.Sessions, // To manage user sessions and app grants
],
};

Fetch an access token​

After setting up the SDK in your application, you can use the client.getAccessToken() method to fetch an access token. This token is an opaque token that can be used to access the Account API.

If you are not using the official SDK, you should set the resource to empty for the access token grant request to /oidc/token.

Access Account API using access token​

You should include the access token in the Authorization field of HTTP headers with the Bearer format (Bearer YOUR_TOKEN) when interacting with the Account API.

Here's an example to get the user account information:

curl https://[tenant-id].logto.app/api/my-account \
-H 'authorization: Bearer <access_token>'

Manage basic account information​

Retrieve user account information​

To get user data, you can use the GET /api/my-account endpoint.

curl https://[tenant-id].logto.app/api/my-account \
-H 'authorization: Bearer <access_token>'

The response body would be like:

{
"id": "...",
"username": "...",
"name": "...",
"avatar": "..."
}

The response fields may vary depending on the account center settings.

Update basic account information​

Basic account information includes the username, name, avatar, custom data, and other profile information.

To update username, name, avatar, and customData you can use the PATCH /api/my-account endpoint.

curl -X PATCH https://[tenant-id].logto.app/api/my-account \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"username":"...","name":"...","avatar":"..."}'

To update other profile information, including familyName, givenName, middleName, nickname, profile (profile page URL), website, gender, birthdate, zoneinfo, locale, and address, you can use the PATCH /api/my-account/profile endpoint.

curl -X PATCH https://[tenant-id].logto.app/api/my-account/profile \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"familyName":"...","givenName":"..."}'

Manage identifiers and other sensitive information​

For security reasons, sensitive Account API operations require recent user authentication from a first-party application: the access token must carry acr satisfying urn:logto:acr:1fa and an auth_time within your tenant's Recent authentication window (600 seconds / 10 minutes by default, configurable from 60 to 7,200 seconds).

When the access token lacks urn:logto:acr:1fa or has aged past the window, Account API returns 401 Unauthorized with an RFC 9470 WWW-Authenticate header (error="insufficient_user_authentication", acr_values="urn:logto:acr:1fa", max_age="<window>"). Start an OIDC step-up authentication request with those parameters and retry the call with the newly issued access token.

note:

Binding a new email address, phone number, social identity, or WebAuthn passkey also requires proving ownership of that new identifier or factor through the Verification API and passing newIdentifierVerificationRecordId in the request body, as shown in each section below.

Update user's password​

To update the user's password, you can use the POST /api/my-account/password endpoint.

curl -X POST https://[tenant-id].logto.app/api/my-account/password \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"password":"..."}'
tip:

Just like passwords created during sign-up, passwords set through the Account API must comply with the password policy you configured in Console > Security > Password policy. Logto returns detailed validation results and error messages if the password fails the policy.

note:

To use this method, you need to configure the email connector, and make sure the BindNewIdentifier template is configured.

To update or link a new email, you should first prove the ownership of the email.

Call the POST /api/verifications/verification-code endpoint to request a verification code.

curl -X POST https://[tenant-id].logto.app/api/verifications/verification-code \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"identifier":{"type":"email","value":"..."}}'

You will find a verificationId in the response, and receive a verification code in the email, use it to verify the email.

curl -X POST https://[tenant-id].logto.app/api/verifications/verification-code/verify \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"identifier":{"type":"email","value":"..."},"verificationId":"...","code":"..."}'

After verifying the code, you can now call PATCH /api/my-account/primary-email to update the user's email, set the verificationId to the request body as newIdentifierVerificationRecordId.

curl -X POST https://[tenant-id].logto.app/api/my-account/primary-email \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"email":"...","newIdentifierVerificationRecordId":"<verification_record_id_from_new_email>"}'
tip:

Just like emails collected during sign-up, any email linked through the Account API must pass the blocklist verification you configured in Console > Security > Blocklist. Logto will reject the request and return a detailed error if the email violates the policy.

Remove the user's email​

To remove the user's email, you can use the DELETE /api/my-account/primary-email endpoint.

curl -X DELETE https://[tenant-id].logto.app/api/my-account/primary-email \
-H 'authorization: Bearer <access_token>'

Manage phone​

note:

To use this method, you need to configure the SMS connector, and make sure the BindNewIdentifier template is configured.

Similar to updating email, you can use the PATCH /api/my-account/primary-phone endpoint to update or link a new phone. And use the DELETE /api/my-account/primary-phone endpoint to remove the user's phone.

To link a new social connection, first you should request an authorization URL with POST /api/verifications/social.

curl -X POST https://[tenant-id].logto.app/api/verifications/social \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"connectorId":"...","redirectUri":"...","state":"..."}'
  • connectorId: The ID of the social connector.
  • redirectUri: The redirect URI after the user authorizes the application, you should host a web page at this URL and capture the callback.
  • state: The state to be returned after the user authorizes the application, it is a random string that is used to prevent CSRF attacks.

In the response, you will find a verificationRecordId, keep it for later use.

After the user authorizes the application, you will receive a callback at the redirectUri with the state parameter. Then you can use the POST /api/verifications/social/verify endpoint to verify the social connection.

curl -X POST https://[tenant-id].logto.app/api/verifications/social/verify \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"connectorData":"...","verificationRecordId":"..."}'

The connectorData is the data returned by the social connector after the user authorizes the application, you need to parse and get the query parameters from the redirectUri in your callback page, and wrap them as a JSON as the value of the connectorData field.

Finally, you can use the POST /api/my-account/identities endpoint to link the social connection.

curl -X POST https://[tenant-id].logto.app/api/my-account/identities \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"newIdentifierVerificationRecordId":"<verification_record_id_from_social>"}'

Remove a social connection​

To remove a social connection, you can use the DELETE /api/my-account/identities endpoint.

curl -X DELETE https://[tenant-id].logto.app/api/my-account/identities/[connector_target_id] \
-H 'authorization: Bearer <access_token>'
note:

Remember to enable MFA and WebAuthn first.

note:

To use this method, you need to enable the mfa field in the account center settings.

Step 1: Add your front-end app origin to the related origins

WebAuthn passkeys are bound to a specific hostname called the Relying Party ID (RP ID). Only applications hosted on the RP ID's origin can register or authenticate with those passkeys.

Since your front-end application calls the Account API from a different domain than Logto's authentication pages, you need to configure Related Origins to allow cross-origin passkey operations.

How Logto determines the RP ID:

  • Default setup: If you only use Logto's default domain https://[tenant-id].logto.app, the RP ID is [tenant-id].logto.app
  • Custom domain: If you've configured a custom domain like https://auth.example.com, the RP ID becomes auth.example.com

Configure Related Origins:

Use the PATCH /api/account-center endpoint to add your front-end application's origin. For example, if your app's account center runs on https://account.example.com:

curl -X PATCH https://[tenant-id].logto.app/api/account-center \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"webauthnRelatedOrigins":["https://account.example.com"]}'
note:

WebAuthn supports up to 5 unique eTLD+1 labels for Related Origins. The eTLD+1 (effective top-level domain plus one label) is the registrable domain portion. For example:

  • https://example.com, https://app.example.com, and https://auth.example.com count as one label (example.com)
  • https://shopping.com, https://shopping.co.uk, and https://shopping.co.jp also count as one label (shopping)
  • https://example.com and https://another.com count as two labels

If you need to support more than 5 different domains as the Related Origins, refer to the Related Origin Requests documentation for details.

Step 2: Request new registration options

Use the POST /api/verifications/web-authn/registration endpoint to request registration for a new passkey. Logto allows each user account to register multiple passkeys.

curl -X POST https://[tenant-id].logto.app/api/verifications/web-authn/registration \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

You'll get a response like:

{
"registrationOptions": "...",
"verificationRecordId": "...",
"expiresAt": "..."
}

Step 3: Register the passkey in local browser

Take @simplewebauthn/browser as an example, you can use the startRegistration function to register the passkey in local browser.

import { startRegistration } from '@simplewebauthn/browser';

// ...
const response = await startRegistration({
optionsJSON: registrationOptions, // The data returned by the server in step 1
});
// Save the response for later use

Step 4: Verify the passkey registration

Use the POST /api/verifications/web-authn/registration/verify endpoint to verify the passkey registration.

This step verifies the cryptographic signature generated by the authenticator to ensure the passkey was legitimately created and hasn't been tampered with during transmission.

curl -X POST https://[tenant-id].logto.app/api/verifications/web-authn/registration/verify \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"payload":"...","verificationRecordId":"..."}'
  • payload: The response from the local browser in step 2.
  • verificationRecordId: The verification record ID returned by the server in step 1.

Step 5: Link the passkey

Finally, you can link the passkey to the user's account using the POST /api/my-account/mfa-verifications endpoint.

curl -X POST https://[tenant-id].logto.app/api/my-account/mfa-verifications \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"type":"WebAuthn","newIdentifierVerificationRecordId":"..."}'
  • type: the type of the MFA factor, currently only WebAuthn is supported.
  • newIdentifierVerificationRecordId: the verification record ID returned by the server in step 1.

Manage existing WebAuthn passkeys​

To manage existing WebAuthn passkeys, you can use the GET /api/my-account/mfa-verifications endpoint to get current passkeys and other MFA verification factors.

curl https://[tenant-id].logto.app/api/my-account/mfa-verifications \
-H 'authorization: Bearer <access_token>'

The response body would be like:

[
{
"id": "...",
"type": "WebAuthn",
"name": "...",
"agent": "...",
"createdAt": "...",
"updatedAt": "..."
}
]
  • id: the ID of the verification.
  • type: the type of the verification, WebAuthn for WebAuthn passkey.
  • name: the name of the passkey, optional field.
  • agent: the user agent of the passkey.

Update the passkey name using PATCH /api/my-account/mfa-verifications/{verificationId}/name endpoint:

curl -X PATCH https://[tenant-id].logto.app/api/my-account/mfa-verifications/{verificationId}/name \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"name":"..."}'

Delete the passkey using DELETE /api/my-account/mfa-verifications/{verificationId} endpoint:

curl -X DELETE https://[tenant-id].logto.app/api/my-account/mfa-verifications/{verificationId} \
-H 'authorization: Bearer <access_token>'
note:

Remember to enable MFA and TOTP first.

note:

To use this method, you need to enable the mfa field in the account center settings.

Step 1: Generate a TOTP secret

Use the POST /api/my-account/mfa-verifications/totp-secret/generate endpoint to generate a TOTP secret.

curl -X POST https://[tenant-id].logto.app/api/my-account/mfa-verifications/totp-secret/generate \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

The response body would be like:

{
"secret": "..."
}

Step 2: Display the TOTP secret to the user

Use the secret to generate a QR code or display it directly to the user. The user should add it to their authenticator app (such as Google Authenticator, Microsoft Authenticator, or Authy).

The URI format for the QR code should be:

otpauth://totp/[Issuer]:[Account]?secret=[Secret]&issuer=[Issuer]

Example:

otpauth://totp/YourApp:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=YourApp

Step 3: Bind the TOTP factor

After the user has added the secret to their authenticator app, they need to verify it and bind it to their account. Use the POST /api/my-account/mfa-verifications endpoint to bind the TOTP factor.

curl -X POST https://[tenant-id].logto.app/api/my-account/mfa-verifications \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"type":"Totp","secret":"..."}'
  • type: must be Totp.
  • secret: the TOTP secret generated in step 1.
note:

A user can only have one TOTP factor at a time. If the user already has a TOTP factor, attempting to add another one will result in a 422 error.

Replace an existing TOTP​

If the user already has a TOTP factor configured, you can replace it with a new one using the PUT /api/my-account/mfa-verifications/totp endpoint. This is an idempotent operation that removes the existing TOTP and binds a new one.

note:

To use this method, you need to enable the mfa field in the account center settings.

Step 1: Generate a new TOTP secret

Use the POST /api/my-account/mfa-verifications/totp-secret/generate endpoint to generate a new TOTP secret, then display it to the user as described in Link a new TOTP.

Step 2: Replace the TOTP factor

curl -X PUT https://[tenant-id].logto.app/api/my-account/mfa-verifications/totp \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"secret":"...","code":"..."}'
  • secret: the new TOTP secret generated in step 1.
  • code: the TOTP code generated from the new secret to confirm the binding.

Manage backup codes​

note:

Remember to enable MFA and backup codes first.

note:

To use this method, you need to enable the mfa field in the account center settings.

Step 1: Generate new backup codes

Use the POST /api/my-account/mfa-verifications/backup-codes/generate endpoint to generate a new set of 10 backup codes.

curl -X POST https://[tenant-id].logto.app/api/my-account/mfa-verifications/backup-codes/generate \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

The response body would be like:

{
"codes": ["...", "...", "..."]
}

Step 2: Display backup codes to the user

Before binding the backup codes to the user's account, you must display them to the user and instruct them to:

  • Download or write down these codes immediately
  • Store them in a secure location
  • Understand that each code can only be used once
  • Know that these codes are their last resort if they lose access to their primary MFA methods

You should display the codes in a clear, easy-to-copy format and consider providing a download option (e.g., as a text file or PDF).

Step 3: Bind backup codes to the user account

Use the POST /api/my-account/mfa-verifications endpoint to bind the backup codes to the user's account.

curl -X POST https://[tenant-id].logto.app/api/my-account/mfa-verifications \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"type":"BackupCode","codes":["...","...","..."]}'
  • type: must be BackupCode.
  • codes: the array of backup codes generated in the previous step.
note:
  • A user can only have one set of backup codes at a time. If all codes have been used, the user needs to generate and bind new codes.
  • Backup codes cannot be the only MFA factor. The user must have at least one other MFA factor (such as WebAuthn or TOTP) enabled.
  • Each backup code can only be used once.

View existing backup codes

To view existing backup codes and their usage status, use the GET /api/my-account/mfa-verifications/backup-codes endpoint:

curl https://[tenant-id].logto.app/api/my-account/mfa-verifications/backup-codes \
-H 'authorization: Bearer <access_token>'

The response body would be like:

{
"codes": [
{
"code": "...",
"usedAt": null
},
{
"code": "...",
"usedAt": "2024-01-15T10:30:00.000Z"
}
]
}
  • code: the backup code.
  • usedAt: the timestamp when the code was used, null if not used yet.

Manage 2-step verification settings​

note:

To use these methods, you need to enable the mfa field in the account center settings.

End users can toggle 2-step verification on or off for their account. A common use case is when a user has configured MFA factors (such as passkeys) but only wants to use them for sign-in rather than as an additional verification step — disabling 2-step verification allows them to skip the MFA prompt during sign-in while keeping their MFA factors intact. This is controlled by the skipMfaOnSignIn setting per user.

Get current MFA settings

Use the GET /api/my-account/mfa-settings endpoint to retrieve the user's current 2-step verification settings.

curl https://[tenant-id].logto.app/api/my-account/mfa-settings \
-H 'authorization: Bearer <access_token>'

The response body would be like:

{
"skipMfaOnSignIn": false
}

Update MFA settings

To enable or disable 2-step verification, use the PATCH /api/my-account/mfa-settings endpoint.

curl -X PATCH https://[tenant-id].logto.app/api/my-account/mfa-settings \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json' \
--data-raw '{"skipMfaOnSignIn":true}'
  • skipMfaOnSignIn: set to true to disable 2-step verification for the user, or false to enable it.
note:

This setting only takes effect when the MFA policy is set to Optional. If MFA is Mandatory or Adaptive, the skipMfaOnSignIn setting will be ignored and MFA will be enforced.

Manage user sessions​

List active sessions

To list the user's active sessions, you can use the GET /api/my-account/sessions endpoint.

note:
  • UserScope.Sessions scope is required to access this endpoint.
  • Sessions field in account center settings must be set to ReadOnly or Edit.
curl https://[tenant-id].logto.app/api/my-account/sessions \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

Revoke session by session ID

To revoke a specific session, use the DELETE /api/my-account/sessions/{sessionId} endpoint.

note:
  • UserScope.Sessions scope is required to access this endpoint.
  • Sessions field in account center settings must be set to Edit.
curl -X DELETE https://[tenant-id].logto.app/api/my-account/sessions/{sessionId} \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

Optional query parameters:

  • revokeGrantsTarget: Optionally specify the target of the grants to revoke along with the session. Possible values:
    • all: Revoke all grants associated with the session.
    • firstParty: Revoke only first-party app grants associated with the session. (Recommended for most use cases, as it revokes access for your own app while keeping third-party app grants intact, providing a better user experience.)
    • unspecified: Default behavior revokes grants that does not have offline_access scope, which typically means revoking non-refresh-token grants for the session.

Manage user authorized apps (grants)​

Use user authorized apps (grants) APIs when users need to review and revoke authorized apps from their account settings page.

note:
  • App grant APIs share the same permission model as session APIs.
  • UserScope.Sessions scope is required.
  • Sessions field in account center settings must be enabled:
    • ReadOnly or Edit to list grants.
    • Edit to revoke grants.

List active app grants

To list active app grants of the current user, use the GET /api/my-account/grants endpoint.

curl https://[tenant-id].logto.app/api/my-account/grants \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

Optional query parameter:

  • appType=firstParty: Return first-party app grants only.
  • appType=thirdParty: Return third-party app grants only.
  • Omit appType: Return all active grants.
curl "https://[tenant-id].logto.app/api/my-account/grants?appType=thirdParty" \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

Revoke app grant by grant ID

To revoke a specific app grant, use the DELETE /api/my-account/grants/{grantId} endpoint.

curl -X DELETE https://[tenant-id].logto.app/api/my-account/grants/{grantId} \
-H 'authorization: Bearer <access_token>' \
-H 'content-type: application/json'

When a grant is revoked, previously issued opaque access tokens and refresh tokens for that grant are invalidated.