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

# Authentication

> Secure your API requests with Bearer Token authentication

## Overview

The Sesame HR API uses **Bearer Token** authentication. Every API request must include a valid token in the `Authorization` header.

```
Authorization: Bearer YOUR_API_TOKEN
```

## Getting Your API Token

<Steps>
  <Step title="Access API Settings">
    Log in to [app.sesametime.com](https://app.sesametime.com) and navigate to **Settings** > **Integrations** > **API**
  </Step>

  <Step title="Create a New Token">
    Click **Create New Token**
  </Step>

  <Step title="Copy Your Token">
    Copy the token, you can use the copy icon
  </Step>

  <Step title="Store Securely">
    Save the token in your application's secure configuration (environment variables, secrets manager, etc.)
  </Step>
</Steps>

<Warning>
  **Security Best Practices**

  * Never expose tokens in client-side code, logs, or version control
  * Use environment variables or a secrets manager
  * Create separate tokens for each integration
  * Rotate tokens periodically
  * Revoke tokens immediately when compromised
</Warning>

## Making Authenticated Requests

Include your token in every API request:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api-{region}.sesametime.com/core/v3/employees" \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    -H "Content-Type: application/json"
  ```

  ```javascript JavaScript (fetch) theme={null}
  const SESAME_API_TOKEN = process.env.SESAME_API_TOKEN;
  const BASE_URL = 'https://api-{region}.sesametime.com';

  async function fetchEmployees() {
    const response = await fetch(`${BASE_URL}/core/v3/employees`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${SESAME_API_TOKEN}`,
        'Content-Type': 'application/json'
      }
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    return response.json();
  }
  ```

  ```javascript Node.js (axios) theme={null}
  const axios = require('axios');

  const sesameClient = axios.create({
    baseURL: 'https://api-{region}.sesametime.com',
    headers: {
      'Authorization': `Bearer ${process.env.SESAME_API_TOKEN}`,
      'Content-Type': 'application/json'
    }
  });

  // Usage
  const { data } = await sesameClient.get('/core/v3/employees');
  ```

  ```python Python (requests) theme={null}
  import os
  import requests

  class SesameAPI:
      def __init__(self):
          self.base_url = 'https://api-{region}.sesametime.com'
          self.token = os.environ.get('SESAME_API_TOKEN')
          self.headers = {
              'Authorization': f'Bearer {self.token}',
              'Content-Type': 'application/json'
          }

      def get_employees(self, **params):
          response = requests.get(
              f'{self.base_url}/core/v3/employees',
              headers=self.headers,
              params=params
          )
          response.raise_for_status()
          return response.json()

  # Usage
  api = SesameAPI()
  employees = api.get_employees(limit=10)
  ```

  ```python Python (httpx - async) theme={null}
  import httpx
  import os

  async def get_employees():
      async with httpx.AsyncClient() as client:
          response = await client.get(
              'https://api-{region}.sesametime.com/core/v3/employees',
              headers={
                  'Authorization': f'Bearer {os.environ["SESAME_API_TOKEN"]}',
                  'Content-Type': 'application/json'
              }
          )
          response.raise_for_status()
          return response.json()
  ```

  ```php PHP theme={null}
  <?php
  class SesameAPI {
      private string $baseUrl = 'https://api-{region}.sesametime.com';
      private string $token;

      public function __construct() {
          $this->token = getenv('SESAME_API_TOKEN');
      }

      public function getEmployees(array $params = []): array {
          $url = $this->baseUrl . '/core/v3/employees?' . http_build_query($params);

          $ch = curl_init($url);
          curl_setopt_array($ch, [
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_HTTPHEADER => [
                  'Authorization: Bearer ' . $this->token,
                  'Content-Type: application/json'
              ]
          ]);

          $response = curl_exec($ch);
          $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);

          if ($statusCode >= 400) {
              throw new Exception("API Error: $statusCode");
          }

          return json_decode($response, true);
      }
  }

  // Usage
  $api = new SesameAPI();
  $employees = $api->getEmployees(['limit' => 10]);
  ```

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

  import (
      "encoding/json"
      "fmt"
      "net/http"
      "os"
  )

  type SesameClient struct {
      BaseURL string
      Token   string
      Client  *http.Client
  }

  func NewSesameClient() *SesameClient {
      return &SesameClient{
          BaseURL: "https://api-{region}.sesametime.com",
          Token:   os.Getenv("SESAME_API_TOKEN"),
          Client:  &http.Client{},
      }
  }

  func (c *SesameClient) GetEmployees() (map[string]interface{}, error) {
      req, _ := http.NewRequest("GET", c.BaseURL+"/core/v3/employees", nil)
      req.Header.Set("Authorization", "Bearer "+c.Token)
      req.Header.Set("Content-Type", "application/json")

      resp, err := c.Client.Do(req)
      if err != nil {
          return nil, err
      }
      defer resp.Body.Close()

      var result map[string]interface{}
      json.NewDecoder(resp.Body).Decode(&result)
      return result, nil
  }
  ```

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

  class SesameAPI
    BASE_URL = 'https://api-{region}.sesametime.com'

    def initialize
      @token = ENV['SESAME_API_TOKEN']
    end

    def get_employees(params = {})
      uri = URI("#{BASE_URL}/core/v3/employees")
      uri.query = URI.encode_www_form(params) if params.any?

      request = Net::HTTP::Get.new(uri)
      request['Authorization'] = "Bearer #{@token}"
      request['Content-Type'] = 'application/json'

      response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
        http.request(request)
      end

      JSON.parse(response.body)
    end
  end

  # Usage
  api = SesameAPI.new
  employees = api.get_employees(limit: 10)
  ```
</CodeGroup>

## Verifying Your Token

Test your token by calling the info endpoint:

```bash theme={null}
curl -X GET "https://api-{region}.sesametime.com/core/v3/info" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

## Managing Tokens

### Listing Active Tokens

View all active tokens in **Settings** > **Integrations** > **API**. Each token shows:

* Token
* Active
* Creation Date
* Last Used Date

### Revoking Tokens

To revoke a token:

1. Go to **Settings** > **Integrations** > **API**
2. Find the token to revoke
3. Click the delete button
4. Confirm the action

<Warning>
  Revoking a token immediately invalidates it. Any applications using that token will receive `401 Unauthorized` errors.
</Warning>

## Authentication Errors

| Status | Error         | Cause                    | Solution                               |
| ------ | ------------- | ------------------------ | -------------------------------------- |
| `401`  | Unauthorized  | Missing or invalid token | Check token is correct and not deleted |
| `401`  | Token Expired | Token has been revoked   | Generate a new token                   |

<Accordion title="Troubleshooting 401 Errors">
  1. **Check token format**: Ensure the header is exactly `Authorization: Bearer YOUR_TOKEN` (note the space after "Bearer")
  2. **Verify token is active**: Check in the dashboard that the token hasn't been deleted
  3. **Check region**: Ensure you're using the correct API region for your account
  4. **Check for typos**: Copy the token again from the dashboard
  5. **Check encoding**: Ensure no extra characters or whitespace were added
</Accordion>

## Security Recommendations

<CardGroup cols={2}>
  <Card title="Environment Variables" icon="terminal">
    Store tokens in environment variables, never in code
  </Card>

  <Card title="Secrets Manager" icon="vault">
    Use AWS Secrets Manager, HashiCorp Vault, or similar for production
  </Card>

  <Card title="Token Rotation" icon="rotate">
    Rotate tokens every 90 days as a security best practice
  </Card>

  <Card title="Audit Logs" icon="clipboard-list">
    Monitor API usage in your Sesame HR dashboard
  </Card>
</CardGroup>
