> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-docs-event-stream-action-templates.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Learn how you can empower your users to manage their own account information with the My Account API.

# My Account API

export const ReleaseStageNotice = ({feature, stage, plans, contact, terms}) => {
  const stageTextMap = {
    "beta": "Beta",
    "ea": "Early Access"
  };
  const stageText = stageTextMap[stage] || "a product release stage";
  const prsLink = "/docs/troubleshoot/product-lifecycle/product-release-stages";
  const linkify = (text, url) => {
    return <a href={url} target="_blank" rel="noreferrer" class="link">{text}</a>;
  };
  const includeDetails = (plans, contact, terms) => {
    const hasDetails = terms || plans || contact;
    if (!hasDetails) return null;
    return <span data-as="p">
            {plans && <>This feature is available for {linkify(`${plans} plans`, "https://auth0.com/pricing")}. </>}
            {contact && "To participate, contact " + contact + ". "}
            {terms && <>By using this feature, you agree to the applicable Free Trial terms in Okta's {linkify("Master Subscription Agreement", "https://www.okta.com/legal")}.</>}
        </span>;
  };
  return <Warning>
            <span data-as="p">
                <strong>The {feature} feature is in {linkify(stageText, prsLink)}.</strong>
            </span>

            {includeDetails(plans, contact, terms)}
        </Warning>;
};

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

The Auth0 My Account API provides a dedicated set of endpoints for users to manage their own account information. Customers can use these APIs to build self-service experiences in their applications or progressively add details to a user account.

The My Account API operates within the context of the currently logged-in user, and you can use it directly within user-facing applications.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  **Using Auth0 domain vs. custom domain**

  The My Account API supports using your canonical Auth0 domain or your custom domain, but you must use the same one throughout the entire process, including:

  * Getting an access token
  * Setting the `audience` value
  * Calling the My Account API endpoint

  For more information, read [Custom Domains](/docs/customize/custom-domains).
</Callout>

## Activate the My Account API

You can activate the My Account API for your tenant in the <Tooltip tip="Auth0 Dashboard: Auth0's main product to configure your services." cta="View Glossary" href="/docs/glossary?term=Auth0+Dashboard">Auth0 Dashboard</Tooltip>:

1. Navigate to **Applications > APIs**.
2. Locate the **MyAccount API** banner.
3. Select **Activate**.

<Frame>
  <img src="https://mintcdn.com/docs-dev-docs-event-stream-action-templates/RjB12i6aOVmBONJv/docs/images/cdy7uua7fh8z/DGkDQNIHcegN8vtQyEvF3/a2e98b06867701a66fa1f1b3df1c996b/My_Account_API_-_Activate.png?fit=max&auto=format&n=RjB12i6aOVmBONJv&q=85&s=2eb214f20ebe209741c9048452647264" alt="Auth0 Dashboard APIs page showing the MyAccount API banner with the Activate button" width="1139" height="406" data-path="docs/images/cdy7uua7fh8z/DGkDQNIHcegN8vtQyEvF3/a2e98b06867701a66fa1f1b3df1c996b/My_Account_API_-_Activate.png" />
</Frame>

By default, Auth0 creates the My Account API with the following application API access policies:

* `require_client_grant` for user flows
* `deny_all` for client (machine-to-machine) flows

For an application to access the My Account API on the user's behalf, you must explicitly create a client grant for that application, which allows you to define the maximum scopes the application can request. Alternatively, you can change the policy for user access flows to `allow_all`, which allows any application in your tenant to request any scope from the My Account API.

Auth0 does not recommend using `allow_all` for user access flows because the My Account API exposes sensitive information and operations. You should follow a least privilege principle with My Account API to ensure applications only get access to what they truly need, minimizing potential security risks.

Auth0 determines the final permissions granted to the application by intersecting the scopes allowed by the application API access policy, the Role-Based Access Control (RBAC) permissions assigned to the end user, and any user consent given (if applicable).

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  You cannot update the application API policy for client access to the My Account API, which means you cannot access the My Account API using the Client Credentials Flow.
</Callout>

To learn more about how to manage application API access policies and their associated client grants, read [Application Access to APIs: Client Grants](/docs/get-started/applications/application-access-to-apis-client-grants).

## Default Policy

<ReleaseStageNotice feature="Authentication Assurance for the My Account API" stage="ea" terms="true" contact="Auth0 Support" />

The Default Policy provides built-in authentication assurance for the My Account API by requiring [Step-up Authentication](/docs/secure/multi-factor-authentication/step-up-authentication). When enabled, Auth0 automatically enforces that users have authenticated recently and with a second factor.

The policy enforces 2FA within 15 minutes. Auth0 applies this rule at login and on every Refresh Token exchange:

* If a user has an enrolled MFA factor, 2FA must be completed at login and again when their tokens are older than 15 minutes.
* If a user has no enrollable factor, Auth0 allows initial access but returns an `unmet_authentication_requirements` error on refresh token exchanges after 15 minutes.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  The Default Policy is not compatible with Classic Login. Enable this feature if your tenant uses Universal Login or a supported embedded flow ([Resource Owner Password Flow](/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow) or [native passkeys](/docs/authenticate/database-connections/passkeys/native-passkeys-api)).
</Callout>

### Enable Default Policy

To enable the Default Policy for the My Account API:

1. Navigate to [**Applications > APIs**](https://manage.auth0.com/#/apis), then select the **My Account API**.
2. Select the **Settings** tab.
3. Under **Default Policy**, toggle on **Require 2FA**.
4. Select **Save**.

When your tenant has the Default Policy enabled, Auth0 automatically attaches it whenever it creates a new My Account API.

### Authentication requirements hierarchy

The Default Policy sits between the tenant-level MFA policy and any MFA logic you define in Actions:

1. **Tenant MFA policy**: The base default applied across all authentication on your tenant
2. **Default Policy**: Overrides the tenant-level specifically for the My Account API
3. **Actions**: Any MFA commands in Actions always take precedence over both

### Default Policy behavior

The behavior depends on whether the user has an enrollable second factor.

**Users with an enrolled MFA factor**

For users enrolled with TOTP, email, or another supported factor:

1. At login, Auth0 challenges the user with their enrolled factor before issuing tokens.
2. The refresh token records the authentication method and timestamp (AMR).
3. On refresh token exchange within 15 minutes of the last challenge, Auth0 issues a new access token without re-challenging.
4. On refresh token exchange after 15 minutes, Auth0 challenges the user again before issuing tokens.

**Users without an enrolled MFA factor**

For users with no verified email and no enrolled factor:

1. At login, Auth0 allows access without a second factor.
2. On refresh token exchange within 15 minutes, Auth0 issues a new access token without challenge.
3. On refresh token exchange after 15 minutes, Auth0 returns an `unmet_authentication_requirements` error.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  When Auth0 returns `unmet_authentication_requirements` on a refresh token exchange, you cannot refresh the token. Your application must restart the full authentication flow to obtain new tokens.

  A silent login (`prompt=none`) returns the same error when the user cannot satisfy the policy after 15 minutes.
</Callout>

## Get an access token

You can get an <Tooltip tip="Access Token: Authorization credential, in the form of an opaque string or JWT, used to access an API." cta="View Glossary" href="/docs/glossary?term=access+token">access token</Tooltip> for the My Account API in the same way you’d get an access token for one of your own APIs.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  If you need authentication assurance beyond the Default Policy — for example, to require a specific factor or to apply requirements to only certain operations — you can use [step-up authentication](/docs/secure/multi-factor-authentication/step-up-authentication) with [Actions](/docs/customize/actions) to define custom MFA logic. Note that Actions always override the Default Policy.
</Callout>

If you’re using <Tooltip tip="Universal Login: Your application redirects to Universal Login, hosted on Auth0's Authorization Server, to verify a user's identity." cta="View Glossary" href="/docs/glossary?term=Universal+Login">Universal Login</Tooltip>, read the following articles:

* [Call Your API Using the Authorization Code Flow](/docs/get-started/authentication-and-authorization-flow/authorization-code-flow/call-your-api-using-the-authorization-code-flow)
* [Call Your API Using the Authorization Code Flow with PKCE](/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce/call-your-api-using-the-authorization-code-flow-with-pkce)

If you’re using embedded login, read the following articles:

* [Call Your API Using Resource Owner Password Flow](/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow/call-your-api-using-resource-owner-password-flow)
* [Login Flow with Native Passkeys API](/docs/authenticate/database-connections/passkeys/native-passkeys-api#login-flow)

### Audience

The <Tooltip tip="Audience: Unique identifier of the audience for an issued token. Named aud in a token, its value contains the ID of either an application (Client ID) for an ID Token or an API (API Identifier) for an Access Token." cta="View Glossary" href="/docs/glossary?term=audience">audience</Tooltip> of the My Account API is `https://{yourDomain}/me/`.

### Scope

The My Account API supports the following scopes:

| Scope                              | Description                                                |
| ---------------------------------- | ---------------------------------------------------------- |
| `create:me:authentication_methods` | Allows the user to enroll a new authentication method.     |
| `read:me:authentication_methods`   | Allows the user to view existing authentication methods.   |
| `update:me:authentication_methods` | Allows the user to modify existing authentication methods. |
| `delete:me:authentication_methods` | Allows the user to delete existing authentication methods. |
| `read:me:factors`                  | Allows the user to view the factors they can enroll.       |

For [Connected Accounts with Token Vault](/docs/secure/call-apis-on-users-behalf/token-vault/connected-accounts-for-token-vault), the My Account API supports the following scopes:

| Scope                          | Description                                                                           |
| ------------------------------ | ------------------------------------------------------------------------------------- |
| `create:me:connected_accounts` | Allows the user to connect a new account to their user profile.                       |
| `read:me:connected_accounts`   | Allows the user to view the existing connected accounts linked to their user profile. |
| `delete:me:connected_accounts` | Allows the user to delete a connected account from their user profile.                |

### Access token examples

#### Universal Login with Authorization Code Flow

Retrieving access tokens with [Auth0's Universal Login](/docs/authenticate/login/auth0-universal-login#auth0-universal-login) is a two-step process: request an authorization code and exchange the code for an access token. To learn more about this grant type, read [Authorization Code Flow](/docs/get-started/authentication-and-authorization-flow/authorization-code-flow).

First, make an API call to the `/authorize` endpoint to request an authorization code:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F");
  var request = new RestRequest(Method.GET);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F"

  	req, _ := http.NewRequest("GET", url, nil)

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.get("https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F")
    .asString();
  ```

  ```javascript Node.js theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'GET',
    url: 'https://{yourDomain}/authorize',
    params: {
      response_type: 'code',
      client_id: '{yourClientId}',
      redirect_uri: '{yourRedirectUri}',
      scope: 'create:me:authentication_methods',
      offline_access: '',
      audience: 'https://{yourDomain}/me/'
    }
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  conn.request("GET", "/{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F")

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Get.new(url)

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Next, exchange the code for an access token:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --header 'content-type: application/json' \
    --data '{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/oauth/token"

  	payload := strings.NewReader("{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}")

  	req, _ := http.NewRequest("POST", url, payload)

  	req.Header.Add("content-type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/json")
    .body("{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}")
    .asString();
  ```

  ```javascript Node.js theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    headers: {'content-type': 'application/json'},
    data: {
      grant_type: 'authorization_code',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      code: '{yourAuthorizationCode}',
      redirect_uri: '{yourRedirectUri}',
      audience: 'https://{yourDomain}/me/',
      scope: 'create:me:authentication_methods',
      offline_access: ''
    }
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/oauth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}",
    CURLOPT_HTTPHEADER => [
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}"

  headers = { 'content-type': "application/json" }

  conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/oauth/token")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/json'
  request.body = "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

#### Embedded login with native passkeys

To include [passkeys](/docs/authenticate/database-connections/passkeys) in your embedded application's login flow, first request login challenge:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/passkey/challenge' \
    --header 'content-type: application/json' \
    --data '{"client_id": "{yourClientId}"}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/passkey/challenge");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{"client_id": "{yourClientId}"}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/passkey/challenge"

  	payload := strings.NewReader("{"client_id": "{yourClientId}"}")

  	req, _ := http.NewRequest("POST", url, payload)

  	req.Header.Add("content-type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/passkey/challenge")
    .header("content-type", "application/json")
    .body("{"client_id": "{yourClientId}"}")
    .asString();
  ```

  ```javascript Node.js theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/passkey/challenge',
    headers: {'content-type': 'application/json'},
    data: {client_id: '{yourClientId}'}
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/passkey/challenge",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{"client_id": "{yourClientId}"}",
    CURLOPT_HTTPHEADER => [
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{"client_id": "{yourClientId}"}"

  headers = { 'content-type': "application/json" }

  conn.request("POST", "/{yourDomain}/passkey/challenge", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/passkey/challenge")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/json'
  request.body = "{"client_id": "{yourClientId}"}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Next, authenticate existing users:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --header 'content-type: application/json' \
    --data '{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/oauth/token"

  	payload := strings.NewReader("{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}")

  	req, _ := http.NewRequest("POST", url, payload)

  	req.Header.Add("content-type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/json")
    .body("{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}")
    .asString();
  ```

  ```javascript Node.js theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    headers: {'content-type': 'application/json'},
    data: '{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}'
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/oauth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}",
    CURLOPT_HTTPHEADER => [
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}"

  headers = { 'content-type': "application/json" }

  conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/oauth/token")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/json'
  request.body = "{  "grant_type": "urn:okta:params:oauth:grant-type:webauthn",  "client_id": "{yourClientId}",  "scope": "create:me:authentication_methods offline_access",  "audience": "https://{yourDomain}/me/",  "auth_session": "{sessionIdFromTheFirstRequest}",  "authn_response": "{authenticatorResponse}"}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

## Manage authentication methods

With the My Account API, configure authentication methods so your end users are able to enroll and manage their own authentication methods. Most methods use a two-step flow: start enrollment, then confirm your enrollment.

Review the table for supported authentication methods.

| Type                                     | Enrollment behavior                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Enrollable via API |
| :--------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------- |
| `email`<br />Secondary (MFA)             | `POST { "type": "email" }` Include `email` in the `POST` request. Auth0 sends a one-time code to the address. Submit that code as `otp_code` in the verify request.                                                                                                                                                                                                                                                                                                                                                     | Yes                |
| `phone`<br />Secondary (MFA)             | `POST { "type": "sms" }` Auth0 sends a one-time code to the phone number. Submit that code as `otp_code` in the verify request.                                                                                                                                                                                                                                                                                                                                                                                         | Yes                |
| `totp`<br />Secondary (MFA)              | `POST { "type": "totp" }` The response includes: <ul><li>`barcode_uri`: renders as a QR code for the user to scan with an authenticator app.</li><li>`manual_input_code`: the TOTP secret for users who cannot scan a QR code.</li></ul>                                                                                                                                                                                                                                                                                | Yes                |
| `push-notification`<br />Secondary (MFA) | `POST { "type": "push-notification" }` The response includes a `barcode_uri` for the user to scan and link an authenticator app. The verify request requires only `auth_session` and not `otp_code`. Auth0 completes enrollment after the user approves the push in their app.                                                                                                                                                                                                                                          | Yes                |
| `recovery-code`<br />Secondary (MFA)     | `POST { "type": "recovery-code" }` The response includes a `recovery_code`. Display this value to the user immediately since you cannot retrieve it again. The verify request requires only `auth_session`.                                                                                                                                                                                                                                                                                                             | Yes                |
| `password`<br />Primary                  | `POST { "type": "password" }` The response includes a `policy` object describing the tenant's password requirements (e.g. minimum length, allowed character types, history, and dictionary settings). Submit `new_password` along with `auth_session` in the verify request. Auth0 validates the password against the policy before confirming enrollment.                                                                                                                                                              | Yes                |
| `passkey`<br />Primary                   | `POST { "type": "passkey" }`. The response does not include an ID. Instead it returns: <ul><li>`auth_session`: unique session identifier for the enrollment as returned by `POST /authentication-methods`.</li><li>`authn_params_public_key`: allows the WebAuthn `PublicKeyCredentialCreationOptions` to pass to `navigator.credentials.create()`. In the verify request, submit the full WebAuthn `AuthenticatorAttestationResponse` as `authn_response`. The method ID is returned in the verify response.</li></ul> | Yes                |
| `webauthn-platform`<br />Secondary (MFA) | Enrollment is not currently supported.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | No — read-only     |
| `webauthn-roaming`<br />Secondary (MFA)  | Enrollment is not currently supported.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | No — read-only     |

### Enrollment flow

Enrolling an authentication method is a two-step process:

1. To start enrollment, make a `POST` call to `/me/authentication-methods` with the method type and any required fields. Auth0 returns an `auth_session` token and type-specific enrollment.
2. To confirm enrollment, make a `POST` call to `/me/authentication-methods/{id}/verify` with the `auth_session` and the verification credential for that method type (an OTP code, a new password, or a WebAuthn response).

Once confirmed, Auth0 sets the method's `confirmed` field to `true` in subsequent `GET` responses.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Passkey enrollment does not include an ID in the `POST` response. Auth0 only returns the ID after the verify step succeeds.
</Callout>

### Manage authentication method examples

#### Enroll a TOTP authenticator

Enrolling TOTP is a two-step process: starting TOTP enrollment and confirming TOTP enrollment.

First, start enrollment to receive a QR code and manual secret for the user to add to their authenticator app:

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl --request POST \
      --url 'https://{yourDomain}/me/authentication-methods' \
      --header 'Authorization: Bearer {yourAccessToken}' \
      --header 'Content-Type: application/json' \
      --data '{"type": "totp"}'
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "id": "amr_abc123",
      "auth_session": "eyJhbGci...",
      "barcode_uri": "otpauth://totp/YourApp:user%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=YourApp",
      "manual_input_code": "JBSWY3DPEHPK3PXP"
    }
    ```
  </Tab>
</Tabs>

Next, confirm by submitting the one-time code from the user's authenticator app along with the `auth_session` and `id` from the previous response:

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl --request POST \
      --url 'https://{yourDomain}/me/authentication-methods/{id}/verify' \
      --header 'Authorization: Bearer {yourAccessToken}' \
      --header 'Content-Type: application/json' \
      --data '{"auth_session": "{yourAuthSession}", "otp_code": "{yourOtpCode}"}'
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "id": "amr_abc123",
      "type": "totp",
      "confirmed": true,
      "created_at": "2024-01-15T10:30:00.000Z",
      "updated_at": "2024-01-15T10:35:00.000Z"
    }
    ```
  </Tab>
</Tabs>

#### List authentication methods

Retrieve all authentication methods enrolled for the current user. The `confirmed` field indicates whether enrollment has been completed.

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl --request GET \
      --url 'https://{yourDomain}/me/authentication-methods' \
      --header 'Authorization: Bearer {yourAccessToken}'
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    [
      {
        "id": "amr_abc123",
        "type": "totp",
        "confirmed": true,
        "created_at": "2024-01-15T10:30:00.000Z",
        "updated_at": "2024-01-15T10:35:00.000Z"
      },
      {
        "id": "amr_def456",
        "type": "email",
        "email": "user@example.com",
        "confirmed": true,
        "created_at": "2024-01-10T08:00:00.000Z",
        "updated_at": "2024-01-10T08:05:00.000Z"
      }
    ]
    ```
  </Tab>
</Tabs>

#### Delete an authentication method

Remove an enrolled authentication method. Replace `{id}` with the method's `id` from the list response.

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl --request DELETE \
      --url 'https://{yourDomain}/me/authentication-methods/{id}' \
      --header 'Authorization: Bearer {yourAccessToken}'
    ```
  </Tab>

  <Tab title="Response">
    ```text theme={null}
    HTTP 204 No Content
    ```
  </Tab>
</Tabs>

## Cross-Origin Requests

If you intend to call the My Account API directly from a browser-based application (like a Single Page Application) running on a different domain than your Auth0 tenant, you may encounter browser security policies known as [Cross-Origin Resource Sharing (CORS)](/docs/authenticate/passwordless/implement-login/embedded-login/spa#configure-cross-origin-resource-sharing-cors). By default, browsers block these cross-origin requests.

To allow your application to successfully make requests to the API, you must add your application's domain (its "origin") to your client's configuration:

1. Navigate to [Dashboard > Applications](https://manage.auth0.com/#/applications). Select the application to view.
2. Under **Cross-Origin Authentication**, toggle on **Allow Cross-Origin Authentication**.
3. Locate **Allowed Origins (CORS)**, and enter your application's origin URL.
4. Select **Save**.

To learn more, read [Configure Cross-Origin Resource Sharing](/docs/get-started/applications/set-up-cors).

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  If you do not need to use CORS for your application, ensure that **Allow Cross-Origin Authentication** is toggled off. Adding your application's URL to this list tells Auth0 to trust requests from that origin, allowing your client-side application to access the API.
</Callout>
