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
- Call
POST /api/auth/tokenwith the user's email and password. - Read the
access_tokenfrom the response. - Send that token in the
Authorizationheader on API requests. - 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
