Developers
eTime API Read rosters, shifts, people and leave from your own scripts, spreadsheets and tools, and make changes the same way managers do in the app. Every change is checked against the same rules.
Base URL https://api.etime.my/v1/api
Auth Authorization: Bearer etk_…
Format JSON over HTTPS On this page Getting started Make a key. In eTime, open Account → API keys and choose Create a key . Copy it straight away: it is shown once.Keep it secret. Put it in an environment variable, such as ETIME_KEY, not in your code.Call the API with the key in the Authorization header.API keys A key acts as you : with your role, in your units, in the workplace you made it in. It sees exactly what you see in the app. People without pay access never get pay figures, and in ID mode names are left out.
Read Look at rosters, people, leave and offers. A read key can never change anything, whatever your role.
Read and write Also change shifts, answer offers and ask for leave, as far as your role allows. Endpoints that change things are marked Read-and-write key .
Keys start with etk_live_. eTime keeps only a fingerprint of each key, so a lost key can't be shown again: revoke it and make a new one. Owners and admins can see and revoke every key in the workplace.
Your first call Ask who the key acts as:
Shell Copy
curl https://api.etime.my/v1/api/me \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"userId" : "usr_hanne" ,
"name" : "Hanne Vik" ,
"memberId" : "mem_hanne" ,
"orgId" : "org_solbakken" ,
"role" : "owner" ,
"personId" : null ,
"can" : [
"roster.read" ,
"roster.edit" ,
"roster.publish" ,
"pay.read" ,
"people.read"
] ,
"hasPasskey" : false
} The same from JavaScript:
JavaScript Copy
const res = await fetch ("https://api.etime.my/v1/api/rosters?unitId=unt_ward3b" , {
headers : { Authorization : `Bearer ${process.env.ETIME_KEY}` },
});
if (!res.ok ) throw new Error ((await res.json ()).message );
const rosters = await res.json ();Making changes Roster changes are operations on a version. Read the roster first and send its version as baseVersion. eTime checks the change against labour law, the agreement and your house rules; one that breaks a hard rule comes back with "ok": false and the reasons in plain words, and nothing is saved. Send your own clientOpId so a retry never applies a change twice.
Shell Copy
curl -X POST https://api.etime.my/v1/api/rosters/ros_8f3k2a/operations \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"baseVersion": 12,
"op": { "kind": "assign", "slotId": "slt_night_20261105_nurse_1", "personId": "per_ingrid" },
"clientOpId": "my-script-2026-11-05-001"
}' Everyone watching the roster in the app sees the change at once, and it shows in the roster's history as made by you.
Errors Errors use HTTP status codes and always have the same JSON body. The message is plain English you can show to people.
Response · 403 Copy
{
"defined" : false ,
"code" : "FORBIDDEN" ,
"status" : 403 ,
"message" : "This API key can only read. Make a key with \"Read and write\" access to change things."
} Status Code Meaning 400BAD_REQUESTSomething in the request is wrong, or the change would break a rule. The message says what. 401UNAUTHORIZEDNo key, or the key is unknown, revoked or expired. 403FORBIDDENYour role can't do this, the unit is outside your access, or the key can only read. 404NOT_FOUNDNo such endpoint, or nothing with that id in your workplace. 429TOO_MANY_REQUESTSOver the rate limit. Wait the number of seconds in Retry-After.
Rate limits Each key may make 120 requests a minute . Over that, you get 429 with a Retry-After header in seconds. Wait that long and try again. Too many unknown keys from one address are also slowed down.
Versioning The version is in the path: /v1. Within v1 we only add things: new endpoints, new optional inputs and new fields in answers, so ignore fields you don't know. Anything that would break your code comes as /v2, announced well ahead, with v1 kept running for a good while.
Browsers and CORS The API answers requests from any website, but only with an API key: sign-in cookies are never used for requests from other sites. Don't put a key in a public web page; anyone could copy it. Call the API from a server or a script instead.
Reference · 41 endpoints
Account Who the key acts as.
The member the key acts as: role, workplace, and what that role may do.
Response userIdstring required
namestring required
memberIdstring required
orgIdstring required
role"owner" | "admin" | "scheduler" | "manager" | "employee" | "viewer" | "payroll" | "representative" required
personIdstring or null required
canarray of "roster.read" | "roster.edit" | "roster.publish" | "pay.read" | "people.read" | "people.edit" | "roles.edit" | "rules.edit" | "members.manage" | "billing.manage" | "budget.edit" | "settings.manage" | "audit.read" | "overview.read" required
hasPasskeyboolean required
Request Copy
curl "https://api.etime.my/v1/api/me" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"userId" : "abc_123" ,
"name" : "Ward 3B" ,
"memberId" : "mem_hanne" ,
"orgId" : "org_solbakken" ,
"role" : "owner" ,
"personId" : "per_ingrid" ,
"can" : [
"roster.read"
] ,
"hasPasskey" : false
} Which modes are on and what staff are shown.
Request Copy
curl "https://api.etime.my/v1/api/settings/me" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"orgId" : "org_solbakken" ,
"orgName" : "Ward 3B" ,
"role" : "owner" ,
"modes" : {
"meetings" : false ,
"timeTracking" : false ,
"homeVisits" : false
} ,
"transparency" : {
"ownPay" : false ,
"ownFairness" : false ,
"whyPicked" : false ,
"rosterReasons" : false
} ,
"canManage" : false
} Units Sites and units.
Request Copy
curl "https://api.etime.my/v1/api/units" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"sites" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B" ,
"timeZone" : "string" ,
"archived" : false
}
] ,
"units" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B" ,
"siteId" : "sit_solbakken" ,
"people" : 1 ,
"archived" : false
}
] ,
"siteLimit" : 1 ,
"plan" : "string" ,
"canManage" : false
} Rosters Roster periods, shifts, assignments and versions.
Roster periods of the units you can see, oldest first. Filter by unit with unitId.
Parameters unitIdstring query
3–120 characters
Response idstring required
3–120 characters
unitIdstring required
3–120 characters
periodStartstring required
periodEndstring required
status"draft" | "proposed" | "published" | "locked" required
versioninteger required
publishedVersioninteger or null required
Request Copy
curl "https://api.etime.my/v1/api/rosters" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
[
{
"id" : "abc_123" ,
"unitId" : "unt_ward3b" ,
"periodStart" : "2026-11-05" ,
"periodEnd" : "2026-11-05" ,
"status" : "draft" ,
"version" : 12 ,
"publishedVersion" : 12
}
] GET /rosters/{rosterId}Read key The roster with every shift, slot and assignment, as the rule engine sees it, plus display names. Pay, absence reasons and colleagues' preferences are removed unless your role may see pay.
Request Copy
curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"roster" : {
"id" : "abc_123" ,
"unitId" : "unt_ward3b" ,
"periodStart" : "2026-11-05" ,
"periodEnd" : "2026-11-05" ,
"status" : "draft" ,
"version" : 12 ,
"publishedVersion" : 12
} ,
"snapshot" : null ,
"names" : { } ,
"me" : {
"userId" : "abc_123" ,
"name" : "Ward 3B" ,
"memberId" : "mem_hanne" ,
"orgId" : "org_solbakken" ,
"role" : "owner" ,
"personId" : "per_ingrid" ,
"can" : [
"roster.read"
] ,
"hasPasskey" : false
} ,
"catalog" : {
"roles" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
] ,
"qualifications" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
]
} ,
"unitName" : "Ward 3B"
} GET /rosters/{rosterId}/versionsRead key Parameters Response versionsarray of object required Request Copy
curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/versions" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"versions" : [
{
"version" : 12 ,
"publishedAt" : "2026-11-05T05:50:00.000Z" ,
"publishedBy" : "string" ,
"filled" : 1 ,
"open" : 1 ,
"current" : false
}
]
} GET /rosters/{rosterId}/versions/{version}Read key Who was on which slot in that version.
Request Copy
curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/versions/12" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"version" : 12 ,
"assignments" : { }
} Parameters unitIdstring query
3–120 characters
Response rotationsarray of object required Request Copy
curl "https://api.etime.my/v1/api/rotations" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"rotations" : [
{
"id" : "abc_123" ,
"unitId" : "unt_ward3b" ,
"name" : "Ward 3B" ,
"weeks" : 1 ,
"anchor" : "2026-11-05" ,
"pattern" : [
"string"
]
}
]
} Parameters Response typesarray of object required fromstring required
tzstring required
Request Copy
curl "https://api.etime.my/v1/api/shift-types?unitId=unt_ward3b" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"types" : [
{
"key" : "string" ,
"name" : "Ward 3B" ,
"start" : "2026-11-05" ,
"end" : "2026-11-05" ,
"breakMinutes" : 1 ,
"paidBreak" : false
}
] ,
"from" : "2026-11-05" ,
"tz" : "string"
} POST /rosters/{rosterId}/operationsRead-and-write key Assign or unassign people. Send the roster's current version as baseVersion; the change is checked against every rule and refused with plain reasons when it breaks one. Retrying with the same clientOpId is safe.
Parameters Body Response One of these shapes:
ok: true ok: false okfalse required
versioninteger required
reasonstring required
violationsarray of object required ruleKeystring required
personIdstring required
messagestring required
Request Copy
curl -X POST "https://api.etime.my/v1/api/rosters/ros_8f3k2a/operations" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"baseVersion": 12,
"op": {
"kind": "assign",
"slotId": "slt_night_20261105_nurse_1",
"personId": "per_ingrid"
},
"clientOpId": "abc_123"
}' Response · 200 Copy
{
"ok" : true ,
"version" : 12 ,
"eventIds" : [
"string"
]
} POST /rosters/{rosterId}/publishRead-and-write key Publish the roster at version. Staff are told.
Parameters Body Response One of these shapes:
ok: true ok: false okfalse required
versioninteger required
reasonstring required
violationsarray of object required ruleKeystring required
personIdstring required
messagestring required
Request Copy
curl -X POST "https://api.etime.my/v1/api/rosters/ros_8f3k2a/publish" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"version": 12
}' Response · 200 Copy
{
"ok" : true ,
"version" : 12 ,
"eventIds" : [
"string"
]
} People People and job roles.
Names are left out in ID mode; pay is left out unless your role may see pay.
Response orgNamestring required
idModeboolean required
currencystring required
unitsarray of object required idstring required
namestring required
catalogobject required rolesarray of object required idstring required
namestring required
qualificationsarray of object required idstring required
namestring required
peoplearray of object required idstring required
3–120 characters
aliasstring required
payrollIdstring or null required
namestring or null required
status"active" | "onboarding" | "inactive" required
employment"employee" | "contractor" | "temp" | "agency" | "on_call" required
rolesarray of string required
tagsarray of string required
homeUnitIdsarray of string required
contractobject or null required qualificationsarray of object required accountobject or null required inviteobject or null required idstring required
3–120 characters
expiresAtstring required
emailedboolean required
Request Copy
curl "https://api.etime.my/v1/api/people" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"orgName" : "Ward 3B" ,
"idMode" : false ,
"currency" : "NOK" ,
"units" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
] ,
"catalog" : {
"roles" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
] ,
"qualifications" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
]
} ,
"people" : [
{
"id" : "abc_123" ,
"alias" : "string" ,
"payrollId" : "abc_123" ,
"name" : "Ward 3B" ,
"status" : "active" ,
"employment" : "employee"
}
]
} Response orgNamestring required
idModeboolean required
currencystring required
countrystring required
rolesarray of object required idstring required
3–120 characters
namestring required
payobject or null required hourlyinteger or null required
gradestring or null required
hoursPerWeeknumber or null required
qualificationsarray of string required
peopleinteger required
placesinteger required
qualificationsarray of object required idstring required
namestring required
Request Copy
curl "https://api.etime.my/v1/api/roles" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"orgName" : "Ward 3B" ,
"idMode" : false ,
"currency" : "NOK" ,
"country" : "string" ,
"roles" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B" ,
"pay" : {
"per" : "hour" ,
"amount" : 1
} ,
"hourly" : 1 ,
"grade" : "string" ,
"hoursPerWeek" : 1
}
] ,
"qualifications" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
]
} POST /peopleRead-and-write key Body aliasstring
1–40 characters
payrollIdstring
up to 40 characters
givenNamestring
1–80 characters
familyNamestring
up to 80 characters
rolesarray of string required
employment"employee" | "contractor" | "temp" | "agency" | "on_call" required
homeUnitIdstring required
3–120 characters
homeUnitIdsarray of string
tagsarray of string
contractobject required qualificationsarray of string required
Response idstring required
3–120 characters
Request Copy
curl -X POST "https://api.etime.my/v1/api/people" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"alias": "string",
"payrollId": "abc_123",
"givenName": "Ward 3B",
"familyName": "Ward 3B",
"roles": [
"string"
],
"employment": "employee",
"homeUnitId": "abc_123",
"homeUnitIds": [
"string"
],
"tags": [
"string"
],
"contract": {
"hoursPerWeek": 1,
"baseRate": 1,
"rateMultiplier": 1,
"validFrom": "string"
},
"qualifications": [
"string"
]
}' Response · 200 Copy
{
"id" : "abc_123"
} PATCH /people/{id}Read-and-write key Parameters idstring path required
3–120 characters
Body aliasstring
1–40 characters
payrollIdstring
up to 40 characters
givenNamestring
1–80 characters
familyNamestring
up to 80 characters
rolesarray of string
employment"employee" | "contractor" | "temp" | "agency" | "on_call"
status"active" | "onboarding" | "inactive"
homeUnitIdstring
3–120 characters
homeUnitIdsarray of string
tagsarray of string
contractobject qualificationsarray of string
Response idstring required
3–120 characters
Request Copy
curl -X PATCH "https://api.etime.my/v1/api/people/abc_123" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"alias": "string",
"payrollId": "abc_123",
"givenName": "Ward 3B",
"familyName": "Ward 3B",
"roles": [
"string"
],
"employment": "employee",
"status": "active",
"homeUnitId": "abc_123",
"homeUnitIds": [
"string"
],
"tags": [
"string"
],
"contract": {
"hoursPerWeek": 1,
"baseRate": 1,
"rateMultiplier": 1,
"validFrom": "string"
},
"qualifications": [
"string"
]
}' Response · 200 Copy
{
"id" : "abc_123"
} Rules Labour law, agreement and house rules.
Response orgNamestring required
countrystring required
idModeboolean required
packsarray of object required idstring required
keystring required
namestring required
kind"jurisdiction" | "agreement" | "org" | "local" | "ai_discovered" required
versionstring required
provenancestring required
notModelledarray of string required
notestring or null required
rulesarray of object required keystring required
kindstring required
familystring required
severity"hard" | "soft" required
titlestring required
summarystring required
citationsarray of object required sourcestring required
titlestring required
urlstring
refstring
paramsmap of any required
confidence"high" | "medium" | "low"
provenancestring
status"applies" | "overruled" required
notestring or null required
appliesTostring or null required
houseboolean required
houseTypestring or null required
houseValuenumber or null required
Request Copy
curl "https://api.etime.my/v1/api/rules" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"orgName" : "Ward 3B" ,
"country" : "string" ,
"idMode" : false ,
"packs" : [
{
"id" : "abc_123" ,
"key" : "string" ,
"name" : "Ward 3B" ,
"kind" : "jurisdiction" ,
"version" : "string" ,
"provenance" : "string"
}
]
} Shift offers Open shifts offered to staff.
GET /rosters/{rosterId}/calloutsRead key Parameters Response idstring required
3–120 characters
rosterIdstring required
3–120 characters
slotIdstring required
3–120 characters
reason"sick" | "absence" | "new_demand" | "unfilled" | "swap_failed" required
policy"employer_picks" | "first_eligible_wins" | "auto_pick_best" required
status"open" | "filled" | "expired" | "cancelled" required
createdAtstring required
filledBystring or null required
replacesstring or null required
audienceCountinteger or null required
responsesarray of object required personIdstring required
answer"accept" | "decline" required
respondedAtstring required
eligibleboolean required
rankinteger required
costobject required amountinteger required
currencystring required
3–3 characters
reasonsarray of string required
blockedstring or null required
beststring or null required
mineobject or null required Request Copy
curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/callouts" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
[
{
"id" : "abc_123" ,
"rosterId" : "ros_8f3k2a" ,
"slotId" : "slt_night_20261105_nurse_1" ,
"reason" : "sick" ,
"policy" : "employer_picks" ,
"status" : "open" ,
"createdAt" : "2026-11-05T05:50:00.000Z" ,
"filledBy" : "string" ,
"replaces" : "string" ,
"audienceCount" : 1 ,
"responses" : [
{
"personId" : "per_ingrid" ,
"answer" : "accept" ,
"respondedAt" : "2026-11-05T05:50:00.000Z" ,
"eligible" : false ,
"rank" : 1 ,
"cost" : {
"amount" : 1 ,
"currency" : "NOK"
}
}
] ,
"best" : "string" ,
"mine" : {
"answer" : "accept" ,
"eligible" : false ,
"blocked" : "string" ,
"pay" : {
"amount" : 1 ,
"currency" : "NOK"
} ,
"weekHours" : 1 ,
"result" : {
"picked" : false ,
"why" : "string"
}
}
}
] POST /calloutsRead-and-write key Offer an open slot to the people who can take it. They are told by push and email.
Body rosterIdstring required
3–120 characters
slotIdstring required
3–120 characters
Response idstring required
3–120 characters
offeredTointeger required
Request Copy
curl -X POST "https://api.etime.my/v1/api/callouts" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"rosterId": "ros_8f3k2a",
"slotId": "slt_night_20261105_nurse_1"
}' Response · 200 Copy
{
"id" : "abc_123" ,
"offeredTo" : 1
} POST /callouts/{calloutId}/cancelRead-and-write key Request Copy
curl -X POST "https://api.etime.my/v1/api/callouts/cal_2m9x7q/cancel" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"ok" : true
} POST /callouts/{calloutId}/pickRead-and-write key Parameters Body personIdstring required
3–120 characters
Response Request Copy
curl -X POST "https://api.etime.my/v1/api/callouts/cal_2m9x7q/pick" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"personId": "per_ingrid"
}' Response · 200 Copy
{
"ok" : true
} POST /callouts/{calloutId}/respondRead-and-write key Request Copy
curl -X POST "https://api.etime.my/v1/api/callouts/cal_2m9x7q/respond" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"answer": "accept"
}' Response · 200 Copy
{
"picked" : false
} Swaps Shift swaps between staff.
Request Copy
curl "https://api.etime.my/v1/api/swaps" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"swaps" : [
{
"id" : "abc_123" ,
"rosterId" : "ros_8f3k2a" ,
"unitId" : "unt_ward3b" ,
"kind" : "exchange" ,
"status" : "asked" ,
"fromPersonId" : "abc_123"
}
] ,
"policy" : "manager"
} POST /swaps/optionsRead key Body slotIdstring required
3–120 characters
Response Request Copy
curl -X POST "https://api.etime.my/v1/api/swaps/options" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"slotId": "slt_night_20261105_nurse_1"
}' Response · 200 Copy
{
"exchange" : [
{
"personId" : "per_ingrid" ,
"with" : {
"slotId" : "slt_night_20261105_nurse_1" ,
"shiftId" : "shf_night_20261105" ,
"name" : "Ward 3B" ,
"startsAt" : "2026-11-05T05:50:00.000Z" ,
"endsAt" : "2026-11-05T05:50:00.000Z"
} ,
"costDelta" : {
"amount" : 1 ,
"currency" : "NOK"
}
}
] ,
"takers" : 1 ,
"policy" : "manager"
} Request Copy
curl "https://api.etime.my/v1/api/swaps/policy" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"policy" : "manager"
} POST /swapsRead-and-write key Body slotIdstring required
3–120 characters
withSlotIdstring
3–120 characters
Response Request Copy
curl -X POST "https://api.etime.my/v1/api/swaps" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"slotId": "slt_night_20261105_nurse_1",
"withSlotId": "abc_123"
}' Response · 200 Copy
{
"id" : "abc_123" ,
"status" : "asked"
} POST /swaps/{id}/answerRead-and-write key Parameters idstring path required
3–120 characters
Body Response Request Copy
curl -X POST "https://api.etime.my/v1/api/swaps/abc_123/answer" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"answer": "accept"
}' Response · 200 Copy
{
"id" : "abc_123" ,
"status" : "asked"
} POST /swaps/{id}/cancelRead-and-write key Parameters idstring path required
3–120 characters
Response Request Copy
curl -X POST "https://api.etime.my/v1/api/swaps/abc_123/cancel" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"id" : "abc_123" ,
"status" : "asked"
} POST /swaps/{id}/decideRead-and-write key Parameters idstring path required
3–120 characters
Body Response Request Copy
curl -X POST "https://api.etime.my/v1/api/swaps/abc_123/decide" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "approve"
}' Response · 200 Copy
{
"id" : "abc_123" ,
"status" : "asked"
} Leave and absence Sickness, leave and summer holidays.
GET /holiday-roundsRead key Response roundsarray of object required idstring required
unitIdstring required
yearinteger required
periodFromstring required
a date, YYYY-MM-DD
periodTostring required
a date, YYYY-MM-DD
weeksinteger required
peakFromstring required
a date, YYYY-MM-DD
peakTostring required
a date, YYYY-MM-DD
closesOnstring required
a date, YYYY-MM-DD
capacitymap of integer required
status"open" | "allocated" | "published" required
versioninteger required
startsarray of string required
peakStartsarray of string required
wishCountinteger required
myWishesarray of object required rankinteger required
1–3
startstring required
a date, YYYY-MM-DD
mineobject or null required personIdstring required
startstring or null required
a date, YYYY-MM-DD
endstring or null required
a date, YYYY-MM-DD
wishRankinteger or null required
reason"wish" | "nearest" | "no_wishes" | "no_room" | "not_eligible" | "manager" required
priorityinteger required
peakLastYearinteger required
peakWeeksinteger required
firstWishTakenByinteger required
peoplearray of object or null required personIdstring required
groupstring required
wishesarray of object required rankinteger required
1–3
startstring required
a date, YYYY-MM-DD
allocationobject or null required personIdstring required
startstring or null required
a date, YYYY-MM-DD
endstring or null required
a date, YYYY-MM-DD
wishRankinteger or null required
reason"wish" | "nearest" | "no_wishes" | "no_room" | "not_eligible" | "manager" required
priorityinteger required
peakLastYearinteger required
peakWeeksinteger required
firstWishTakenByinteger required
Request Copy
curl "https://api.etime.my/v1/api/holiday-rounds" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"rounds" : [
{
"id" : "abc_123" ,
"unitId" : "unt_ward3b" ,
"year" : 2026 ,
"periodFrom" : "2026-11-05" ,
"periodTo" : "2026-11-05" ,
"weeks" : 1
}
]
} Your requests and balance; for people who run the roster, also the team's and the inbox.
Parameters yearinteger query
2020–2100
Response Request Copy
curl "https://api.etime.my/v1/api/leave" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"tz" : "string" ,
"today" : "2026-11-05" ,
"year" : 2026 ,
"idMode" : false ,
"orgName" : "Ward 3B" ,
"jurisdiction" : "string" ,
"names" : { } ,
"people" : [
{
"id" : "abc_123" ,
"alias" : "string" ,
"roles" : [
"string"
]
}
] ,
"roles" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
] ,
"units" : [
{
"id" : "abc_123" ,
"name" : "Ward 3B"
}
] ,
"rules" : {
"entitlement" : {
"title" : "string" ,
"summary" : "string" ,
"citations" : [
{
"title" : "string" ,
"url" : "string"
}
]
} ,
"blocks" : {
"title" : "string" ,
"summary" : "string" ,
"citations" : [
{
"title" : "string" ,
"url" : "string"
}
]
} ,
"dayCount" : "mon_sat_no_holidays"
} ,
"mine" : {
"requests" : [
{
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"type" : "sick" ,
"status" : "requested" ,
"from" : "2026-11-05" ,
"to" : "2026-11-05"
}
] ,
"balance" : {
"personId" : "per_ingrid" ,
"alias" : "string" ,
"vacation" : {
"entitled" : 1 ,
"accrued" : 1 ,
"why" : "full" ,
"adjusted" : 1 ,
"used" : 1 ,
"planned" : 1
} ,
"compTime" : {
"earned" : 1 ,
"used" : 1 ,
"left" : 1
} ,
"flex" : {
"hours" : 1
}
}
} ,
"inbox" : [
{
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"type" : "sick" ,
"status" : "requested" ,
"from" : "2026-11-05" ,
"to" : "2026-11-05"
}
] ,
"team" : [
{
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"type" : "sick" ,
"status" : "requested" ,
"from" : "2026-11-05" ,
"to" : "2026-11-05"
}
]
} GET /leave/{id}/impactRead key Parameters idstring path required
3–120 characters
Response Request Copy
curl "https://api.etime.my/v1/api/leave/abc_123/impact" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"leaveId" : "abc_123" ,
"shifts" : [
{
"shiftId" : "shf_night_20261105" ,
"slotId" : "slt_night_20261105_nurse_1" ,
"rosterId" : "ros_8f3k2a" ,
"name" : "Ward 3B" ,
"startsAt" : "2026-11-05T05:50:00.000Z" ,
"endsAt" : "2026-11-05T05:50:00.000Z"
}
] ,
"uncovered" : 1 ,
"costChange" : {
"amount" : 1 ,
"currency" : "NOK"
} ,
"rosteredUntil" : "2026-11-05" ,
"partial" : false ,
"balance" : {
"left" : 1 ,
"after" : 1
} ,
"backfill" : {
"weeks" : [
{
"start" : "2026-11-05" ,
"openMin" : 1 ,
"helperMin" : 1 ,
"tempMin" : 1 ,
"source" : "roster"
}
] ,
"helpers" : [
{
"personId" : "per_ingrid" ,
"minPerWeek" : 1 ,
"spareMinPerWeek" : 1
}
] ,
"totals" : {
"openMin" : 1 ,
"helperMin" : 1 ,
"tempMin" : 1 ,
"helperCost" : {
"amount" : 1 ,
"currency" : "NOK"
} ,
"tempCost" : {
"amount" : 1 ,
"currency" : "NOK"
} ,
"overtimeCost" : {
"amount" : 1 ,
"currency" : "NOK"
}
} ,
"tempFte" : 1 ,
"fullTimeMinPerWeek" : 1
}
} POST /absences/sickRead-and-write key Report yourself (or, if you run the unit, someone else) sick. Their shifts are offered to others.
Body personIdstring
3–120 characters
untilstring required
a date, YYYY-MM-DD
Response absenceIdstring required
3–120 characters
vacatedinteger required
offeredTointeger required
Request Copy
curl -X POST "https://api.etime.my/v1/api/absences/sick" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"personId": "per_ingrid",
"until": "2026-11-05"
}' Response · 200 Copy
{
"absenceId" : "abc_123" ,
"vacated" : 1 ,
"offeredTo" : 1
} POST /leaveRead-and-write key Body Response idstring required
personIdstring required
type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other" required
status"requested" | "approved" | "rejected" | "cancelled" required
fromstring required
a date, YYYY-MM-DD
tostring required
a date, YYYY-MM-DD
partialPercentinteger or null required
daysnumber required
requestedAtstring or null required
decidedAtstring or null required
versioninteger required
Request Copy
curl -X POST "https://api.etime.my/v1/api/leave" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"personId": "per_ingrid",
"type": "sick",
"from": "2026-11-05",
"to": "2026-11-05",
"partialPercent": 10
}' Response · 200 Copy
{
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"type" : "sick" ,
"status" : "requested" ,
"from" : "2026-11-05" ,
"to" : "2026-11-05" ,
"partialPercent" : 1 ,
"days" : 1 ,
"requestedAt" : "2026-11-05T05:50:00.000Z" ,
"decidedAt" : "2026-11-05T05:50:00.000Z" ,
"version" : 12
} POST /leave/{id}/cancelRead-and-write key Parameters idstring path required
3–120 characters
Body Response idstring required
personIdstring required
type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other" required
status"requested" | "approved" | "rejected" | "cancelled" required
fromstring required
a date, YYYY-MM-DD
tostring required
a date, YYYY-MM-DD
partialPercentinteger or null required
daysnumber required
requestedAtstring or null required
decidedAtstring or null required
versioninteger required
Request Copy
curl -X POST "https://api.etime.my/v1/api/leave/abc_123/cancel" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"version": 12
}' Response · 200 Copy
{
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"type" : "sick" ,
"status" : "requested" ,
"from" : "2026-11-05" ,
"to" : "2026-11-05" ,
"partialPercent" : 1 ,
"days" : 1 ,
"requestedAt" : "2026-11-05T05:50:00.000Z" ,
"decidedAt" : "2026-11-05T05:50:00.000Z" ,
"version" : 12
} POST /leave/{id}/decideRead-and-write key Parameters idstring path required
3–120 characters
Body Response statusstring required
vacatedinteger required
offeredTointeger required
Request Copy
curl -X POST "https://api.etime.my/v1/api/leave/abc_123/decide" \
-H "Authorization: Bearer $ETIME_KEY" \
-H "Content-Type: application/json" \
-d '{
"version": 12,
"decision": "approve",
"sendCallouts": false
}' Response · 200 Copy
{
"status" : "string" ,
"vacated" : 1 ,
"offeredTo" : 1
} Time Planned and worked hours.
GET /rosters/{rosterId}/workedRead key Parameters Response entriesarray of object required pendinginteger required
Request Copy
curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/worked" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"entries" : [
{
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"shiftId" : "shf_night_20261105" ,
"start" : "2026-11-05" ,
"end" : "2026-11-05" ,
"breakMinutes" : 1
}
] ,
"pending" : 1
} Response nowstring required
tzstring required
runningobject or null required idstring required
personIdstring required
shiftIdstring or null required
startedAtstring required
endedAtstring or null required
breakMinutesinteger required
source"app" | "kiosk" | "manager" required
status"open" | "submitted" | "approved" | "disputed" required
notestring or null required
versioninteger required
location"inside" | "outside" | "unchecked" or null
roundedobject or null startedAtstring required
endedAtstring required
shiftobject or null required recentarray of object required entryobject required idstring required
personIdstring required
shiftIdstring or null required
startedAtstring required
endedAtstring or null required
breakMinutesinteger required
source"app" | "kiosk" | "manager" required
status"open" | "submitted" | "approved" | "disputed" required
notestring or null required
versioninteger required
location"inside" | "outside" | "unchecked" or null
roundedobject or null startedAtstring required
endedAtstring required
shiftobject or null required locationCheckobject or null pinSetboolean
roundingobject Request Copy
curl "https://api.etime.my/v1/api/time/me" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"now" : "string" ,
"tz" : "string" ,
"running" : {
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"shiftId" : "shf_night_20261105" ,
"startedAt" : "2026-11-05T05:50:00.000Z" ,
"endedAt" : "2026-11-05T05:50:00.000Z" ,
"breakMinutes" : 1 ,
"source" : "app" ,
"status" : "open" ,
"note" : "Covering for Sam" ,
"version" : 12 ,
"location" : "inside" ,
"rounded" : {
"startedAt" : "2026-11-05T05:50:00.000Z" ,
"endedAt" : "2026-11-05T05:50:00.000Z"
}
} ,
"shift" : {
"shiftId" : "shf_night_20261105" ,
"name" : "Ward 3B" ,
"startsAt" : "2026-11-05T05:50:00.000Z" ,
"endsAt" : "2026-11-05T05:50:00.000Z" ,
"paidMin" : 1 ,
"unpaidBreakMin" : 1
} ,
"recent" : [
{
"entry" : {
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"shiftId" : "shf_night_20261105" ,
"startedAt" : "2026-11-05T05:50:00.000Z" ,
"endedAt" : "2026-11-05T05:50:00.000Z" ,
"breakMinutes" : 1
} ,
"shift" : {
"shiftId" : "shf_night_20261105" ,
"name" : "Ward 3B" ,
"startsAt" : "2026-11-05T05:50:00.000Z" ,
"endsAt" : "2026-11-05T05:50:00.000Z" ,
"paidMin" : 1 ,
"unpaidBreakMin" : 1
}
}
] ,
"locationCheck" : {
"outside" : "refuse"
} ,
"pinSet" : false ,
"rounding" : {
"stepMin" : 0 ,
"mode" : "nearest" ,
"graceMin" : 1
}
} Parameters fromstring query required
a date, YYYY-MM-DD
tostring query required
a date, YYYY-MM-DD
Response Request Copy
curl "https://api.etime.my/v1/api/time/team?from=2026-11-05&to=2026-11-05" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"from" : "2026-11-05" ,
"to" : "2026-11-05" ,
"tz" : "string" ,
"idMode" : false ,
"rows" : [
{
"personId" : "per_ingrid" ,
"alias" : "string" ,
"planned" : {
"shiftId" : "shf_night_20261105" ,
"name" : "Ward 3B" ,
"startsAt" : "2026-11-05T05:50:00.000Z" ,
"endsAt" : "2026-11-05T05:50:00.000Z" ,
"paidMin" : 1 ,
"unpaidBreakMin" : 1
} ,
"entry" : {
"id" : "abc_123" ,
"personId" : "per_ingrid" ,
"shiftId" : "shf_night_20261105" ,
"startedAt" : "2026-11-05T05:50:00.000Z" ,
"endedAt" : "2026-11-05T05:50:00.000Z" ,
"breakMinutes" : 1
}
}
] ,
"names" : { } ,
"people" : [
{
"id" : "abc_123" ,
"alias" : "string"
}
] ,
"costs" : [
{
"personId" : "per_ingrid" ,
"planned" : {
"amount" : 1 ,
"currency" : "NOK"
} ,
"worked" : {
"amount" : 1 ,
"currency" : "NOK"
}
}
]
} Meetings Meetings you are in.
Request Copy
curl "https://api.etime.my/v1/api/meetings" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"orgName" : "Ward 3B" ,
"idMode" : false ,
"tz" : "string" ,
"meetings" : [
{
"id" : "abc_123" ,
"title" : "string" ,
"startsAt" : "2026-11-05T05:50:00.000Z" ,
"endsAt" : "2026-11-05T05:50:00.000Z" ,
"location" : "string" ,
"organizerId" : "abc_123"
}
] ,
"names" : { } ,
"people" : [
{
"id" : "abc_123" ,
"alias" : "string"
}
]
} Insights Fairness and open problems.
Parameters Response periodobject required startstring required
endstring required
mineobject required nightsnumber required
weekendsnumber required
holidaysnumber required
thisPeriodobject required nightsnumber required
weekendsnumber required
holidaysnumber required
teamobject required nightsobject required averagenumber required
lownumber required
highnumber required
weekendsobject required averagenumber required
lownumber required
highnumber required
holidaysobject required averagenumber required
lownumber required
highnumber required
peopleinteger required
vsAverageobject required nightsnumber required
weekendsnumber required
holidaysnumber required
Request Copy
curl "https://api.etime.my/v1/api/fairness/me?rosterId=ros_8f3k2a" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"period" : {
"start" : "2026-11-05" ,
"end" : "2026-11-05"
} ,
"mine" : {
"nights" : 1 ,
"weekends" : 1 ,
"holidays" : 1
} ,
"thisPeriod" : {
"nights" : 1 ,
"weekends" : 1 ,
"holidays" : 1
} ,
"team" : {
"nights" : {
"average" : 1 ,
"low" : 1 ,
"high" : 1
} ,
"weekends" : {
"average" : 1 ,
"low" : 1 ,
"high" : 1
} ,
"holidays" : {
"average" : 1 ,
"low" : 1 ,
"high" : 1
} ,
"people" : 1
} ,
"vsAverage" : {
"nights" : 1 ,
"weekends" : 1 ,
"holidays" : 1
}
} GET /rosters/{rosterId}/healRead key Request Copy
curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/heal" \
-H "Authorization: Bearer $ETIME_KEY" Response · 200 Copy
{
"mode" : "suggest" ,
"canChange" : false ,
"recent" : [
{
"eventId" : "abc_123" ,
"at" : "string" ,
"version" : 12 ,
"changes" : [
{
"slotId" : "slt_night_20261105_nurse_1" ,
"personId" : "per_ingrid"
}
]
}
]
} Something unclear or missing? Email support@etime.my .