Authentication

All API requests require an access token. Authenticate with the token endpoint, then send the token in the Authorization header.

Token Authentication

CitoHR API authentication uses a token-based flow. Start by calling the authentication endpoint with the user's email address and password, then use the returned access token on API requests.

Send the token in the request header like this:

Authorization: Bearer YOUR_ACCESS_TOKEN

Base URL

All API requests should be made to your organization's subdomain:

https://{your-subdomain}.citohr.com/api

Or if using the main domain:

https://app.citohr.com/api

Basic Flow

  1. Call POST /api/auth/token with the user's email and password.
  2. Read the access_token from the response.
  3. Send that token in the Authorization header on API requests.
  4. The API executes with that user's normal permissions and organization scope.

If you also receive a refresh token, you can call /api/auth/refresh with that refresh token to request a new access token.

Token Endpoint

Request a token with the user's login credentials:

POST /api/auth/token
Content-Type: application/json

{
  "email": "your-email@example.com",
  "password": "your-password"
}

Example response:

{
  "access_token": "eyJhbGciOi...",
  "refresh_token": "eyJhbGciOi...",
  "token_type": "bearer",
  "expires_in": 3600,
  "expires_at": 1760000000,
  "user": {
    "id": "user_id",
    "email": "admin@company.com",
    "organizationId": "org_id",
    "roles": ["ADMIN"]
  }
}

Refresh Token

Use the refresh endpoint to obtain a new access token without sending the user's email and password again.

POST /api/auth/refresh
Content-Type: application/json

{
  "refresh_token": "YOUR_REFRESH_TOKEN"
}

Example refresh response:

{
  "access_token": "YOUR_NEW_ACCESS_TOKEN"
}

Programmatic Authentication

For server-to-server or scripted access, request a token first, store the refresh token securely if one is returned, and then refresh the access token when needed.

const fetch = require('node-fetch');

async function getAccessToken(email, password) {
  const response = await fetch('https://app.citohr.com/api/auth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ email, password })
  });

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

  const data = await response.json();
  return data;
}

async function refreshAccessToken(refreshToken) {
  const response = await fetch('https://app.citohr.com/api/auth/refresh', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ refresh_token: refreshToken })
  });

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

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

async function getUsers() {
  const auth = await getAccessToken('your-email@example.com', 'your-password');

  const response = await fetch('https://app.citohr.com/api/users', {
    headers: {
      Authorization: `Bearer ${auth.access_token}`
    }
  });

  return response.json();
}

Python Example:

import requests

def get_access_token(email, password):
    response = requests.post(
        'https://app.citohr.com/api/auth/token',
        json={
            'email': email,
            'password': password
        }
    )

    response.raise_for_status()
    data = response.json()
    return data

def refresh_access_token(refresh_token):
    response = requests.post(
        'https://app.citohr.com/api/auth/refresh',
        json={
            'refresh_token': refresh_token
        }
    )

    response.raise_for_status()
    data = response.json()
    return data['access_token']

auth = get_access_token('your-email@example.com', 'your-password')

headers = {
    'Authorization': f'Bearer {auth["access_token"]}'
}

response = requests.get('https://app.citohr.com/api/users', headers=headers)

Authorization & Roles

API requests run with the authenticated user's normal permissions and organization scope.

  • USER - Basic user access to own data
  • MANAGER - Access to team member data
  • ADMIN - Full organization access

If the authenticated user does not have the required role, the API returns 403 Forbidden.

Error Responses

Common authentication errors:

  • 401 Unauthorized - Missing or invalid token
  • 403 Forbidden - Valid token but insufficient permissions
  • 500 Internal Server Error - Server error during authentication