> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corti.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart - Authenticating to the Corti API

> Learn how to authenticate with client credentials.

This guide shows how to authenticate with the Corti API using OAuth 2.0 client credentials.

## Authenticate with an SDK (recommended)

The fastest way to authenticate is with an official SDK. The SDK handles the OAuth2 token exchange and refresh automatically. See [SDK overview](/sdk/overview) for setup and usage details.

Install SDK to your project:

<CodeGroup>
  ```bash title="JavaScript" theme={null}
  npm install @corti/sdk
  # or
  yarn add @corti/sdk
  # or
  pnpm add @corti/sdk
  ```

  ```bash title="C# .NET" theme={null}
  dotnet add package Corti.Sdk

  # Alternatively, in your .csproj:
  # <PackageReference Include="Corti.Sdk" Version="*" />
  ```
</CodeGroup>

Create a client to call API:

<CodeGroup>
  ```ts title="JavaScript" theme={null}
  import { CortiClient } from "@corti/sdk";

  // Replace these with your values
  const CLIENT_ID = "<your-client-id>";
  const CLIENT_SECRET = "<your-client-secret>";
  const ENVIRONMENT = "<eu-or-us>";
  const TENANT = "<your-tenant-name>";

  const client = new CortiClient({
      environment: ENVIRONMENT,
      tenantName: TENANT,
      auth: {
          clientId: CLIENT_ID,
          clientSecret: CLIENT_SECRET,
      },
  });
  ```

  ```csharp title="C# .NET" theme={null}
  using Corti;

  // Replace these with your values
  const string CLIENT_ID = "<your-client-id>";
  const string CLIENT_SECRET = "<your-client-secret>";
  const string ENVIRONMENT = "<eu-or-us>";
  const string TENANT = "<your-tenant-name>";

  var client = new CortiClient(
      tenantName: TENANT,
      environment: ENVIRONMENT,
      auth: CortiClientAuth.ClientCredentials(
          clientId: CLIENT_ID,
          clientSecret: CLIENT_SECRET)
  );
  ```
</CodeGroup>

If you only need a token:

<CodeGroup>
  ```ts title="JavaScript" theme={null}
  import { CortiAuth } from "@corti/sdk";

  // Replace these with your values
  const CLIENT_ID = "<your-client-id>";
  const CLIENT_SECRET = "<your-client-secret>";
  const ENVIRONMENT = "<eu-or-us>";
  const TENANT = "<your-tenant-name>";

  const auth = new CortiAuth({
    environment: ENVIRONMENT,
    tenantName: TENANT,
  });

  const token = await auth.getToken({
    clientId: CLIENT_ID,
    clientSecret: CLIENT_SECRET,
  });

  console.log("accessToken:", token.accessToken);
  ```

  {/* Get a token via client credentials using CustomAuthClient */}

  ```csharp title="C# .NET" theme={null}
  using Corti;

  // Replace these with your values
  const string CLIENT_ID = "<your-client-id>";
  const string CLIENT_SECRET = "<your-client-secret>";
  const string ENVIRONMENT = "<eu-or-us>";
  const string TENANT = "<your-tenant-name>";

  var auth = CustomAuthClient.Create(
      new CortiAuthClientOptions
      {
          TenantName = TENANT,
          Environment = ENVIRONMENT,
      });

  var tokenResponse = await auth.GetTokenAsync(
      new OAuthTokenRequest
      {
          ClientId = CLIENT_ID,
          ClientSecret = CLIENT_SECRET,
      });

  Console.WriteLine(tokenResponse.AccessToken);
  ```
</CodeGroup>

<Tip>For full SDK authentication documentation including bearer tokens, PKCE, authorization code, and ROPC flows, see the [JavaScript Authentication Guide](/sdk/js/authentication) or the [.NET Authentication Guide](/sdk/dotnet/authentication).</Tip>

## Authenticate using manual code examples

If you prefer to handle OAuth manually without an SDK, use the examples below:

