---
title: Work with multiple API endpoints
description: Configure sessions for multiple API endpoints using cookie and header-based authentication.
sidebar:
  order: 40
---

## Overview

To enable use of sessions for multiple API endpoints, you need to update the configuration on both the frontend and backend.

## Before you start

- All your API endpoints must have the same top level domain.
For example, they can be `{"api.example.com", "api2.example.com"}`, but they cannot be `{"api.example.com", "api.otherdomain.com"}`.
- Perform the backend configuration steps only if you are using cookie-based authentication.
If using header based auth, please skip to step 3.

## Steps

### 1. Set the cookie domain in the backend configuration

:::warning
This step is only applicable for cookie based authentication.
:::

Set the `cookieDomain` value to be the common top level domain.
For example, if your API endpoints are `{"api.example.com", "api2.example.com", "api3.example.com"}`, the common portion of these endpoints is `".example.com"` (The dot is important). You would need to set the following:

<CodeGroup group="backend-language">
<Tab title="Node.js" value="nodejs">
```tsx
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    Session.init({
      cookieDomain: ".example.com",
    }),
  ],
});
```
</Tab>
<Tab title="Go" value="go">
```go
import (
	"github.com/supertokens/supertokens-golang/recipe/session"
	"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	cookieDomain := ".example.com"

	supertokens.Init(supertokens.TypeInput{
		RecipeList: []supertokens.Recipe{
			session.Init(&sessmodels.TypeInput{
				CookieDomain: &cookieDomain,
			}),
		},
	})
}
```
</Tab>
<Tab title="Python" value="python">
```python check=false reason="Partial configuration example"
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import session


init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    framework='...',
    recipe_list=[
        session.init(
            cookie_domain='.example.com'
        )
    ]
)
```
</Tab>
</CodeGroup>

The above sets the session cookies' domain to `example.com`, allowing them to send to `*.example.com`.

:::note[Whilst the `cookieDomain` can start with a leading `.`, the value of the `apiDomain` in `appInfo` must point to an exact API domain only. This should be the API in which you want to expose all the auth related endpoints (for example `/auth/signin`).]

