Hopshift
API Reference

Employees

List and look up employees across your Hopshift group

List Employees

GET /api/v1/employees

Returns 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/employees

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number (1-indexed)
limitinteger50Records per page (max: 500)
statusstringactiveFilter by status. One of: active, inactive, terminated, on_leave
typestring:Filter by employment type. One of: full-time, part-time, contract, intern
departmentstring:Filter by department name (case-insensitive partial match)
companystring: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

FieldTypeNotes
idstringInternal system ID. Always unique, never changes. Use this for stable references across your integration.
employee_idstring | nullHR-assigned staff code (e.g. EMP001). null if no code has been assigned.
typestring | nullEmployment type. One of full-time, part-time, contract, intern.
namestring | nullFirst name (Latin script).
surnamestring | nullLast name (Latin script).
name_thstring | nullFirst name in Thai script. Only present for TH company employees.
surname_thstring | nullLast name in Thai script. Only present for TH company employees.
genderstring | nullOne of MALE, FEMALE, OTHER, or null if not set.
birthdatestring | nullDate of birth in YYYY-MM-DD format. null if not recorded.
nationalitystring | nullISO 3166-1 alpha-2 country code (e.g. TH, SG, GB). null if not set.
departmentstring | nullDepartment name. null if no department assigned.
positionstring | nullJob position name (Latin script). null if not assigned.
position_thstring | nullJob position name in Thai script. Only present for TH company employees.
companystringName of the company this employee belongs to.
company_idstringInternal ID of the company. Useful for precise ?company= filtering.
company_countrystring | nullISO 3166-1 alpha-2 country code of the company.
statusstringOne of active, inactive, terminated, on_leave.

Field Value Reference

status

ValueDescription
activeCurrently employed and active
inactiveEmployment paused or on extended leave
terminatedEmployment has ended
on_leaveCurrently on a leave of absence

type

ValueDescription
full-timePermanent full-time employee
part-timePermanent part-time employee
contractFixed-term contract employee
internIntern or trainee

gender

ValueDescription
MALEMale
FEMALEFemale
OTHEROther / prefer not to specify
nullNot recorded

Pagination Object

FieldTypeDescription
pageintegerCurrent page number.
limitintegerRecords per page used for this response.
totalintegerTotal number of matching employees across all pages.
total_pagesintegerTotal 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/:identifier

Look 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/:identifier

Path Parameters

ParameterDescription
identifierThe 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

StatusBodyReason
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" }

On this page