<CodeGroup>
  ```js title="JavaScript" expandable theme={null}
  // Replace these with your values
  const CLIENT_ID = "<your-client-id>";
  const CLIENT_SECRET = "<your-client-secret>";
  const ENVIRONMENT = "<eu-or-us>";
  const TENANT = "<your-tenant-name>";

  async function getAccessToken() {
    const tokenUrl = `https://auth.${ENVIRONMENT}.corti.app/realms/${TENANT}/protocol/openid-connect/token`;

    const params = new URLSearchParams();
    params.append("client_id", CLIENT_ID);
    params.append("client_secret", CLIENT_SECRET);
    params.append("grant_type", "client_credentials");
    params.append("scope", "openid");

    const res = await fetch(tokenUrl, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: params
    });

    if (!res.ok) {
      throw new Error(`Failed to get token, status ${res.status}`);
    }

    const data = await res.json();
    return data.access_token;
  }

  // Example usage
  getAccessToken().then(token => {
    console.log("Access token:", token);
  }).catch(err => {
    console.error("Error:", err);
  });
  ```

  ```csharp title="C# .NET" expandable theme={null}
  using System;
  using System.Net.Http;
  using System.Text.Json;
  using System.Threading.Tasks;

  class Program
  {
      private const string CLIENT_ID = "<your-client-id>";
      private const string CLIENT_SECRET = "<your-client-secret>";
      private const string ENVIRONMENT = "<eu-or-us>";
      private const string TENANT = "<your-tenant-name>";

      private static async Task<string> GetAccessTokenAsync()
      {
          var tokenUrl = $"https://auth.{ENVIRONMENT}.corti.app/realms/{TENANT}/protocol/openid-connect/token";

          using var http = new HttpClient();

          var content = new FormUrlEncodedContent(new[]
          {
              new KeyValuePair<string, string>("client_id", CLIENT_ID),
              new KeyValuePair<string, string>("client_secret", CLIENT_SECRET),
              new KeyValuePair<string, string>("grant_type", "client_credentials"),
              new KeyValuePair<string, string>("scope", "openid")
          });

          var response = await http.PostAsync(tokenUrl, content);
          response.EnsureSuccessStatusCode();

          var payload = await response.Content.ReadAsStringAsync();
          using var json = JsonDocument.Parse(payload);

          return json.RootElement.GetProperty("access_token").GetString()!;
      }

      static async Task Main()
      {
          var token = await GetAccessTokenAsync();
          Console.WriteLine($"Access token: {token}");
      }
  }
  ```

  ```python title="Python" expandable theme={null}
  import requests

  # Replace these with your values
  CLIENT_ID = "<your-client-id>"
  CLIENT_SECRET = "<your-client-secret>"
  ENVIRONMENT = "<eu-or-us>"
  TENANT = "<your-tenant-name>"

  def get_access_token():
      """Request an OAuth2 client-credentials access token from Corti."""
      url = f"https://auth.{ENVIRONMENT}.corti.app/realms/{TENANT}/protocol/openid-connect/token"

      data = {
          "client_id": CLIENT_ID,
          "client_secret": CLIENT_SECRET,
          "grant_type": "client_credentials",
          "scope": "openid",
      }

      res = requests.post(url, data=data, headers={"Content-Type": "application/x-www-form-urlencoded"})
      res.raise_for_status()
      return res.json()["access_token"]


  # Example usage
  if __name__ == "__main__":
      token = get_access_token()
      print("Access token:", token)
  ```

  ```bash title="cURL" theme={null}
  # Replace these with your values
  CLIENT_ID="<your-client-id>"
  CLIENT_SECRET="<your-client-secret>"
  ENVIRONMENT="<eu-or-us>"
  TENANT="<your-tenant-name>"

  curl "https://auth.${ENVIRONMENT}.corti.app/realms/${TENANT}/protocol/openid-connect/token" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "client_id=${CLIENT_ID}" \
    -d "client_secret=${CLIENT_SECRET}" \
    -d "grant_type=client_credentials" \
    -d "scope=openid"
  ```
</CodeGroup>

<Info>Tokens expire after **300 seconds** (5 minutes), refresh as needed.</Info>