For local development, you should not set the `cookieDomain` to an IP address-based domain, or `.localhost` - browsers reject these cookies. Instead, you should [alias `localhost` to a named domain and use that](https://superuser.com/questions/152146/how-to-alias-a-hostname-on-mac-osx).
:::

### 2. Set the older cookie domain in the backend configuration

:::warning
This step is only applicable for cookie based authentication.
:::

To avoid locking out users with existing sessions (they get a 500 error when trying to refresh their session), set `olderCookieDomain` to match your previous `cookieDomain`.
If your `cookieDomain` was not set, you can use an empty string. However, if you don't have any existing sessions, you can skip this step entirely.

<CodeGroup group="backend-language">
<Tab title="Node.js" value="nodejs">
```tsx
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    Session.init({
      cookieDomain: ".example.com",
      olderCookieDomain: "", // Set to an empty string if your previous cookieDomain was unset. Otherwise, use your old cookieDomain value.
    }),
  ],
});
```
</Tab>
<Tab title="Go" value="go">
```go
import (
	"github.com/supertokens/supertokens-golang/recipe/session"
	"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	cookieDomain := ".example.com"
	olderCookieDomain := "" // Set to an empty string if your previous cookieDomain was unset. Otherwise, use your old cookieDomain value.

	supertokens.Init(supertokens.TypeInput{
		RecipeList: []supertokens.Recipe{
			session.Init(&sessmodels.TypeInput{
				CookieDomain: &cookieDomain,
				OlderCookieDomain: &olderCookieDomain,
			}),
		},
	})
}
```
</Tab>
<Tab title="Python" value="python">
```python check=false reason="Partial configuration example"
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import session


init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    framework='...',
    recipe_list=[
        session.init(
            cookie_domain='.example.com',
            older_cookie_domain='' # Set to an empty string if your previous cookie_domain was unset. Otherwise, use your old cookie_domain value.
        )
    ]
)
```
</Tab>
</CodeGroup>

:::warning[- If `olderCookieDomain` isn't set, users with older sessions get a 500 error from the session refresh endpoint, locking them out. This continues until you set `olderCookieDomain` correctly or they clear their cookies.]

- Keep the value set for `olderCookieDomain` for 1 year because the cookie lifetime of the access token on the frontend is 1 year (even though the JWT expiry is a few hours).

- If you have changed the `cookieDomain` more than once within one year, to prevent a stuck state, switch to [header-based auth](https://supertokens.com/docs/post-authentication/session-management/switch-between-cookies-and-header-authentication) for all your clients. The important thing here is that you have to set the backend configuration to header even though that doc says it's optional. This ensures that all clients use header-based auth.

- Changing the `cookieDomain` can cause a temporary spike in requests, even if you set the `olderCookieDomain` correctly. This happens because older sessions, with older cookie domain, require additional refresh calls to clear their old cookies and set new ones. This spike is a one-time event and should not recur after the update.
:::

:::info[Set the `olderCookieDomain` value to prevent clients from having multiple session cookies from different domains. This can happen when cookies from a previous domain are still valid and sent with requests. For instance, if your previous `cookieDomain` was `api.example.com` and the new one is `.example.com`, both sets of cookies would send to the `apiDomain` `api.example.com`, leading to an inconsistent state. This can cause issues until you clear the older cookies. Setting `olderCookieDomain` in the configuration ensures that the SuperTokens SDK can automatically remove these older cookies.]
:::

### 3. Update the frontend configuration

Set the same value for `sessionTokenBackendDomain` on the frontend.
This allows the frontend SDK to apply interception and automatic refreshing across all your API calls:

<UITypeSwitch />

<VariantContent storageKey="ui-type" value="prebuilt">

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
You need to make changes to the auth route configuration, as well as to the `supertokens-web-js` SDK configuration at the root of your application:

This change is in your auth route configuration.
</ContentOption>
</DependentContent>

<CodeGroup group="frontend-prebuilt-ui">
<Tab title="Reactjs" value="reactjs">
```tsx
import SuperTokens from "supertokens-auth-react";
import Session from "supertokens-auth-react/recipe/session";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    Session.init({
      sessionTokenBackendDomain: ".example.com",
    }),
  ],
});
```
</Tab>
<Tab title="Angular" value="angular">
```tsx check=false reason="Requires SDK globals from surrounding application"
supertokensUIInit({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    supertokensUISession.init({
      sessionTokenBackendDomain: ".example.com",
    }),
  ],
});
```
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
This change goes in the `supertokens-web-js` SDK configuration at the root of your application:
</ContentOption>
</DependentContent>

<CodeGroup passive group="frontend-prebuilt-ui">
<Tab title="Angular" value="angular">
```tsx
import SuperTokens from "supertokens-web-js";
import Session from "supertokens-web-js/recipe/session";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
  },
  recipeList: [
    Session.init({
      sessionTokenBackendDomain: ".example.com",
    }),
  ],
});
```
</Tab>
</CodeGroup>

</VariantContent>

<VariantContent storageKey="ui-type" value="custom">



<CodeGroup group="frontend-custom-ui">
<Tab title="Web" value="web">
<DependentContent group="install-method" label="Installation method">
<ContentOption title="npm" value="npm">
```tsx
import SuperTokens from "supertokens-web-js";
import Session from "supertokens-web-js/recipe/session";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
  },
  recipeList: [
    Session.init({
      sessionTokenBackendDomain: ".example.com",
    }),
  ],
});
```
</ContentOption>
<ContentOption title="Script tag" value="script-tag">
```tsx check=false reason="Requires SDK globals from surrounding application"
supertokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
  },
  recipeList: [
    supertokensSession.init({
      sessionTokenBackendDomain: ".example.com",
    }),
  ],
});
```
</ContentOption>
</DependentContent>
</Tab>
<Tab title="Mobile" value="mobile">
<DependentContent group="mobile-frameworks" label="Mobile framework">
<ContentOption title="ReactNative" value="reactnative">
```tsx
import SuperTokens from "supertokens-react-native";

SuperTokens.init({
  apiDomain: "...",
  sessionTokenBackendDomain: ".example.com",
});
```
</ContentOption>
<ContentOption title="Android" value="android">
```kotlin
import android.app.Application
import com.supertokens.session.SuperTokens

class MainApplication: Application() {
    override fun onCreate() {
        super.onCreate()

        SuperTokens.Builder(this, "...")
            .sessionTokenBackendDomain(".example.com")
            .build()
    }
}
```
</ContentOption>
<ContentOption title="iOS" value="ios">
```swift
import UIKit
import SuperTokensIOS

fileprivate class ApplicationDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        do {
            try SuperTokens.initialize(
                apiDomain: "...",
                sessionTokenBackendDomain: ".example.com"
            )
        } catch SuperTokensError.initError(let message) {
            // TODO: Handle initialization error
        } catch {
            // Some other error
        }

        return true
    }

}
```
</ContentOption>
<ContentOption title="Flutter" value="flutter">
```dart
import 'package:supertokens_flutter/supertokens.dart';

void initialiseSuperTokens() {
    SuperTokens.init(
        apiDomain: "...",
        sessionTokenBackendDomain: ".example.com",
    );
}
```
</ContentOption>
</DependentContent>
</Tab>
</CodeGroup>



</VariantContent>
