Employees
List and look up employees across your Hopshift group
List Employees
GET /api/v1/employeesReturns a paginated list of employees across every company in your group.
Authentication required: Yes: see Authentication.
Required scope: employees:read
Endpoint
GET https://hopshift.nottoosweetlabs.com/api/v1/employeesQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-indexed) |
limit | integer | 50 | Records per page (max: 500) |
status | string | active | Filter by status. One of: active, inactive, terminated, on_leave |
type | string | : | Filter by employment type. One of: full-time, part-time, contract, intern |
department | string | : | Filter by department name (case-insensitive partial match) |
company | string | : | Filter by company name (case-insensitive partial match) or exact company ID |
Request Examples
# All active employees (default)
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees" \
-H "Authorization: Bearer hops_your_api_key_here"
# Full-time employees in the FOH department
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees?type=full-time&department=FOH" \
-H "Authorization: Bearer hops_your_api_key_here"
# All employees at a specific company
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees?company=Sarnies+Coffee" \
-H "Authorization: Bearer hops_your_api_key_here"
# Terminated employees
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees?status=terminated&limit=500" \
-H "Authorization: Bearer hops_your_api_key_here"Response
{
"data": [
{
"id": "e97009bb-da79-4c30-b28c-47e676da94f1",
"employee_id": "EMP001",
"type": "full-time",
"name": "Somchai",
"surname": "Jaidee",
"name_th": "สมชาย",
"surname_th": "ใจดี",
"gender": "MALE",
"birthdate": "1990-01-15",
"nationality": "TH",
"department": "Engineering",
"position": "Software Engineer",
"position_th": "วิศวกรซอฟต์แวร์",
"company": "Hopshift Bangkok",
"company_id": "cml3tyydi000t4mwvfwybk976",
"company_country": "TH",
"status": "active"
},
{
"id": "f12a3bc4-1234-5678-abcd-ef1234567890",
"employee_id": null,
"type": "part-time",
"name": "Sarah",
"surname": "Wong",
"gender": "FEMALE",
"birthdate": "1995-07-22",
"nationality": "SG",
"department": "Operations",
"position": "Shift Supervisor",
"company": "Hopshift Singapore",
"company_id": "cml3abc1200024mwvzqx4d8ks",
"company_country": "SG",
"status": "active"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 150,
"total_pages": 3
}
}Thai name and position fields (name_th, surname_th, position_th) are only present in records belonging to companies whose country is set to TH. They are omitted entirely for non-TH employees.
Response Fields
Employee Object
| Field | Type | Notes |
|---|---|---|
id | string | Internal system ID. Always unique, never changes. Use this for stable references across your integration. |
employee_id | string | null | HR-assigned staff code (e.g. EMP001). null if no code has been assigned. |
type | string | null | Employment type. One of full-time, part-time, contract, intern. |
name | string | null | First name (Latin script). |
surname | string | null | Last name (Latin script). |
name_th | string | null | First name in Thai script. Only present for TH company employees. |
surname_th | string | null | Last name in Thai script. Only present for TH company employees. |
gender | string | null | One of MALE, FEMALE, OTHER, or null if not set. |
birthdate | string | null | Date of birth in YYYY-MM-DD format. null if not recorded. |
nationality | string | null | ISO 3166-1 alpha-2 country code (e.g. TH, SG, GB). null if not set. |
department | string | null | Department name. null if no department assigned. |
position | string | null | Job position name (Latin script). null if not assigned. |
position_th | string | null | Job position name in Thai script. Only present for TH company employees. |
company | string | Name of the company this employee belongs to. |
company_id | string | Internal ID of the company. Useful for precise ?company= filtering. |
company_country | string | null | ISO 3166-1 alpha-2 country code of the company. |
status | string | One of active, inactive, terminated, on_leave. |
Field Value Reference
status
| Value | Description |
|---|---|
active | Currently employed and active |
inactive | Employment paused or on extended leave |
terminated | Employment has ended |
on_leave | Currently on a leave of absence |
type
| Value | Description |
|---|---|
full-time | Permanent full-time employee |
part-time | Permanent part-time employee |
contract | Fixed-term contract employee |
intern | Intern or trainee |
gender
| Value | Description |
|---|---|
MALE | Male |
FEMALE | Female |
OTHER | Other / prefer not to specify |
null | Not recorded |
Pagination Object
| Field | Type | Description |
|---|---|---|
page | integer | Current page number. |
limit | integer | Records per page used for this response. |
total | integer | Total number of matching employees across all pages. |
total_pages | integer | Total pages given the current limit. |
Pagination
Results are ordered by employee last name (ascending). Use page and limit to step through large result sets.
To fetch all employees in one request (up to 500):
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees?limit=500" \
-H "Authorization: Bearer hops_your_api_key_here"To fetch all employees across multiple pages:
const BASE_URL = "https://hopshift.nottoosweetlabs.com";
const API_KEY = process.env.HOPSHIFT_API_KEY;
async function fetchAllEmployees() {
const allEmployees = [];
let page = 1;
let totalPages = 1;
while (page <= totalPages) {
const response = await fetch(
`${BASE_URL}/api/v1/employees?page=${page}&limit=500`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
if (!response.ok) throw new Error(`API error: ${response.status}`);
const body = await response.json();
allEmployees.push(...body.data);
totalPages = body.pagination.total_pages;
page++;
}
return allEmployees;
}Use limit=500 when syncing all employees to minimise the number of requests. At 200 requests per minute you can sync up to 100,000 employees per minute.
Get Employee
GET /api/v1/employees/:identifierLook up a single employee by their internal system id or HR-assigned employee_id. Both are tried automatically: no need to specify which type you're using.
Authentication required: Yes: see Authentication.
Required scope: employees:read
Endpoint
GET https://hopshift.nottoosweetlabs.com/api/v1/employees/:identifierPath Parameters
| Parameter | Description |
|---|---|
identifier | The employee's internal id (e.g. e97009bb-da79-4c30-b28c-47e676da94f1) or HR-assigned employee_id (e.g. EMP001) |
Request Examples
# Look up by HR employee ID
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees/EMP001" \
-H "Authorization: Bearer hops_your_api_key_here"
# Look up by internal system ID
curl "https://hopshift.nottoosweetlabs.com/api/v1/employees/e97009bb-da79-4c30-b28c-47e676da94f1" \
-H "Authorization: Bearer hops_your_api_key_here"Response
{
"data": {
"id": "e97009bb-da79-4c30-b28c-47e676da94f1",
"employee_id": "EMP001",
"type": "full-time",
"name": "Somchai",
"surname": "Jaidee",
"name_th": "สมชาย",
"surname_th": "ใจดี",
"gender": "MALE",
"birthdate": "1990-01-15",
"nationality": "TH",
"department": "Engineering",
"position": "Software Engineer",
"position_th": "วิศวกรซอฟต์แวร์",
"company": "Hopshift Bangkok",
"company_id": "cml3tyydi000t4mwvfwybk976",
"company_country": "TH",
"status": "active"
}
}The response fields are identical to those in the List Employees endpoint.
Error Responses
| Status | Body | Reason |
|---|---|---|
401 | {"error": "Unauthorized"} | Missing or invalid API key |
403 | {"error": "Forbidden: missing employees:read scope"} | Key lacks required scope |
404 | {"error": "Employee not found"} | No employee matched the identifier within your group |
429 | {"error": "Too many requests"} | Rate limit exceeded |
Error Responses (List)
400 Bad Request
Returned when a query parameter has an invalid value.
{
"error": "Invalid status. Valid values: active, inactive, terminated, on_leave"
}401 Unauthorized
{ "error": "Unauthorized" }403 Forbidden
{ "error": "Forbidden: missing employees:read scope" }429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 23
Content-Type: application/json
{ "error": "Too many requests" }500 Internal Server Error
{ "error": "Internal server error" }