Skip to content
eTimeDocs

Try publish, must cover, kiosk or swap.

    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
    OpenAPI
    openapi.json · v1.0.0
    On this page

    Getting started

    1. Make a key. In eTime, open Account → API keys and choose Create a key. Copy it straight away: it is shown once.
    2. Keep it secret. Put it in an environment variable, such as ETIME_KEY, not in your code.
    3. 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
    curl https://api.etime.my/v1/api/me \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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
    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
    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
    {
      "defined": false,
      "code": "FORBIDDEN",
      "status": 403,
      "message": "This API key can only read. Make a key with \"Read and write\" access to change things."
    }
    StatusCodeMeaning
    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.

    GET/meRead key

    Who you are

    The member the key acts as: role, workplace, and what that role may do.

    Response

    • userIdstringrequired
    • namestringrequired
    • memberIdstringrequired
    • orgIdstringrequired
    • role"owner" | "admin" | "scheduler" | "manager" | "employee" | "viewer" | "payroll" | "representative"required
    • personIdstring or nullrequired
    • 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
    • hasPasskeybooleanrequired
    Request
    curl "https://api.etime.my/v1/api/me" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "userId": "abc_123",
      "name": "Ward 3B",
      "memberId": "mem_hanne",
      "orgId": "org_solbakken",
      "role": "owner",
      "personId": "per_ingrid",
      "can": [
        "roster.read"
      ],
      "hasPasskey": false
    }
    GET/settings/meRead key

    Your workplace settings

    Which modes are on and what staff are shown.

    Response

    • orgIdstringrequired
    • orgNamestringrequired
    • role"owner" | "admin" | "scheduler" | "manager" | "employee" | "viewer" | "payroll" | "representative"required
    • modesobjectrequired
      • meetingsbooleanrequired
      • timeTrackingbooleanrequired
      • homeVisitsbooleanrequired
    • transparencyobjectrequired
      • ownPaybooleanrequired
      • ownFairnessbooleanrequired
      • whyPickedbooleanrequired
      • rosterReasonsbooleanrequired
    • canManagebooleanrequired
    Request
    curl "https://api.etime.my/v1/api/settings/me" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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.

    GET/unitsRead key

    List sites and units you can see

    Response

    • sitesarray of objectrequired
      • idstringrequired
      • namestringrequired
      • timeZonestringrequired
      • archivedbooleanrequired
    • unitsarray of objectrequired
      • idstringrequired
      • namestringrequired
      • siteIdstringrequired
      • peopleintegerrequired
      • archivedbooleanrequired
    • siteLimitinteger or nullrequired
    • planstringrequired
    • canManagebooleanrequired
    Request
    curl "https://api.etime.my/v1/api/units" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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.

    GET/rostersRead key

    List rosters

    Roster periods of the units you can see, oldest first. Filter by unit with unitId.

    Parameters

    • unitIdstringquery

      3–120 characters

    Response

    • idstringrequired

      3–120 characters

    • unitIdstringrequired

      3–120 characters

    • periodStartstringrequired
    • periodEndstringrequired
    • status"draft" | "proposed" | "published" | "locked"required
    • versionintegerrequired
    • publishedVersioninteger or nullrequired
    Request
    curl "https://api.etime.my/v1/api/rosters" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    [
      {
        "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

    Get a roster

    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.

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    Response

    • rosterobjectrequired
      • idstringrequired

        3–120 characters

      • unitIdstringrequired

        3–120 characters

      • periodStartstringrequired
      • periodEndstringrequired
      • status"draft" | "proposed" | "published" | "locked"required
      • versionintegerrequired
      • publishedVersioninteger or nullrequired
    • snapshotanyrequired
    • namesmap of stringrequired
    • meobjectrequired
      • userIdstringrequired
      • namestringrequired
      • memberIdstringrequired
      • orgIdstringrequired
      • role"owner" | "admin" | "scheduler" | "manager" | "employee" | "viewer" | "payroll" | "representative"required
      • personIdstring or nullrequired
      • 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
      • hasPasskeybooleanrequired
    • catalogobjectrequired
      • rolesarray of objectrequired
        • idstringrequired
        • namestringrequired
      • qualificationsarray of objectrequired
        • idstringrequired
        • namestringrequired
    • unitNamestringrequired
    Request
    curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    List a roster's versions

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    Response

    • versionsarray of objectrequired
      • versionintegerrequired
      • publishedAtstring or nullrequired
      • publishedBystring or nullrequired
      • filledintegerrequired
      • openintegerrequired
      • currentbooleanrequired
      • storedbooleanrequired
    Request
    curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/versions" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    Get a roster version

    Who was on which slot in that version.

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    • versionintegerpathrequired

      at least 0

    Response

    • versionintegerrequired
    • assignmentsmap of stringrequired
    Request
    curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/versions/12" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "version": 12,
      "assignments": {}
    }
    GET/rotationsRead key

    List rotations

    Parameters

    • unitIdstringquery

      3–120 characters

    Response

    • rotationsarray of objectrequired
      • idstringrequired

        3–120 characters

      • unitIdstringrequired

        3–120 characters

      • namestringrequired
      • weeksintegerrequired
      • anchorstringrequired

        a date, YYYY-MM-DD

      • patternarray of string or nullrequired
      • membersarray of objectrequired
        • personIdstringrequired

          3–120 characters

        • offsetWeeksintegerrequired

          0–51

      • versionintegerrequired
    Request
    curl "https://api.etime.my/v1/api/rotations" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "rotations": [
        {
          "id": "abc_123",
          "unitId": "unt_ward3b",
          "name": "Ward 3B",
          "weeks": 1,
          "anchor": "2026-11-05",
          "pattern": [
            "string"
          ]
        }
      ]
    }
    GET/shift-typesRead key

    List a unit's shift types

    Parameters

    • unitIdstringqueryrequired

      3–120 characters

    Response

    • typesarray of objectrequired
      • keystringrequired
      • namestringrequired
      • startstringrequired
      • endstringrequired
      • breakMinutesintegerrequired
      • paidBreakbooleanrequired
      • daysarray of integerrequired
      • needsarray of objectrequired
        • roleIdstringrequired

          3–120 characters

        • countintegerrequired

          0–50

        • mustCoverboolean
      • upcomingintegerrequired
      • staffedintegerrequired
    • fromstringrequired
    • tzstringrequired
    Request
    curl "https://api.etime.my/v1/api/shift-types?unitId=unt_ward3b" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    Change a roster

    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

    • rosterIdstringpathrequired

      3–120 characters

    Body

    • baseVersionintegerrequired
    • opone of 3 shapesrequired
      • kind: "assign"
        • kind"assign"required
        • slotIdstringrequired

          3–120 characters

        • personIdstringrequired

          3–120 characters

        • overrideobject
          • reasonstringrequired

            at least 3 characters

      • kind: "unassign"
        • kind"unassign"required
        • slotIdstringrequired

          3–120 characters

      • kind: "bulk"
        • kind"bulk"required
        • changesarray of objectrequired
          • slotIdstringrequired

            3–120 characters

          • personIdstring or nullrequired

            3–120 characters

        • source"solver" | "swap" | "manual" | "ai_chat"required
        • overrideobject
          • reasonstringrequired

            at least 3 characters

    • clientOpIdstringrequired

      8–64 characters

    Response

    One of these shapes:

    • ok: true
      • oktruerequired
      • versionintegerrequired
      • eventIdsarray of stringrequired
    • ok: false
      • okfalserequired
      • versionintegerrequired
      • reasonstringrequired
      • violationsarray of objectrequired
        • ruleKeystringrequired
        • personIdstringrequired
        • messagestringrequired
    Request
    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
    {
      "ok": true,
      "version": 12,
      "eventIds": [
        "string"
      ]
    }
    POST/rosters/{rosterId}/publishRead-and-write key

    Publish a roster

    Publish the roster at version. Staff are told.

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    Body

    • versionintegerrequired

    Response

    One of these shapes:

    • ok: true
      • oktruerequired
      • versionintegerrequired
      • eventIdsarray of stringrequired
    • ok: false
      • okfalserequired
      • versionintegerrequired
      • reasonstringrequired
      • violationsarray of objectrequired
        • ruleKeystringrequired
        • personIdstringrequired
        • messagestringrequired
    Request
    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
    {
      "ok": true,
      "version": 12,
      "eventIds": [
        "string"
      ]
    }

    People

    People and job roles.

    GET/peopleRead key

    List people

    Names are left out in ID mode; pay is left out unless your role may see pay.

    Response

    • orgNamestringrequired
    • idModebooleanrequired
    • currencystringrequired
    • unitsarray of objectrequired
      • idstringrequired
      • namestringrequired
    • catalogobjectrequired
      • rolesarray of objectrequired
        • idstringrequired
        • namestringrequired
      • qualificationsarray of objectrequired
        • idstringrequired
        • namestringrequired
    • peoplearray of objectrequired
      • idstringrequired

        3–120 characters

      • aliasstringrequired
      • payrollIdstring or nullrequired
      • namestring or nullrequired
      • status"active" | "onboarding" | "inactive"required
      • employment"employee" | "contractor" | "temp" | "agency" | "on_call"required
      • rolesarray of stringrequired
      • tagsarray of stringrequired
      • homeUnitIdsarray of stringrequired
      • contractobject or nullrequired
        • validFromstringrequired
        • ftenumberrequired
        • hoursPerWeeknumberrequired
        • baseRateobject or nullrequired
          • amountintegerrequired
          • currencystringrequired

            3–3 characters

        • rateMultipliernumber or nullrequired
      • qualificationsarray of objectrequired
        • idstringrequired
        • validUntilstring or nullrequired
      • accountobject or nullrequired
        • role"owner" | "admin" | "scheduler" | "manager" | "employee" | "viewer" | "payroll" | "representative"required
        • hasPasskeybooleanrequired
      • inviteobject or nullrequired
        • idstringrequired

          3–120 characters

        • expiresAtstringrequired
        • emailedbooleanrequired
    Request
    curl "https://api.etime.my/v1/api/people" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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"
        }
      ]
    }
    GET/rolesRead key

    List job roles

    Response

    • orgNamestringrequired
    • idModebooleanrequired
    • currencystringrequired
    • countrystringrequired
    • rolesarray of objectrequired
      • idstringrequired

        3–120 characters

      • namestringrequired
      • payobject or nullrequired
        • per"hour" | "month"required
        • amountintegerrequired
      • hourlyinteger or nullrequired
      • gradestring or nullrequired
      • hoursPerWeeknumber or nullrequired
      • qualificationsarray of stringrequired
      • peopleintegerrequired
      • placesintegerrequired
    • qualificationsarray of objectrequired
      • idstringrequired
      • namestringrequired
    Request
    curl "https://api.etime.my/v1/api/roles" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    Add a person

    Body

    • aliasstring

      1–40 characters

    • payrollIdstring

      up to 40 characters

    • givenNamestring

      1–80 characters

    • familyNamestring

      up to 80 characters

    • rolesarray of stringrequired
    • employment"employee" | "contractor" | "temp" | "agency" | "on_call"required
    • homeUnitIdstringrequired

      3–120 characters

    • homeUnitIdsarray of string
    • tagsarray of string
    • contractobjectrequired
      • hoursPerWeeknumberrequired

        0–80

      • baseRateinteger

        at least 0

      • rateMultipliernumber

        0–10

      • validFromstring
    • qualificationsarray of stringrequired

    Response

    • idstringrequired

      3–120 characters

    Request
    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
    {
      "id": "abc_123"
    }
    PATCH/people/{id}Read-and-write key

    Change a person

    Parameters

    • idstringpathrequired

      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
      • hoursPerWeeknumberrequired

        0–80

      • baseRateinteger

        at least 0

      • rateMultipliernumber

        0–10

      • validFromstring
    • qualificationsarray of string

    Response

    • idstringrequired

      3–120 characters

    Request
    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
    {
      "id": "abc_123"
    }

    Rules

    Labour law, agreement and house rules.

    GET/rulesRead key

    List the rules you work under

    Response

    • orgNamestringrequired
    • countrystringrequired
    • idModebooleanrequired
    • packsarray of objectrequired
      • idstringrequired
      • keystringrequired
      • namestringrequired
      • kind"jurisdiction" | "agreement" | "org" | "local" | "ai_discovered"required
      • versionstringrequired
      • provenancestringrequired
      • notModelledarray of stringrequired
      • notestring or nullrequired
      • rulesarray of objectrequired
        • keystringrequired
        • kindstringrequired
        • familystringrequired
        • severity"hard" | "soft"required
        • titlestringrequired
        • summarystringrequired
        • citationsarray of objectrequired
          • sourcestringrequired
          • titlestringrequired
          • urlstring
          • refstring
        • paramsmap of anyrequired
        • confidence"high" | "medium" | "low"
        • provenancestring
        • status"applies" | "overruled"required
        • notestring or nullrequired
        • appliesTostring or nullrequired
        • housebooleanrequired
        • houseTypestring or nullrequired
        • houseValuenumber or nullrequired
    Request
    curl "https://api.etime.my/v1/api/rules" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    List a roster's shift offers

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    Response

    • idstringrequired

      3–120 characters

    • rosterIdstringrequired

      3–120 characters

    • slotIdstringrequired

      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
    • createdAtstringrequired
    • filledBystring or nullrequired
    • replacesstring or nullrequired
    • audienceCountinteger or nullrequired
    • responsesarray of objectrequired
      • personIdstringrequired
      • answer"accept" | "decline"required
      • respondedAtstringrequired
      • eligiblebooleanrequired
      • rankintegerrequired
      • costobjectrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

      • reasonsarray of stringrequired
      • blockedstring or nullrequired
    • beststring or nullrequired
    • mineobject or nullrequired
      • answer"accept" | "decline" or nullrequired
      • eligiblebooleanrequired
      • blockedstring or nullrequired
      • payobject or nullrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

      • weekHoursnumberrequired
      • resultobject or nullrequired
        • pickedbooleanrequired
        • whystring or nullrequired
    Request
    curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/callouts" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    [
      {
        "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 shift

    Offer an open slot to the people who can take it. They are told by push and email.

    Body

    • rosterIdstringrequired

      3–120 characters

    • slotIdstringrequired

      3–120 characters

    Response

    • idstringrequired

      3–120 characters

    • offeredTointegerrequired
    Request
    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
    {
      "id": "abc_123",
      "offeredTo": 1
    }
    POST/callouts/{calloutId}/cancelRead-and-write key

    Withdraw a shift offer

    Parameters

    • calloutIdstringpathrequired

      3–120 characters

    Response

    • oktruerequired
    Request
    curl -X POST "https://api.etime.my/v1/api/callouts/cal_2m9x7q/cancel" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "ok": true
    }
    POST/callouts/{calloutId}/pickRead-and-write key

    Choose who gets an offered shift

    Parameters

    • calloutIdstringpathrequired

      3–120 characters

    Body

    • personIdstringrequired

      3–120 characters

    Response

    • oktruerequired
    Request
    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
    {
      "ok": true
    }
    POST/callouts/{calloutId}/respondRead-and-write key

    Answer a shift offer

    Parameters

    • calloutIdstringpathrequired

      3–120 characters

    Body

    • answer"accept" | "decline"required

    Response

    • pickedbooleanrequired
    Request
    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
    {
      "picked": false
    }

    Swaps

    Shift swaps between staff.

    GET/swapsRead key

    List shift swaps

    Response

    • swapsarray of objectrequired
      • idstringrequired

        3–120 characters

      • rosterIdstringrequired

        3–120 characters

      • unitIdstringrequired

        3–120 characters

      • kind"exchange" | "giveaway"required
      • status"asked" | "accepted" | "applied" | "declined" | "rejected" | "cancelled"required
      • fromPersonIdstringrequired
      • fromobjectrequired
        • slotIdstringrequired
        • shiftIdstringrequired
        • namestringrequired
        • startsAtstringrequired
        • endsAtstringrequired
      • toPersonIdstring or nullrequired
      • toobject or nullrequired
        • slotIdstringrequired
        • shiftIdstringrequired
        • namestringrequired
        • startsAtstringrequired
        • endsAtstringrequired
      • createdAtstringrequired
      • role"asker" | "asked" | "taker" | "manager"required
      • checkobject or nullrequired
        • okbooleanrequired
        • reasonsarray of objectrequired
          • personIdstringrequired
          • textstringrequired
      • costDeltaobject or nullrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

      • takersinteger or nullrequired
      • needsApprovalbooleanrequired
      • overBudgetbooleanrequired
    • policy"manager" | "no_cost" | "auto"required
    Request
    curl "https://api.etime.my/v1/api/swaps" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "swaps": [
        {
          "id": "abc_123",
          "rosterId": "ros_8f3k2a",
          "unitId": "unt_ward3b",
          "kind": "exchange",
          "status": "asked",
          "fromPersonId": "abc_123"
        }
      ],
      "policy": "manager"
    }
    POST/swaps/optionsRead key

    Find shifts to swap with

    Body

    • slotIdstringrequired

      3–120 characters

    Response

    • exchangearray of objectrequired
      • personIdstringrequired
      • withobjectrequired
        • slotIdstringrequired
        • shiftIdstringrequired
        • namestringrequired
        • startsAtstringrequired
        • endsAtstringrequired
      • costDeltaobject or nullrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

    • takersintegerrequired
    • policy"manager" | "no_cost" | "auto"required
    Request
    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
    {
      "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"
    }
    GET/swaps/policyRead key

    Who approves swaps

    Response

    • policy"manager" | "no_cost" | "auto"required
    Request
    curl "https://api.etime.my/v1/api/swaps/policy" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "policy": "manager"
    }
    POST/swapsRead-and-write key

    Ask for a swap

    Body

    • slotIdstringrequired

      3–120 characters

    • withSlotIdstring

      3–120 characters

    Response

    • idstringrequired

      3–120 characters

    • status"asked" | "accepted" | "applied" | "declined" | "rejected" | "cancelled"required
    Request
    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
    {
      "id": "abc_123",
      "status": "asked"
    }
    POST/swaps/{id}/answerRead-and-write key

    Answer a swap request

    Parameters

    • idstringpathrequired

      3–120 characters

    Body

    • answer"accept" | "decline"required

    Response

    • idstringrequired

      3–120 characters

    • status"asked" | "accepted" | "applied" | "declined" | "rejected" | "cancelled"required
    Request
    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
    {
      "id": "abc_123",
      "status": "asked"
    }
    POST/swaps/{id}/cancelRead-and-write key

    Withdraw a swap request

    Parameters

    • idstringpathrequired

      3–120 characters

    Response

    • idstringrequired

      3–120 characters

    • status"asked" | "accepted" | "applied" | "declined" | "rejected" | "cancelled"required
    Request
    curl -X POST "https://api.etime.my/v1/api/swaps/abc_123/cancel" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "id": "abc_123",
      "status": "asked"
    }
    POST/swaps/{id}/decideRead-and-write key

    Approve or turn down a swap

    Parameters

    • idstringpathrequired

      3–120 characters

    Body

    • decision"approve" | "reject"required

    Response

    • idstringrequired

      3–120 characters

    • status"asked" | "accepted" | "applied" | "declined" | "rejected" | "cancelled"required
    Request
    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
    {
      "id": "abc_123",
      "status": "asked"
    }

    Leave and absence

    Sickness, leave and summer holidays.

    GET/holiday-roundsRead key

    List summer holiday rounds

    Response

    • roundsarray of objectrequired
      • idstringrequired
      • unitIdstringrequired
      • yearintegerrequired
      • periodFromstringrequired

        a date, YYYY-MM-DD

      • periodTostringrequired

        a date, YYYY-MM-DD

      • weeksintegerrequired
      • peakFromstringrequired

        a date, YYYY-MM-DD

      • peakTostringrequired

        a date, YYYY-MM-DD

      • closesOnstringrequired

        a date, YYYY-MM-DD

      • capacitymap of integerrequired
      • status"open" | "allocated" | "published"required
      • versionintegerrequired
      • startsarray of stringrequired
      • peakStartsarray of stringrequired
      • wishCountintegerrequired
      • myWishesarray of objectrequired
        • rankintegerrequired

          1–3

        • startstringrequired

          a date, YYYY-MM-DD

      • mineobject or nullrequired
        • personIdstringrequired
        • startstring or nullrequired

          a date, YYYY-MM-DD

        • endstring or nullrequired

          a date, YYYY-MM-DD

        • wishRankinteger or nullrequired
        • reason"wish" | "nearest" | "no_wishes" | "no_room" | "not_eligible" | "manager"required
        • priorityintegerrequired
        • peakLastYearintegerrequired
        • peakWeeksintegerrequired
        • firstWishTakenByintegerrequired
      • peoplearray of object or nullrequired
        • personIdstringrequired
        • groupstringrequired
        • wishesarray of objectrequired
          • rankintegerrequired

            1–3

          • startstringrequired

            a date, YYYY-MM-DD

        • allocationobject or nullrequired
          • personIdstringrequired
          • startstring or nullrequired

            a date, YYYY-MM-DD

          • endstring or nullrequired

            a date, YYYY-MM-DD

          • wishRankinteger or nullrequired
          • reason"wish" | "nearest" | "no_wishes" | "no_room" | "not_eligible" | "manager"required
          • priorityintegerrequired
          • peakLastYearintegerrequired
          • peakWeeksintegerrequired
          • firstWishTakenByintegerrequired
    Request
    curl "https://api.etime.my/v1/api/holiday-rounds" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "rounds": [
        {
          "id": "abc_123",
          "unitId": "unt_ward3b",
          "year": 2026,
          "periodFrom": "2026-11-05",
          "periodTo": "2026-11-05",
          "weeks": 1
        }
      ]
    }
    GET/leaveRead key

    Leave and balances

    Your requests and balance; for people who run the roster, also the team's and the inbox.

    Parameters

    • yearintegerquery

      2020–2100

    Response

    • tzstringrequired
    • todaystringrequired

      a date, YYYY-MM-DD

    • yearintegerrequired
    • idModebooleanrequired
    • orgNamestringrequired
    • jurisdictionstringrequired
    • namesmap of stringrequired
    • peoplearray of objectrequired
      • idstringrequired
      • aliasstringrequired
      • rolesarray of stringrequired
    • rolesarray of objectrequired
      • idstringrequired
      • namestringrequired
    • unitsarray of objectrequired
      • idstringrequired
      • namestringrequired
    • rulesobjectrequired
      • entitlementobject or nullrequired
        • titlestringrequired
        • summarystringrequired
        • citationsarray of objectrequired
          • titlestringrequired
          • urlstring or nullrequired
      • blocksobject or nullrequired
        • titlestringrequired
        • summarystringrequired
        • citationsarray of objectrequired
          • titlestringrequired
          • urlstring or nullrequired
      • dayCount"mon_sat_no_holidays" | "mon_fri" or nullrequired
    • mineobject or nullrequired
      • requestsarray of objectrequired
        • idstringrequired
        • personIdstringrequired
        • type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other"required
        • status"requested" | "approved" | "rejected" | "cancelled"required
        • fromstringrequired

          a date, YYYY-MM-DD

        • tostringrequired

          a date, YYYY-MM-DD

        • partialPercentinteger or nullrequired
        • daysnumberrequired
        • requestedAtstring or nullrequired
        • decidedAtstring or nullrequired
        • versionintegerrequired
      • balanceobjectrequired
        • personIdstringrequired
        • aliasstringrequired
        • vacationobject or nullrequired
          • entitlednumberrequired
          • accruednumberrequired
          • why"full" | "late_start" | "part_year" | "first_year" | "not_employed"required
          • adjustednumberrequired
          • usednumberrequired
          • plannednumberrequired
          • requestednumberrequired
          • leftnumberrequired
        • compTimeobjectrequired
          • earnednumberrequired
          • usednumberrequired
          • leftnumberrequired
        • flexobjectrequired
          • hoursnumberrequired
    • inboxarray of object or nullrequired
      • idstringrequired
      • personIdstringrequired
      • type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other"required
      • status"requested" | "approved" | "rejected" | "cancelled"required
      • fromstringrequired

        a date, YYYY-MM-DD

      • tostringrequired

        a date, YYYY-MM-DD

      • partialPercentinteger or nullrequired
      • daysnumberrequired
      • requestedAtstring or nullrequired
      • decidedAtstring or nullrequired
      • versionintegerrequired
    • teamarray of object or nullrequired
      • idstringrequired
      • personIdstringrequired
      • type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other"required
      • status"requested" | "approved" | "rejected" | "cancelled"required
      • fromstringrequired

        a date, YYYY-MM-DD

      • tostringrequired

        a date, YYYY-MM-DD

      • partialPercentinteger or nullrequired
      • daysnumberrequired
      • requestedAtstring or nullrequired
      • decidedAtstring or nullrequired
      • versionintegerrequired
    • balancesarray of object or nullrequired
      • personIdstringrequired
      • aliasstringrequired
      • vacationobject or nullrequired
        • entitlednumberrequired
        • accruednumberrequired
        • why"full" | "late_start" | "part_year" | "first_year" | "not_employed"required
        • adjustednumberrequired
        • usednumberrequired
        • plannednumberrequired
        • requestednumberrequired
        • leftnumberrequired
      • compTimeobjectrequired
        • earnednumberrequired
        • usednumberrequired
        • leftnumberrequired
      • flexobjectrequired
        • hoursnumberrequired
    Request
    curl "https://api.etime.my/v1/api/leave" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    What approving leave would mean

    Parameters

    • idstringpathrequired

      3–120 characters

    Response

    • leaveIdstringrequired
    • shiftsarray of objectrequired
      • shiftIdstringrequired
      • slotIdstringrequired
      • rosterIdstringrequired
      • namestringrequired
      • startsAtstringrequired
      • endsAtstringrequired
      • roleIdstringrequired
      • mustCoverbooleanrequired
      • coverCountintegerrequired
      • beststring or nullrequired
      • bestCostobject or nullrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

      • theirCostobject or nullrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

    • uncoveredintegerrequired
    • costChangeobject or nullrequired
      • amountintegerrequired
      • currencystringrequired

        3–3 characters

    • rosteredUntilstring or nullrequired

      a date, YYYY-MM-DD

    • partialbooleanrequired
    • balanceobject or nullrequired
      • leftnumberrequired
      • afternumberrequired
    • backfillobject or nullrequired
      • weeksarray of objectrequired
        • startstringrequired

          a date, YYYY-MM-DD

        • openMinintegerrequired
        • helperMinintegerrequired
        • tempMinintegerrequired
        • source"roster" | "contract"required
      • helpersarray of objectrequired
        • personIdstringrequired
        • minPerWeekintegerrequired
        • spareMinPerWeekintegerrequired
      • totalsobjectrequired
        • openMinintegerrequired
        • helperMinintegerrequired
        • tempMinintegerrequired
        • helperCostobject or nullrequired
          • amountintegerrequired
          • currencystringrequired

            3–3 characters

        • tempCostobject or nullrequired
          • amountintegerrequired
          • currencystringrequired

            3–3 characters

        • overtimeCostobject or nullrequired
          • amountintegerrequired
          • currencystringrequired

            3–3 characters

      • tempFtenumberrequired
      • fullTimeMinPerWeekintegerrequired
    Request
    curl "https://api.etime.my/v1/api/leave/abc_123/impact" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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 sick

    Report yourself (or, if you run the unit, someone else) sick. Their shifts are offered to others.

    Body

    • personIdstring

      3–120 characters

    • untilstringrequired

      a date, YYYY-MM-DD

    Response

    • absenceIdstringrequired

      3–120 characters

    • vacatedintegerrequired
    • offeredTointegerrequired
    Request
    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
    {
      "absenceId": "abc_123",
      "vacated": 1,
      "offeredTo": 1
    }
    POST/leaveRead-and-write key

    Ask for leave

    Body

    • personIdstring

      3–120 characters

    • type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other"required
    • fromstringrequired

      a date, YYYY-MM-DD

    • tostringrequired

      a date, YYYY-MM-DD

    • partialPercentinteger

      10–90

    Response

    • idstringrequired
    • personIdstringrequired
    • type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other"required
    • status"requested" | "approved" | "rejected" | "cancelled"required
    • fromstringrequired

      a date, YYYY-MM-DD

    • tostringrequired

      a date, YYYY-MM-DD

    • partialPercentinteger or nullrequired
    • daysnumberrequired
    • requestedAtstring or nullrequired
    • decidedAtstring or nullrequired
    • versionintegerrequired
    Request
    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
    {
      "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

    Cancel leave

    Parameters

    • idstringpathrequired

      3–120 characters

    Body

    • versionintegerrequired

    Response

    • idstringrequired
    • personIdstringrequired
    • type"sick" | "sick_child" | "vacation" | "parental" | "maternity" | "paternity" | "long_term" | "training" | "comp_time" | "unpaid" | "public_duty" | "other"required
    • status"requested" | "approved" | "rejected" | "cancelled"required
    • fromstringrequired

      a date, YYYY-MM-DD

    • tostringrequired

      a date, YYYY-MM-DD

    • partialPercentinteger or nullrequired
    • daysnumberrequired
    • requestedAtstring or nullrequired
    • decidedAtstring or nullrequired
    • versionintegerrequired
    Request
    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
    {
      "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

    Approve or turn down leave

    Parameters

    • idstringpathrequired

      3–120 characters

    Body

    • versionintegerrequired
    • decision"approve" | "reject"required
    • sendCalloutsboolean

    Response

    • statusstringrequired
    • vacatedintegerrequired
    • offeredTointegerrequired
    Request
    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
    {
      "status": "string",
      "vacated": 1,
      "offeredTo": 1
    }

    Time

    Planned and worked hours.

    GET/rosters/{rosterId}/workedRead key

    Worked hours for a roster (pay access)

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    Response

    • entriesarray of objectrequired
      • idstringrequired
      • personIdstringrequired
      • shiftIdstring or nullrequired
      • startstringrequired
      • endstringrequired
      • breakMinutesintegerrequired
    • pendingintegerrequired
    Request
    curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/worked" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "entries": [
        {
          "id": "abc_123",
          "personId": "per_ingrid",
          "shiftId": "shf_night_20261105",
          "start": "2026-11-05",
          "end": "2026-11-05",
          "breakMinutes": 1
        }
      ],
      "pending": 1
    }
    GET/time/meRead key

    Your hours

    Response

    • nowstringrequired
    • tzstringrequired
    • runningobject or nullrequired
      • idstringrequired
      • personIdstringrequired
      • shiftIdstring or nullrequired
      • startedAtstringrequired
      • endedAtstring or nullrequired
      • breakMinutesintegerrequired
      • source"app" | "kiosk" | "manager"required
      • status"open" | "submitted" | "approved" | "disputed"required
      • notestring or nullrequired
      • versionintegerrequired
      • location"inside" | "outside" | "unchecked" or null
      • roundedobject or null
        • startedAtstringrequired
        • endedAtstringrequired
    • shiftobject or nullrequired
      • shiftIdstringrequired
      • namestringrequired
      • startsAtstringrequired
      • endsAtstringrequired
      • paidMinintegerrequired
      • unpaidBreakMinintegerrequired
    • recentarray of objectrequired
      • entryobjectrequired
        • idstringrequired
        • personIdstringrequired
        • shiftIdstring or nullrequired
        • startedAtstringrequired
        • endedAtstring or nullrequired
        • breakMinutesintegerrequired
        • source"app" | "kiosk" | "manager"required
        • status"open" | "submitted" | "approved" | "disputed"required
        • notestring or nullrequired
        • versionintegerrequired
        • location"inside" | "outside" | "unchecked" or null
        • roundedobject or null
          • startedAtstringrequired
          • endedAtstringrequired
      • shiftobject or nullrequired
        • shiftIdstringrequired
        • namestringrequired
        • startsAtstringrequired
        • endsAtstringrequired
        • paidMinintegerrequired
        • unpaidBreakMinintegerrequired
    • locationCheckobject or null
      • outside"refuse" | "flag"required
    • pinSetboolean
    • roundingobject
      • stepMin0 | 5 | 10 | 15required
      • mode"nearest" | "favour"required
      • graceMinintegerrequired

        0–15

    Request
    curl "https://api.etime.my/v1/api/time/me" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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
      }
    }
    GET/time/teamRead key

    The team's planned and worked hours

    Parameters

    • fromstringqueryrequired

      a date, YYYY-MM-DD

    • tostringqueryrequired

      a date, YYYY-MM-DD

    Response

    • fromstringrequired
    • tostringrequired
    • tzstringrequired
    • idModebooleanrequired
    • rowsarray of objectrequired
      • personIdstringrequired
      • aliasstringrequired
      • plannedobject or nullrequired
        • shiftIdstringrequired
        • namestringrequired
        • startsAtstringrequired
        • endsAtstringrequired
        • paidMinintegerrequired
        • unpaidBreakMinintegerrequired
      • entryobject or nullrequired
        • idstringrequired
        • personIdstringrequired
        • shiftIdstring or nullrequired
        • startedAtstringrequired
        • endedAtstring or nullrequired
        • breakMinutesintegerrequired
        • source"app" | "kiosk" | "manager"required
        • status"open" | "submitted" | "approved" | "disputed"required
        • notestring or nullrequired
        • versionintegerrequired
        • location"inside" | "outside" | "unchecked" or null
        • roundedobject or null
          • startedAtstringrequired
          • endedAtstringrequired
    • namesmap of stringrequired
    • peoplearray of objectrequired
      • idstringrequired
      • aliasstringrequired
    • costsarray of object or nullrequired
      • personIdstringrequired
      • plannedobjectrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

      • workedobjectrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

    Request
    curl "https://api.etime.my/v1/api/time/team?from=2026-11-05&to=2026-11-05" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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.

    GET/meetingsRead key

    List your meetings

    Response

    • orgNamestringrequired
    • idModebooleanrequired
    • tzstringrequired
    • meetingsarray of objectrequired
      • idstringrequired
      • titlestringrequired
      • startsAtstringrequired
      • endsAtstringrequired
      • locationstring or nullrequired
      • organizerIdstringrequired
      • attendeesarray of stringrequired
      • attendance"fixed" | "on_shift"required
      • status"confirmed" | "moved" | "cancelled" | "skipped"required
      • outsidearray of objectrequired
        • personIdstringrequired
        • minutesintegerrequired
      • extraCostobject or nullrequired
        • amountintegerrequired
        • currencystringrequired

          3–3 characters

    • namesmap of stringrequired
    • peoplearray of objectrequired
      • idstringrequired
      • aliasstringrequired
    Request
    curl "https://api.etime.my/v1/api/meetings" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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.

    GET/fairness/meRead key

    Your fairness against the team

    Parameters

    • rosterIdstringqueryrequired

      3–120 characters

    Response

    • periodobjectrequired
      • startstringrequired
      • endstringrequired
    • mineobjectrequired
      • nightsnumberrequired
      • weekendsnumberrequired
      • holidaysnumberrequired
    • thisPeriodobjectrequired
      • nightsnumberrequired
      • weekendsnumberrequired
      • holidaysnumberrequired
    • teamobjectrequired
      • nightsobjectrequired
        • averagenumberrequired
        • lownumberrequired
        • highnumberrequired
      • weekendsobjectrequired
        • averagenumberrequired
        • lownumberrequired
        • highnumberrequired
      • holidaysobjectrequired
        • averagenumberrequired
        • lownumberrequired
        • highnumberrequired
      • peopleintegerrequired
    • vsAverageobjectrequired
      • nightsnumberrequired
      • weekendsnumberrequired
      • holidaysnumberrequired
    Request
    curl "https://api.etime.my/v1/api/fairness/me?rosterId=ros_8f3k2a" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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

    Open problems and suggested fixes

    Parameters

    • rosterIdstringpathrequired

      3–120 characters

    Response

    • mode"suggest" | "auto_no_cost"required
    • canChangebooleanrequired
    • recentarray of objectrequired
      • eventIdstringrequired
      • atstringrequired
      • versionintegerrequired
      • changesarray of objectrequired
        • slotIdstringrequired

          3–120 characters

        • personIdstring or nullrequired

          3–120 characters

    Request
    curl "https://api.etime.my/v1/api/rosters/ros_8f3k2a/heal" \
      -H "Authorization: Bearer $ETIME_KEY"
    Response · 200
    {
      "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.