> ## 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 to configure and use a default custom domain in Auth0.

# Default Custom Domain

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>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

When you have [multiple custom domains](/docs/customize/custom-domains/multiple-custom-domains) configured for your Auth0 tenant, you can designate one as the **default custom domain**. The default domain simplifies configuration and ensures a consistent user experience when a custom domain is not explicitly specified.

## What is a default custom domain?

The default custom domain is the custom domain that Auth0 uses automatically for:

* **Email and phone communications**: Sending password reset emails, email verification links, and other Auth0-generated notifications when no specific custom domain is specified. This includes scenarios where notifications are sent during authentication.
* **Management API calls**: Handling API requests that trigger notifications without the `auth0-custom-domain` header

You can configure your canonical tenant domain (`YOUR_TENANT.auth0.com` or `YOUR_TENANT.REGION.auth0.com`) as the default custom domain. There will always be a default custom domain configured for your tenant.

## Benefits of setting a default domain

Setting a default custom domain provides several advantages:

* **Simplified configuration**: Reduces the need to specify custom domains in every Management API call or configuration
* **Consistent branding**: Ensures users always see your brand, even when a specific domain isn't specified
* **Optional `auth0-custom-domain` header**: Makes the custom domain header optional in Management API requests
* **Fallback behavior**: Provides sensible defaults for multi-brand or multi-tenant implementations
* **Easier migration**: Simplifies transitioning from a single custom domain to multiple custom domains

## Configure a default domain

You can set a default custom domain through the Auth0 Dashboard or the Management API.

### Using the Auth0 Dashboard

To set a default custom domain in the Auth0 Dashboard:

1. Navigate to **Auth0 Dashboard** > **Branding > Custom Domains**
2. Find the verified custom domain you want to set as default in the list
3. Click the **Set as Default** button for that domain
4. Confirm the action in the dialog that appears

The domain will now show a "Default" badge in the custom domains list.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Only verified custom domains can be set as the default. Ensure your custom domain is fully verified and active before designating it as the default.
</Callout>

### Using the Management API

