Employees
The people who can be sent to jobs (personal), their weekly working hours and their skills. Sync them from an HR or payroll system; match on employee_number.
List employees
/employeesEmployees by last name, then first name, with their skills and linked login. For an HR or payroll sync, match on employee_number. Cursor-paginated: follow links.next, or pass meta.next_cursor as cursor.
curl 'https://api.closepact.com/v1/api/employees' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY"{
"data": [
{
"id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"employee_number": "A-017",
"first_name": "Ali",
"last_name": "Hassan",
"name": "Ali Hassan",
"email": "ali.hassan@nordiskfastighet.se",
"phone": "073-981 22 40",
"employment_type": "employed",
"weekly_hours": 40,
"hourly_cost_cents": 32000,
"hourly_billing_rate_cents": 65000,
"color": "#2F80ED",
"status": "active",
"started_at": "2024-03-01",
"ended_at": null,
"user": {
"id": "01a14eb3-c6a1-7e2f-8a3b-4c5d6e7f8091",
"name": "Ali Hassan",
"email": "ali.hassan@nordiskfastighet.se"
},
"skills": [
{
"id": "01a15b70-7c8d-7e9f-a0b1-c2d3e4f50617",
"name": "Storstädning",
"color": "#27AE60",
"level": 3
}
],
"created_at": "2024-02-20T08:30:00+00:00",
"updated_at": "2026-10-01T12:00:00+00:00"
}
],
"links": {
"first": null,
"last": null,
"prev": null,
"next": null
},
"meta": {
"path": "https://api.closepact.com/v1/api/employees",
"per_page": 25,
"next_cursor": null,
"prev_cursor": null
}
}Query parameters
qstringSearch in first name, last name and employee number (case-insensitive, substring).
Example
Hassanfilter[status]stringOnly
activeor onlyinactiveemployees.One of
activeinactivefilter[skill_id]string(uuid)Only employees holding this skill.
limitintegerItems per page, 1–100.
Default
251–100cursorstringOpaque cursor from
meta.next_cursorormeta.prev_cursorof the previous page.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataarray of objectsrequiredidstring(uuid)requiredThe employee id.
employee_numberstringnullablerequiredYour own number for them (e.g. from payroll), or null.
first_namestringrequiredFirst name.
last_namestringrequiredLast name.
namestringrequiredFirst and last name.
emailstringnullablerequiredEmail address; assignments are emailed here. Null for none.
phonestringnullablerequiredPhone number as entered; used for SMS notices when the organization has turned them on.
employment_typestringrequiredKind of employment.
One of
employedhourlycontractorweekly_hoursnumbernullablerequiredContracted hours per week, or null.
hourly_cost_centsintegernullablerequiredWhat an hour of this person costs the company, in öre (not what it is sold for). Copied onto time entries as
hourly_rate_centswhen they are approved, for margin; never invoiced.hourly_billing_rate_centsintegernullablerequiredWhat an hour of this person is invoiced at, in öre excluding VAT. Copied onto time entries as
billing_rate_centswhen they are approved; the invoice basis bills hourly work at it unless the job was quoted one service price per hour. Null: such hours are billed at nothing and the basis warns.colorstringnullablerequiredColour on the board, e.g.
#2F80ED, or null.statusstringrequiredInactive employees stay on past jobs and timesheets but cannot be scheduled without a
not_employederror.One of
activeinactivestarted_atstring(date)nullablerequiredFirst day of employment, or null. Calendar date,
YYYY-MM-DD.ended_atstring(date)nullablerequiredLast day of employment, or null. Calendar date,
YYYY-MM-DD.userobjectnullableThe member login this employee is linked to, or null. Included by the list and
GET /employees/{employee}.skillsarray of objectsrequiredCompetences the employee holds. A service that requires competences can only be done by somebody holding them all.
availabilityarray of objectsWeekly working hours. Included by
GET /employees/{employee}only; also atGET /employees/{employee}/availability.created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
linksobjectrequiredmetaobjectrequired
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 429The key has made more requests this minute than its limit allows.Errors
Create an employee
/employeesAdds somebody who can be scheduled — from an HR system, say. An employee does not need a login and does not use a licence; link one with user_id if they should see their own jobs in the field app.
curl -X POST 'https://api.closepact.com/v1/api/employees' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ali",
"last_name": "Hassan",
"employee_number": "A-017",
"email": "ali.hassan@nordiskfastighet.se",
"phone": "073-981 22 40",
"employment_type": "employed",
"hourly_cost_cents": 32000,
"hourly_billing_rate_cents": 65000,
"weekly_hours": 40,
"started_at": "2024-03-01",
"skill_ids": [
"01a15b70-7c8d-7e9f-a0b1-c2d3e4f50617"
]
}'{
"data": {
"id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"employee_number": "A-017",
"first_name": "Ali",
"last_name": "Hassan",
"name": "Ali Hassan",
"email": "ali.hassan@nordiskfastighet.se",
"phone": "073-981 22 40",
"employment_type": "employed",
"weekly_hours": 40,
"hourly_cost_cents": 32000,
"hourly_billing_rate_cents": 65000,
"color": "#2F80ED",
"status": "active",
"started_at": "2024-03-01",
"ended_at": null,
"skills": [
{
"id": "01a15b70-7c8d-7e9f-a0b1-c2d3e4f50617",
"name": "Storstädning",
"color": "#27AE60",
"level": 3
}
],
"created_at": "2024-02-20T08:30:00+00:00",
"updated_at": "2026-10-01T12:00:00+00:00"
}
}Request body
application/json · required
first_namestringrequiredFirst name.
at most 128 characters
last_namestringrequiredLast name.
at most 128 characters
employee_numberstringnullableYour own number for them, e.g. the payroll id.
at most 32 characters
emailstring(email)nullableEmail address for assignment notices.
at most 320 characters
phonestringnullablePhone number.
at most 32 characters
employment_typestringDefault
employed.One of
employedhourlycontractorhourly_cost_centsintegernullableCost of an hour of this person in öre — wage and overheads, never invoiced.
≥ 0
hourly_billing_rate_centsintegernullableWhat an hour of this person is invoiced at, in öre excluding VAT. An hourly job bills this person's approved time at it when the job was not quoted one service price per hour.
≥ 0
weekly_hoursnumbernullableContracted hours per week, 0–168.
0–168
colorstringnullableColour on the board, e.g.
#2F80ED.at most 16 characters
statusstringDefault
active.One of
activeinactivestarted_atstring(date)nullableFirst day of employment. Calendar date,
YYYY-MM-DD.ended_atstring(date)nullableLast day of employment; not before
started_at. Calendar date,YYYY-MM-DD.user_idstring(uuid)nullableLink to the login of a member of your organization (an active member), or null for none.
sub_entity_idstring(uuid)nullableThe office (sub-entity) the employee belongs to. Must be one of yours.
skill_idsarray of strings(uuid)Replaces the employee's skills with these (see
GET /skills). Ids that are not your organization's are ignored. Leave out to keep the current skills;[]removes them all. A skill the employee already holds keeps its level; a new one starts at 1. To set levels, sendskillsinstead.skillsarray of objectsReplaces the employee's skills with these, each with a level. Same rules as
skill_ids, which it cannot be sent together with. A skill sent withoutlevelis level 1.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataobjectrequiredSomebody who can be sent to a job (personal). Not the same as a member of the organization: an employee may be linked to a member's login (
user) but need not be — field staff who never sign in are scheduled without using a licence.idstring(uuid)requiredThe employee id.
employee_numberstringnullablerequiredYour own number for them (e.g. from payroll), or null.
first_namestringrequiredFirst name.
last_namestringrequiredLast name.
namestringrequiredFirst and last name.
emailstringnullablerequiredEmail address; assignments are emailed here. Null for none.
phonestringnullablerequiredPhone number as entered; used for SMS notices when the organization has turned them on.
employment_typestringrequiredKind of employment.
One of
employedhourlycontractorweekly_hoursnumbernullablerequiredContracted hours per week, or null.
hourly_cost_centsintegernullablerequiredWhat an hour of this person costs the company, in öre (not what it is sold for). Copied onto time entries as
hourly_rate_centswhen they are approved, for margin; never invoiced.hourly_billing_rate_centsintegernullablerequiredWhat an hour of this person is invoiced at, in öre excluding VAT. Copied onto time entries as
billing_rate_centswhen they are approved; the invoice basis bills hourly work at it unless the job was quoted one service price per hour. Null: such hours are billed at nothing and the basis warns.colorstringnullablerequiredColour on the board, e.g.
#2F80ED, or null.statusstringrequiredInactive employees stay on past jobs and timesheets but cannot be scheduled without a
not_employederror.One of
activeinactivestarted_atstring(date)nullablerequiredFirst day of employment, or null. Calendar date,
YYYY-MM-DD.ended_atstring(date)nullablerequiredLast day of employment, or null. Calendar date,
YYYY-MM-DD.userobjectnullableThe member login this employee is linked to, or null. Included by the list and
GET /employees/{employee}.skillsarray of objectsrequiredCompetences the employee holds. A service that requires competences can only be done by somebody holding them all.
availabilityarray of objectsWeekly working hours. Included by
GET /employees/{employee}only; also atGET /employees/{employee}/availability.created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 422The request body or query failed validation.Errors
- 429The key has made more requests this minute than its limit allows.Errors
Get an employee
/employees/{employee}One employee with skills, linked login and weekly availability. A deleted employee, or another organization's, is a 404.
curl 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY"{
"data": {
"id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"employee_number": "A-017",
"first_name": "Ali",
"last_name": "Hassan",
"name": "Ali Hassan",
"email": "ali.hassan@nordiskfastighet.se",
"phone": "073-981 22 40",
"employment_type": "employed",
"weekly_hours": 40,
"hourly_cost_cents": 32000,
"hourly_billing_rate_cents": 65000,
"color": "#2F80ED",
"status": "active",
"started_at": "2024-03-01",
"ended_at": null,
"user": {
"id": "01a14eb3-c6a1-7e2f-8a3b-4c5d6e7f8091",
"name": "Ali Hassan",
"email": "ali.hassan@nordiskfastighet.se"
},
"skills": [
{
"id": "01a15b70-7c8d-7e9f-a0b1-c2d3e4f50617",
"name": "Storstädning",
"color": "#27AE60",
"level": 3
}
],
"availability": [
{
"id": "01a15b91-2a3b-7c4d-8e5f-60718293a4b5",
"organization_id": "01a14eb3-c5f0-7c55-8c2e-6a0e1f7b9d21",
"employee_id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"weekday": 1,
"start_time": "07:00:00",
"end_time": "11:30:00",
"valid_from": "2026-01-01T00:00:00.000000Z",
"valid_to": null,
"created_at": "2025-12-18T10:00:00.000000Z",
"updated_at": "2025-12-18T10:00:00.000000Z"
},
{
"id": "01a15b91-2a3c-7d5e-9f60-718293a4b5c6",
"organization_id": "01a14eb3-c5f0-7c55-8c2e-6a0e1f7b9d21",
"employee_id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"weekday": 1,
"start_time": "12:15:00",
"end_time": "16:00:00",
"valid_from": "2026-01-01T00:00:00.000000Z",
"valid_to": null,
"created_at": "2025-12-18T10:00:00.000000Z",
"updated_at": "2025-12-18T10:00:00.000000Z"
}
],
"created_at": "2024-02-20T08:30:00+00:00",
"updated_at": "2026-10-01T12:00:00+00:00"
}
}Path parameters
employeestring(uuid)requiredThe employee id.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataobjectrequiredSomebody who can be sent to a job (personal). Not the same as a member of the organization: an employee may be linked to a member's login (
user) but need not be — field staff who never sign in are scheduled without using a licence.idstring(uuid)requiredThe employee id.
employee_numberstringnullablerequiredYour own number for them (e.g. from payroll), or null.
first_namestringrequiredFirst name.
last_namestringrequiredLast name.
namestringrequiredFirst and last name.
emailstringnullablerequiredEmail address; assignments are emailed here. Null for none.
phonestringnullablerequiredPhone number as entered; used for SMS notices when the organization has turned them on.
employment_typestringrequiredKind of employment.
One of
employedhourlycontractorweekly_hoursnumbernullablerequiredContracted hours per week, or null.
hourly_cost_centsintegernullablerequiredWhat an hour of this person costs the company, in öre (not what it is sold for). Copied onto time entries as
hourly_rate_centswhen they are approved, for margin; never invoiced.hourly_billing_rate_centsintegernullablerequiredWhat an hour of this person is invoiced at, in öre excluding VAT. Copied onto time entries as
billing_rate_centswhen they are approved; the invoice basis bills hourly work at it unless the job was quoted one service price per hour. Null: such hours are billed at nothing and the basis warns.colorstringnullablerequiredColour on the board, e.g.
#2F80ED, or null.statusstringrequiredInactive employees stay on past jobs and timesheets but cannot be scheduled without a
not_employederror.One of
activeinactivestarted_atstring(date)nullablerequiredFirst day of employment, or null. Calendar date,
YYYY-MM-DD.ended_atstring(date)nullablerequiredLast day of employment, or null. Calendar date,
YYYY-MM-DD.userobjectnullableThe member login this employee is linked to, or null. Included by the list and
GET /employees/{employee}.skillsarray of objectsrequiredCompetences the employee holds. A service that requires competences can only be done by somebody holding them all.
availabilityarray of objectsWeekly working hours. Included by
GET /employees/{employee}only; also atGET /employees/{employee}/availability.created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 429The key has made more requests this minute than its limit allows.Errors
Update an employee
/employees/{employee}Changes the fields you send. To take somebody off the schedule but keep their history, set status to inactive (or ended_at) rather than deleting them.
curl -X PATCH 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "070-123 45 67",
"weekly_hours": 32
}'{
"data": {
"id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"employee_number": "A-017",
"first_name": "Ali",
"last_name": "Hassan",
"name": "Ali Hassan",
"email": "ali.hassan@nordiskfastighet.se",
"phone": "070-123 45 67",
"employment_type": "employed",
"weekly_hours": 32,
"hourly_cost_cents": 32000,
"hourly_billing_rate_cents": 65000,
"color": "#2F80ED",
"status": "active",
"started_at": "2024-03-01",
"ended_at": null,
"skills": [
{
"id": "01a15b70-7c8d-7e9f-a0b1-c2d3e4f50617",
"name": "Storstädning",
"color": "#27AE60",
"level": 3
}
],
"created_at": "2024-02-20T08:30:00+00:00",
"updated_at": "2026-10-01T12:00:00+00:00"
}
}Path parameters
employeestring(uuid)requiredThe employee id.
Request body
application/json · required
first_namestringFirst name.
at most 128 characters
last_namestringLast name.
at most 128 characters
employee_numberstringnullableYour own number for them, e.g. the payroll id.
at most 32 characters
emailstring(email)nullableEmail address for assignment notices.
at most 320 characters
phonestringnullablePhone number.
at most 32 characters
employment_typestringDefault
employed.One of
employedhourlycontractorhourly_cost_centsintegernullableCost of an hour of this person in öre — wage and overheads, never invoiced.
≥ 0
hourly_billing_rate_centsintegernullableWhat an hour of this person is invoiced at, in öre excluding VAT. An hourly job bills this person's approved time at it when the job was not quoted one service price per hour.
≥ 0
weekly_hoursnumbernullableContracted hours per week, 0–168.
0–168
colorstringnullableColour on the board, e.g.
#2F80ED.at most 16 characters
statusstringDefault
active.One of
activeinactivestarted_atstring(date)nullableFirst day of employment. Calendar date,
YYYY-MM-DD.ended_atstring(date)nullableLast day of employment; not before
started_at. Calendar date,YYYY-MM-DD.user_idstring(uuid)nullableLink to the login of a member of your organization (an active member), or null for none.
sub_entity_idstring(uuid)nullableThe office (sub-entity) the employee belongs to. Must be one of yours.
skill_idsarray of strings(uuid)Replaces the employee's skills with these (see
GET /skills). Ids that are not your organization's are ignored. Leave out to keep the current skills;[]removes them all. A skill the employee already holds keeps its level; a new one starts at 1. To set levels, sendskillsinstead.skillsarray of objectsReplaces the employee's skills with these, each with a level. Same rules as
skill_ids, which it cannot be sent together with. A skill sent withoutlevelis level 1.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataobjectrequiredSomebody who can be sent to a job (personal). Not the same as a member of the organization: an employee may be linked to a member's login (
user) but need not be — field staff who never sign in are scheduled without using a licence.idstring(uuid)requiredThe employee id.
employee_numberstringnullablerequiredYour own number for them (e.g. from payroll), or null.
first_namestringrequiredFirst name.
last_namestringrequiredLast name.
namestringrequiredFirst and last name.
emailstringnullablerequiredEmail address; assignments are emailed here. Null for none.
phonestringnullablerequiredPhone number as entered; used for SMS notices when the organization has turned them on.
employment_typestringrequiredKind of employment.
One of
employedhourlycontractorweekly_hoursnumbernullablerequiredContracted hours per week, or null.
hourly_cost_centsintegernullablerequiredWhat an hour of this person costs the company, in öre (not what it is sold for). Copied onto time entries as
hourly_rate_centswhen they are approved, for margin; never invoiced.hourly_billing_rate_centsintegernullablerequiredWhat an hour of this person is invoiced at, in öre excluding VAT. Copied onto time entries as
billing_rate_centswhen they are approved; the invoice basis bills hourly work at it unless the job was quoted one service price per hour. Null: such hours are billed at nothing and the basis warns.colorstringnullablerequiredColour on the board, e.g.
#2F80ED, or null.statusstringrequiredInactive employees stay on past jobs and timesheets but cannot be scheduled without a
not_employederror.One of
activeinactivestarted_atstring(date)nullablerequiredFirst day of employment, or null. Calendar date,
YYYY-MM-DD.ended_atstring(date)nullablerequiredLast day of employment, or null. Calendar date,
YYYY-MM-DD.userobjectnullableThe member login this employee is linked to, or null. Included by the list and
GET /employees/{employee}.skillsarray of objectsrequiredCompetences the employee holds. A service that requires competences can only be done by somebody holding them all.
availabilityarray of objectsWeekly working hours. Included by
GET /employees/{employee}only; also atGET /employees/{employee}/availability.created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 422The request body or query failed validation.Errors
- 429The key has made more requests this minute than its limit allows.Errors
Delete an employee
/employees/{employee}Removes the employee from lists and reads. Their name stays on past jobs and their hours on past timesheets. For somebody who has left, status: inactive is usually what you want.
curl -X DELETE 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY"{
"deleted": true
}Path parameters
employeestring(uuid)requiredThe employee id.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
deletedbooleanrequiredOne of
true
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 429The key has made more requests this minute than its limit allows.Errors
List an employee's working hours
/employees/{employee}/availabilityAll of the employee's availability rules, by weekday and start time — the whole set, not a page. Rules that have expired (valid_to in the past) are included.
curl 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40/availability' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY"{
"data": [
{
"id": "01a15b91-2a3b-7c4d-8e5f-60718293a4b5",
"organization_id": "01a14eb3-c5f0-7c55-8c2e-6a0e1f7b9d21",
"employee_id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"weekday": 1,
"start_time": "07:00:00",
"end_time": "11:30:00",
"valid_from": "2026-01-01T00:00:00.000000Z",
"valid_to": null,
"created_at": "2025-12-18T10:00:00.000000Z",
"updated_at": "2025-12-18T10:00:00.000000Z"
},
{
"id": "01a15b91-2a3c-7d5e-9f60-718293a4b5c6",
"organization_id": "01a14eb3-c5f0-7c55-8c2e-6a0e1f7b9d21",
"employee_id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"weekday": 1,
"start_time": "12:15:00",
"end_time": "16:00:00",
"valid_from": "2026-01-01T00:00:00.000000Z",
"valid_to": null,
"created_at": "2025-12-18T10:00:00.000000Z",
"updated_at": "2025-12-18T10:00:00.000000Z"
}
]
}Path parameters
employeestring(uuid)requiredThe employee id.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataarray of objectsrequiredidstring(uuid)requiredThe rule id.
organization_idstring(uuid)requiredYour organization.
employee_idstring(uuid)requiredThe employee.
weekdayintegerrequiredISO weekday: 1 = Monday … 7 = Sunday.
1–7
start_timestringrequiredStart,
HH:MM:SS, in Swedish local time (Europe/Stockholm). Job times, which are UTC instants, are converted to that clock — and to its weekday — before they are compared with the rule.end_timestringrequiredEnd,
HH:MM:SS, after the start.valid_fromstring(date-time)nullablerequiredFirst day the rule applies, as midnight UTC of that date (
2026-01-01T00:00:00.000000Z), or null for always. Only the date counts: it is matched against the job's date in Swedish time.valid_tostring(date-time)nullablerequiredLast day the rule applies (the whole day), as midnight UTC of that date, or null for open-ended. Only the date counts: it is matched against the job's date in Swedish time.
created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 429The key has made more requests this minute than its limit allows.Errors
Add working hours
/employees/{employee}/availabilityAdds the hours an employee normally works on one weekday. The schedule warns (outside_working_hours) when a job falls outside them; it never refuses. A split shift is two rules on the same day; gaps of up to an hour between them count as one working day.
To change hours from a date, add a rule with valid_from and end the old one with valid_to, so earlier timesheets keep the hours they were planned against. An identical rule (same day, times and dates) is a 409; an end before the start is a 422.
curl -X POST 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40/availability' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"weekday": 1,
"start_time": "07:00",
"end_time": "11:30",
"valid_from": "2026-01-01"
}'{
"data": {
"id": "01a15b91-2a3b-7c4d-8e5f-60718293a4b5",
"organization_id": "01a14eb3-c5f0-7c55-8c2e-6a0e1f7b9d21",
"employee_id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"weekday": 1,
"start_time": "07:00:00",
"end_time": "11:30:00",
"valid_from": "2026-01-01T00:00:00.000000Z",
"valid_to": null,
"created_at": "2025-12-18T10:00:00.000000Z",
"updated_at": "2025-12-18T10:00:00.000000Z"
}
}Path parameters
employeestring(uuid)requiredThe employee id.
Request body
application/json · required
weekdayintegerrequiredISO weekday: 1 = Monday … 7 = Sunday.
1–7
start_timestringrequiredStart,
HH:MM(orHH:MM:SS; seconds are dropped), in Swedish local time (Europe/Stockholm). Job times are converted to that clock before they are compared, so07:00means seven in the morning in Sweden, summer and winter.pattern ^\d{2}:\d{2}(:\d{2})?$
end_timestringrequiredEnd, after the start (otherwise 422).
pattern ^\d{2}:\d{2}(:\d{2})?$
valid_fromstring(date)nullableFirst day the rule applies, or null for always. Calendar date,
YYYY-MM-DD.valid_tostring(date)nullableLast day the rule applies, or null for open-ended; not before
valid_from. Calendar date,YYYY-MM-DD.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataobjectrequiredHours an employee normally works on one weekday. Several rules on one day are allowed (a split shift around lunch). An employee with no rules at all is treated as always available.
idstring(uuid)requiredThe rule id.
organization_idstring(uuid)requiredYour organization.
employee_idstring(uuid)requiredThe employee.
weekdayintegerrequiredISO weekday: 1 = Monday … 7 = Sunday.
1–7
start_timestringrequiredStart,
HH:MM:SS, in Swedish local time (Europe/Stockholm). Job times, which are UTC instants, are converted to that clock — and to its weekday — before they are compared with the rule.end_timestringrequiredEnd,
HH:MM:SS, after the start.valid_fromstring(date-time)nullablerequiredFirst day the rule applies, as midnight UTC of that date (
2026-01-01T00:00:00.000000Z), or null for always. Only the date counts: it is matched against the job's date in Swedish time.valid_tostring(date-time)nullablerequiredLast day the rule applies (the whole day), as midnight UTC of that date, or null for open-ended. Only the date counts: it is matched against the job's date in Swedish time.
created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 422The request body or query failed validation.Errors
- 429The key has made more requests this minute than its limit allows.Errors
Change working hours
/employees/{employee}/availability/{rule}Changes the fields you send; the result is checked as a whole (sending only end_time still has to end after the stored start). A rule of another employee is a 404.
curl -X PATCH 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40/availability/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"end_time": "11:00"
}'{
"data": {
"id": "01a15b91-2a3b-7c4d-8e5f-60718293a4b5",
"organization_id": "01a14eb3-c5f0-7c55-8c2e-6a0e1f7b9d21",
"employee_id": "01a15b90-1f2e-7a3b-8c4d-5e6f7a8b9c01",
"weekday": 1,
"start_time": "07:00:00",
"end_time": "11:00:00",
"valid_from": "2026-01-01T00:00:00.000000Z",
"valid_to": null,
"created_at": "2025-12-18T10:00:00.000000Z",
"updated_at": "2025-12-18T10:00:00.000000Z"
}
}Path parameters
employeestring(uuid)requiredThe employee id.
rulestring(uuid)requiredThe availability rule id.
Request body
application/json · required
weekdayintegerISO weekday: 1 = Monday … 7 = Sunday.
1–7
start_timestringStart,
HH:MM(orHH:MM:SS; seconds are dropped), in Swedish local time (Europe/Stockholm). Job times are converted to that clock before they are compared, so07:00means seven in the morning in Sweden, summer and winter.pattern ^\d{2}:\d{2}(:\d{2})?$
end_timestringEnd, after the start (otherwise 422).
pattern ^\d{2}:\d{2}(:\d{2})?$
valid_fromstring(date)nullableFirst day the rule applies, or null for always. Calendar date,
YYYY-MM-DD.valid_tostring(date)nullableLast day the rule applies, or null for open-ended; not before
valid_from. Calendar date,YYYY-MM-DD.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataobjectrequiredHours an employee normally works on one weekday. Several rules on one day are allowed (a split shift around lunch). An employee with no rules at all is treated as always available.
idstring(uuid)requiredThe rule id.
organization_idstring(uuid)requiredYour organization.
employee_idstring(uuid)requiredThe employee.
weekdayintegerrequiredISO weekday: 1 = Monday … 7 = Sunday.
1–7
start_timestringrequiredStart,
HH:MM:SS, in Swedish local time (Europe/Stockholm). Job times, which are UTC instants, are converted to that clock — and to its weekday — before they are compared with the rule.end_timestringrequiredEnd,
HH:MM:SS, after the start.valid_fromstring(date-time)nullablerequiredFirst day the rule applies, as midnight UTC of that date (
2026-01-01T00:00:00.000000Z), or null for always. Only the date counts: it is matched against the job's date in Swedish time.valid_tostring(date-time)nullablerequiredLast day the rule applies (the whole day), as midnight UTC of that date, or null for open-ended. Only the date counts: it is matched against the job's date in Swedish time.
created_atstring(date-time)requiredISO 8601 date-time, in UTC.
updated_atstring(date-time)requiredISO 8601 date-time, in UTC.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 422The request body or query failed validation.Errors
- 429The key has made more requests this minute than its limit allows.Errors
Remove working hours
/employees/{employee}/availability/{rule}Deletes the rule. An employee left with no rules is treated as always available.
curl -X DELETE 'https://api.closepact.com/v1/api/employees/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40/availability/01a14f2c-7c1e-7d0b-9a3e-3f5b2c8d1e40' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY"{
"deleted": true
}Path parameters
employeestring(uuid)requiredThe employee id.
rulestring(uuid)requiredThe availability rule id.
Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
deletedbooleanrequiredOne of
true
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 404No such record in this organization.Errors
- 429The key has made more requests this minute than its limit allows.Errors
List skills
/skillsThe organization's competences, by name — the ids to use in skill_ids on employees and services, and in filter[skill_id]. The whole list, not a page. Skills are managed in the panel.
curl 'https://api.closepact.com/v1/api/skills' \
-H "Authorization: Bearer $CLOSEPACT_API_KEY"{
"data": [
{
"id": "01a15b70-7c8e-7f00-b1c2-d3e4f5061728",
"name": "Fönsterputs",
"slug": "fonsterputs",
"color": "#56CCF2"
},
{
"id": "01a15b70-7c8d-7e9f-a0b1-c2d3e4f50617",
"name": "Storstädning",
"slug": "storstadning",
"color": "#27AE60"
}
]
}Responses
Headers
X-RateLimit-Limit— Requests this key may make per minute.X-RateLimit-Remaining— Requests left in the current minute.
dataarray of objectsrequiredidstring(uuid)requiredThe skill id, for
skill_idson employees and services.namestringrequiredName, e.g. "Storstädning".
slugstringrequiredURL-friendly name, unique in the organization.
colorstringnullablerequiredColour, or null.
- 401No key, or the key is invalid, revoked or expired, or its creator no longer has access.Errors
- 402The organization has not bought the module this endpoint belongs to, or it has lapsed to read-only, or its tier does not include what the operation needs:Errors
featurenames the capability (the operation'sx-feature) andrequired_tierthe cheapest tier that grants it. Every operation answers this with"feature": "core.api"when no module the organization holds is on a tier that includes the API. - 403The key lacks the scope, or the member it acts as lacks the permission or holds no seat in the module (Errors
module_seat_required— an administrator assigns seats under Settings → Users), or the organization is suspended. - 429The key has made more requests this minute than its limit allows.Errors