To set a default custom domain via the Management API, use the `PATCH /api/v2/custom-domains/default` endpoint:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url 'https://{yourDomain}/api/v2/custom-domains/default' \
    --header 'authorization: Bearer {yourMgmtApiAccessToken}' \
    --header 'content-type: application/json' \
    --data '{
      "domain": "my-custom-domain.com"
    }'
  ```

  ```javascript Node.js theme={null}
  import { ManagementClient } from "auth0";

  const management = new ManagementClient({
    domain: '{yourDomain}',
    clientId: '{yourClientId}',
    clientSecret: '{yourClientSecret}',
  });

  await management.customDomains.setDefault({
    domain: 'my-custom-domain.com',
  });
  ```

  ```python Python theme={null}
  from auth0.management import ManagementClient

  client = ManagementClient(
      domain='{yourDomain}',
      client_id='{yourClientId}',
      client_secret='{yourClientSecret}',
  )

  client.custom_domains.set_default({
      'domain': 'my-custom-domain.com',
  })
  ```

  ```go Go theme={null}
  import (
      "context"
      "github.com/auth0/go-auth0/v2/management"
      management_client "github.com/auth0/go-auth0/v2/management/client"
      "github.com/auth0/go-auth0/v2/management/option"
  )

  mgmt, err := management_client.New(
      "{yourDomain}",
      option.WithClientCredentials("{yourClientId}", "{yourClientSecret}"),
  )
  if err != nil {
      // Handle error
  }

  err = mgmt.CustomDomains.SetDefault(context.Background(), &management.SetDefaultCustomDomainRequestContent{
      Domain: "my-custom-domain.com",
  })
  ```

  ```java Java theme={null}
  import com.auth0.client.mgmt.ManagementAPI;
  import com.auth0.json.mgmt.customdomains.SetDefaultCustomDomainRequest;

  ManagementAPI mgmt = ManagementAPI.newBuilder(
      "{yourDomain}",
      "{yourMgmtApiAccessToken}"
  ).build();

  SetDefaultCustomDomainRequest request = new SetDefaultCustomDomainRequest("my-custom-domain.com");

  mgmt.customDomains()
      .setDefault(request)
      .execute();
  ```
</AuthCodeGroup>

## Remove default domain designation

To remove the default designation from a custom domain:

1. Set a different custom domain as the default (only one domain can be default at a time), or
2. Use the Management API to set `is_default: false` on the current default domain

When no custom domain is set as default, Auth0 will use your canonical tenant domain.

## How the default domain is used

### Email notifications

When Auth0 sends email notifications (password resets, email verification, welcome emails), the default domain is used for links and customizations in these notifications. You can customize email templates to use custom domain information in the "From" address, subject line, and email body.

### Management API endpoints that trigger notifications

The default custom domain is used specifically for Management API endpoints that trigger email or phone notifications. The `auth0-custom-domain` header becomes optional for these endpoints when you have a default domain configured.

**Endpoints that trigger email notifications:**

* `POST /api/v2/tickets/password-change` - Sends password reset email
* `POST /api/v2/tickets/email-verification` - Sends email verification
* `POST /api/v2/jobs/verification-email` - Sends verification email to user(s)
* `POST /api/v2/users` - Can trigger welcome email if configured
* `PATCH /api/v2/users/{id}` - Can trigger verification email when email is updated

**Endpoints that trigger phone notifications:**

* `POST /api/v2/users/{id}/phone/verification` - Sends SMS verification code

**Example:**

<AuthCodeGroup>
  ```bash Without custom domain header (uses default) theme={null}
  # Password reset ticket uses default domain in email links
  curl --request POST \
    --url 'https://{yourDomain}/api/v2/tickets/password-change' \
    --header 'authorization: Bearer {yourMgmtApiAccessToken}' \
    --header 'content-type: application/json' \
    --data '{
      "user_id": "auth0|123456",
      "result_url": "https://example.com/password-changed"
    }'
  ```

  ```bash With custom domain header (overrides default) theme={null}
  # Explicitly specify a different custom domain for this notification
  curl --request POST \
    --url 'https://{yourDomain}/api/v2/tickets/password-change' \
    --header 'authorization: Bearer {yourMgmtApiAccessToken}' \
    --header 'auth0-custom-domain: brand-specific.com' \
    --header 'content-type: application/json' \
    --data '{
      "user_id": "auth0|123456",
      "result_url": "https://example.com/password-changed"
    }'
  ```
</AuthCodeGroup>

When you don't provide the `auth0-custom-domain` header for these notification endpoints, Auth0 automatically uses the default custom domain for links and customizations in the email or SMS. You can override this on a per-request basis by including the `auth0-custom-domain` header.

## Using the default domain with Actions

Use [Actions](/docs/customize/actions) to implement logic based on the custom domain:

```javascript theme={null}
exports.onExecutePostLogin = async (event, api) => {
  const domain = event.custom_domain?.domain;

  // Store the login domain in user metadata
  if (domain) {
    api.user.setAppMetadata('login_domain', domain);
  }
};
```

To learn more about using custom domain information in Actions, see [Actions Integration with Multiple Custom Domains](/docs/customize/custom-domains/multiple-custom-domains/actions-integration).

## Best practices

When configuring a default custom domain, consider these best practices:

* **Choose a stable domain**: Select a domain that won't change frequently as your default
* **Verify before setting**: Ensure the domain is fully verified and operational before making it default
* **Document the decision**: Record why a particular domain was chosen as default for future reference
* **Test email flows**: After setting a default domain, test password reset and email verification flows
* **Monitor token issuers**: Verify that tokens have the expected `iss` claim after setting a default
* **Plan for multi-brand scenarios**: If you serve multiple brands, choose a generic or admin domain as default
* **Update integrations**: Inform your team about the default domain to ensure proper integration configuration

## Learn more

* [Multiple Custom Domains](/docs/customize/custom-domains/multiple-custom-domains)
* [Configure Features to Use Custom Domains](/docs/customize/custom-domains/configure-features-to-use-custom-domains)
* [Custom Domains Overview](/docs/customize/custom-domains)
* [Use Custom Domains in Emails](/docs/customize/custom-domains/configure-features-to-use-custom-domains#use-custom-domains-in-emails-and-phone-notifications)
* [Actions Integration with Custom Domains](/docs/customize/actions)
