{"info":{"_postman_id":"425c4079-d4b2-40a6-8908-df1353c2a647","name":"Eitje open API","description":"<html><head></head><body><h3 id=\"intro\">Intro</h3>\n<p><a href=\"https://www.eitje.app\">Eitje is scheduling software</a> and its API offers access to our customers' data on various levels.</p>\n<h3 id=\"data\">Data</h3>\n<p>An API connection is made with an \"organisation\", which may have one or more \"environments\": different venues at different locations. Each \"environment\" has multiple \"teams\", such as a team for the kitchen and the bar. A user may belong to many teams and many environments.</p>\n<h3 id=\"setup\">Setup</h3>\n<p>In order to start developing an integration, you need:</p>\n<ul>\n<li>your own credentials as a partner, and test credentials, which you may obtain by contacting <a href=\"https://mailto:info@eitje.app\">info@eitje.app</a></li>\n</ul>\n<h3 id=\"authentication\">Authentication</h3>\n<p>The authentication is basic and is done through the header. It relies on your <code>Partner-Username</code> and <code>Partner-Password</code> and our shared customer's <code>Api-Username</code> and <code>Api-Password</code>, which they may find on the settings page in Eitje (if they have the \"admin\" role). You must supply all four keys in the header separately.</p>\n<p>In Postman, the collection pre-request script adds these four headers automatically from your variables. You do not need to configure them on individual requests.</p>\n<h2 id=\"parameters\">Parameters</h2>\n<p>You can provide parameters as a JSON body or as query params, both are accepted. Authentication must be done through the header though.</p>\n<h2 id=\"filters\">Filters</h2>\n<p>Some list endpoints require date filters: Planning shifts, Time registration shifts, Leave requests, Availability shifts, Events, and Revenue days.</p>\n<p>Pass <code>filters[start_date]</code> and <code>filters[end_date]</code> as query params or in a JSON body. Optional <code>filters[date_filter_type]</code> is <code>resource_date</code> by default, or <code>updated</code> when filtering by <code>updated_at</code>.</p>\n<p>Dates can be <code>YYYY-MM-DD</code>. For <code>updated</code>, you may pass an ISO8601 datetime. Default limits are 7 days for <code>resource_date</code> and 2 days for <code>updated</code>; endpoints with different limits say so on the request.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"filters\": {\n    \"start_date\": \"2025-03-01\",\n    \"end_date\": \"2025-03-04\",\n    \"date_filter_type\": \"updated\"\n  }\n}\n</code></pre>\n<h2 id=\"contract-parts\">Contract parts</h2>\n<p>Contracts, salaries, user employment types and work schedules each have their own ID and date range. They are managed separately; creating or updating one does not automatically adjust the others. Salaries, employment type assignments and work schedules do not require a contract_id.</p>\n<p>Referenced IDs must belong to the authenticated organisation. Overlapping periods of the same resource for the same user within the organisation are rejected.</p>\n<p>Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive (2027-01-01 means the last day is 2026-12-31). On create, omit end_date or send null for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null clears the end date.</p>\n<h3 id=\"more-info\">More info</h3>\n<ul>\n<li><p>test url: <code>https://open-api-test.eitje.app/open_api</code></p>\n</li>\n<li><p>production url: <code>https://open-api.eitje.app/open_api</code></p>\n</li>\n<li><p>For questions you may also reach us at <a href=\"https://mailto:info@eitje.app\">info@eitje.app</a></p>\n</li>\n<li><p>Missing data? Feel free to contact us for new endpoints and attributes</p>\n</li>\n<li><p><a href=\"https://www.eitje.app\">Learn more about Eitje</a></p>\n</li>\n</ul>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"443091","collectionId":"425c4079-d4b2-40a6-8908-df1353c2a647","publishedId":"2s9YXk2gBR","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2023-11-28T10:25:59.000Z"},"item":[{"name":"Availability shifts","item":[{"name":"List availability shifts","event":[{"listen":"test","script":{"id":"50d73443-2282-48fa-acc0-4885dae26c27","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Response has the required fields\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item).to.have.property('id');","        pm.expect(item).to.have.property('created_at');","        pm.expect(item).to.have.property('updated_at');","        pm.expect(item).to.have.property('user');","        pm.expect(item).to.have.property('remarks');","        pm.expect(item).to.have.property('date');","        pm.expect(item).to.have.property('status');","    });","});","","","pm.test(\"User object is present and has the required properties\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item).to.have.property('user').that.is.an('object');","        pm.expect(item.user).to.have.property('id').that.is.a('number');","        pm.expect(item.user).to.have.property('name').that.is.a('string');","    });","});","","","pm.test(\"Date is in a valid date format\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  responseData.items.forEach(function(item) {","    pm.expect(item.date).to.match(/^\\d{4}-\\d{2}-\\d{2}$/);","  });","});","","","pm.test(\"Items array is present and contains at least one element\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array').that.is.not.empty;","});"],"type":"text/javascript","packages":{}}}],"id":"0821d30c-7535-4f2b-b9e3-2ee81314b9e4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/availability_shifts","description":"<p>Requires date filters.</p>\n","urlObject":{"path":["availability_shifts"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"9cc00a80-5cd5-4415-a11b-06d0d4dd62d0","name":"List availability shifts","originalRequest":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2023-01-01\",\n        \"end_date\": \"2023-01-07\"\n    }\n}","options":{"raw":{"language":"json"}}},"url":"-availability_shifts"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"bb1f00a2f8c29e0e678f9d7a8b7c171c\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"10eff30b-8ab2-4d3c-b2da-f062c4322af6"},{"key":"X-Runtime","value":"0.300403"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 12,\n            \"created_at\": \"2025-03-12T13:51:55.912617Z\",\n            \"updated_at\": \"2025-03-12T13:51:55.912617Z\",\n            \"remarks\": \"bruiloft\",\n            \"date\": \"2025-03-27\",\n            \"status\": \"unavailable\",\n            \"user\": {\n                \"id\": 2,\n                \"name\": \"Fixed Ferdy\"\n            }\n        },\n        {\n            \"id\": 10,\n            \"created_at\": \"2025-03-12T13:51:46.223091Z\",\n            \"updated_at\": \"2025-03-12T13:51:46.223091Z\",\n            \"remarks\": \"zin om te werken!\",\n            \"date\": \"2025-03-25\",\n            \"status\": \"available\",\n            \"user\": {\n                \"id\": 13,\n                \"name\": \"Financial Fay\"\n            }\n        },\n        {\n            \"id\": 14,\n            \"created_at\": \"2025-03-12T13:52:25.985657Z\",\n            \"updated_at\": \"2025-03-12T13:52:25.985657Z\",\n            \"remarks\": \"\",\n            \"date\": \"2025-03-27\",\n            \"status\": \"partly_unavailable\",\n            \"user\": {\n                \"id\": 167,\n                \"name\": \"Barack Obama\"\n            },\n            \"start_datetime\": \"2025-03-27T10:00:00.000000Z\",\n            \"end_datetime\": \"2025-03-27T14:00:00.000000Z\"\n        }\n    ]\n}"}],"_postman_id":"0821d30c-7535-4f2b-b9e3-2ee81314b9e4"}],"id":"047c40ff-641a-4b29-9257-1d2c02e32e3b","description":"<p>Availability shifts are organisation-wide availability records for users. <code>status</code> is <code>available</code>, <code>unavailable</code>, or <code>partly_unavailable</code>; partly unavailable records also include <code>start_datetime</code> and <code>end_datetime</code>. Missing records can still mean the organisation's default availability applies.</p>\n","_postman_id":"047c40ff-641a-4b29-9257-1d2c02e32e3b"},{"name":"Check ins","item":[{"name":"List check ins","event":[{"listen":"test","script":{"id":"f22c491d-468a-46f2-9c3f-1719c3b5b135","exec":["pm.test(\"Response status code is 200\", function () {","    pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Response has the required content type of application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Items array is present in the response\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array');","});","","","pm.test(\"Items array should be empty\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').that.is.empty;","});","","","pm.test(\"Items array should exist and be an array\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array');","});"],"type":"text/javascript","packages":{}}}],"id":"1eddf6b6-e66d-4c8f-a420-b4e6969dbf44","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/check_ins","urlObject":{"path":["check_ins"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"1849ef91-6f16-423d-b7af-b8268f388713","name":"List check ins","originalRequest":{"method":"GET","header":[],"url":"-/check_ins"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 9,\n            \"created_at\": \"2025-03-19T16:03:54.529681Z\",\n            \"updated_at\": \"2025-03-19T16:03:54.529681Z\",\n            \"environment\": {\n                \"id\": 2,\n                \"name\": \"Het Grote Ei\"\n            },\n            \"team\": {\n                \"id\": 2,\n                \"name\": \"Algemeen\"\n            },\n            \"user\": {\n                \"id\": 167,\n                \"name\": \"Bloemkool van de Wortel\"\n            },\n            \"start_datetime\": \"2025-03-19T17:03:54.514290+01:00\"\n        }\n    ]\n}"}],"_postman_id":"1eddf6b6-e66d-4c8f-a420-b4e6969dbf44"}],"id":"bd44cc01-d007-4f75-ba1f-76c4fe731000","description":"<p>Users can check in and check out on a central device at their employer's location. We currently only return the pending check ins (check ins that haven't been checked out yet), if you're interested in data after check out, you can use the time registration shifts endpoint.</p>\n","_postman_id":"bd44cc01-d007-4f75-ba1f-76c4fe731000"},{"name":"Contracts","item":[{"name":"List contracts","id":"053f2d41-05ad-401a-823c-65fd40d69a56","request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/contracts","description":"<p>List contract periods for the authenticated organisation.</p>\n","urlObject":{"path":["contracts"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"1990733a-213b-4235-9821-8ad34ed31ee9","name":"contracts","originalRequest":{"method":"GET","header":[],"url":"-/contracts","description":"Returns contracts for the authenticated organisation, including start_date, end_date and trial_months. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 1,\n      \"created_at\": \"2026-06-12T09:15:30.123456Z\",\n      \"updated_at\": \"2026-06-12T09:15:30.123456Z\",\n      \"environment\": {\n        \"id\": 1,\n        \"name\": \"Le Grande Oeuf\"\n      },\n      \"user\": {\n        \"id\": 10,\n        \"name\": \"Calimero Egg\"\n      },\n      \"start_date\": \"2026-01-01\",\n      \"end_date\": null\n    }\n  ]\n}"}],"_postman_id":"053f2d41-05ad-401a-823c-65fd40d69a56"},{"name":"Create contract","id":"8bec791b-fa78-4eee-9734-f5ca62d65b32","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"environment_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/contracts","description":"<p>Creates only the contract period.</p>\n","urlObject":{"path":["contracts"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"2ce8ce15-5c34-408f-9ef5-2f6b0c0e019d","name":"Create contract","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"environment_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null\n}","options":{"raw":{"language":"json"}}},"url":"-/contracts","description":"Create only the contract period. Required: user_id, environment_id, start_date. Optional: end_date, trial_months (integer or null). Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": null\n  }\n}"}],"_postman_id":"8bec791b-fa78-4eee-9734-f5ca62d65b32"},{"name":"Update contract","id":"a9bb51d6-be61-4dcf-873b-5c7614ad40b4","request":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"end_date\": \"2027-01-01\"\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/contracts/{{contract_id}}","urlObject":{"path":["contracts","{{contract_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"86007eeb-59c9-4774-8efe-d7c511f09c31","name":"Update contract","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"end_date\": \"2027-01-01\"\n}","options":{"raw":{"language":"json"}}},"url":"-/contracts/{{contract_id}}","description":"Partially update user_id, environment_id, start_date, end_date or trial_months. trial_months accepts an integer or null. Changes do not adjust the dates of salaries or other parts. Set contract_id in your Postman environment to the returned ID. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": \"2027-01-01\"\n  }\n}"}],"_postman_id":"a9bb51d6-be61-4dcf-873b-5c7614ad40b4"}],"id":"f45b5adc-e7ea-48d8-8129-f5fa772edc5f","description":"<p>A contract stores only the contract period; salary, employment type and work schedule records are optional and managed separately.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>user_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>environment_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>start_date</code></td>\n<td>date</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>end_date</code></td>\n<td>date or null</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"f45b5adc-e7ea-48d8-8129-f5fa772edc5f"},{"name":"Employment types","item":[{"name":"List employment types","id":"7ba63474-e711-4e5a-b8d3-b87cac9784ab","request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/employment_types","description":"<p>List existing employment type definitions for the authenticated organisation. Definitions cannot be created or updated through this endpoint.</p>\n","urlObject":{"path":["employment_types"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"0cc6ec88-da98-43e6-87bd-029e9a1af5fe","name":"List employment types","originalRequest":{"method":"GET","header":[],"url":"-/employment_types","description":"Returns existing definitions with id, timestamps, environment, name, fixed and personal. This endpoint does not create or update definitions."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 1,\n      \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n      \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n      \"environment\": {\n        \"id\": 1,\n        \"name\": \"Le Grande Oeuf\"\n      },\n      \"name\": \"Uren contract\",\n      \"fixed_hours\": true\n    }\n  ]\n}"}],"_postman_id":"7ba63474-e711-4e5a-b8d3-b87cac9784ab"}],"id":"c8353151-1592-4ba8-96f3-1a1bba3ca387","description":"<p>Read-only lookup of employment type definitions. Returns name, fixed_hours and environment alongside ID and timestamps. fixed_hours indicates a fixed-hours type, not an indefinite contract. Use the definition ID as employment_type_id when assigning a type to a user.</p>\n","_postman_id":"c8353151-1592-4ba8-96f3-1a1bba3ca387"},{"name":"Environments","item":[{"name":"List environments","event":[{"listen":"test","script":{"id":"60f53d6b-acaa-4628-93bf-a9a34aa28f67","exec":["pm.test(\"Response status code is 200\", function () {","    pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Content-Type header is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Items array should have the correct structure\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.items).to.be.an('array');","  pm.expect(responseData.items).to.not.be.empty;","  ","  responseData.items.forEach(function(item) {","    pm.expect(item).to.have.property('id').that.is.a('number');","    pm.expect(item).to.have.property('created_at').that.is.a('string');","    pm.expect(item).to.have.property('updated_at').that.is.a('string');","    pm.expect(item).to.have.property('team_ids').that.is.an('array');","    pm.expect(item).to.have.property('user_ids').that.is.an('array');","    pm.expect(item).to.have.property('name').that.is.a('string');","    pm.expect(item).to.have.property('active').that.is.a('boolean');","  });","});","","","pm.test(\"Ensure that 'id', 'created_at', 'updated_at', 'team_ids', 'user_ids', 'name', and 'active' are present in each item of the 'items' array\", function () {","    const responseData = pm.response.json();","","    pm.expect(responseData).to.have.property('items').that.is.an('array').with.lengthOf.at.least(1);","","    responseData.items.forEach(function(item) {","        pm.expect(item).to.include.all.keys('id', 'created_at', 'updated_at', 'team_ids', 'user_ids', 'name', 'active');","    });","});","","","pm.test(\"Verify that created_at and updated_at are in a valid date format\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/, \"created_at should be in valid date format\");","        pm.expect(item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/, \"updated_at should be in valid date format\");","    });","});"],"type":"text/javascript","packages":{},"requests":{}}}],"id":"bc9ecf5c-4764-4f25-bf4c-15327f936c04","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/environments","description":"<p>Retrieve all environments that belong to the organisation, both the active and inactive environments.</p>\n","urlObject":{"path":["environments"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"5ef72c3e-3cb7-4ecc-8903-e34428785369","name":"environments","originalRequest":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/environments"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"9f14662f948e36ca8b810ea436b42912\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"145a8dc2-b47b-45de-9f1e-e75e32d58046"},{"key":"X-Runtime","value":"0.167411"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeuf\",\n            \"team_ids\": [1],\n            \"user_ids\": [10, 20, 30],\n            \"active\": true,\n            \"created_at\": \"2021-02-11T15:59:50.059394Z\",\n            \"updated_at\": \"2022-07-05T20:43:06.816891Z\"\n        }\n    ]\n}"}],"_postman_id":"bc9ecf5c-4764-4f25-bf4c-15327f936c04"}],"id":"4e26b0c2-a027-4069-8d70-b73b8ec4d55a","_postman_id":"4e26b0c2-a027-4069-8d70-b73b8ec4d55a","description":""},{"name":"Events","item":[{"name":"List events","event":[{"listen":"test","script":{"id":"e54247f5-ebfc-43d8-8a0b-a641ac2d5aa3","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Response has the required field - items\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.have.property('items');","});","","","pm.test(\"Items array is present and contains the expected number of elements\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').and.to.have.lengthOf(0);","});","","","pm.test(\"Updated limit is within acceptable range\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.updated).to.be.at.most(14);","});","","pm.test(\"Resource date limit is within acceptable range\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.resource_date).to.be.at.most(90);","});","","","pm.test(\"Content type is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});"],"type":"text/javascript","packages":{}}}],"id":"38d6c444-5d44-41a0-b66c-640b43d47d07","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/events","description":"<ul>\n<li><p>See filters above for explanation</p>\n</li>\n<li><p>Limits:</p>\n<ul>\n<li><p>updated: 14</p>\n</li>\n<li><p>resource_date: 90</p>\n</li>\n</ul>\n</li>\n</ul>\n","urlObject":{"path":["events"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"7b03b001-71f3-4c30-b046-6c96abd0d946","name":"List events","originalRequest":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2025-01-01\",\n        \"end_date\": \"2025-01-07\"\n    }\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/events"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"c5dd5f5c6ebf9de65c44e0a50d6b9cb7\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"f2474f17-762d-4871-b429-33fcfd5e3eaf"},{"key":"X-Runtime","value":"0.029120"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 3,\n            \"created_at\": \"2025-03-14T11:01:41.823273Z\",\n            \"updated_at\": \"2025-03-14T11:01:41.823273Z\",\n            \"title\": \"great party\",\n            \"date\": \"2025-01-01\",\n            \"remarks\": null,\n            \"from\": null,\n            \"till\": null,\n            \"environment\": {\n                \"id\": 1,\n                \"name\": \"Le Grande Oeuf\"\n            }\n        }\n    ]\n}"}],"_postman_id":"38d6c444-5d44-41a0-b66c-640b43d47d07"},{"name":"Create event","event":[{"listen":"test","script":{"id":"be7e94a2-427c-403a-a04e-200985a01a30","exec":["pm.test(\"Response status code is 200\", function () {","  pm.response.to.have.status(200);","});","","","pm.test(\"Content-Type header is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Item object should exist and be an object\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item).to.exist.and.to.be.an('object');","});","","","pm.test(\"Date is in a valid date format\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.item.date).to.match(/^\\d{4}-\\d{2}-\\d{2}$/);","});","","","pm.test(\"Validate environment object\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.item.environment).to.exist.and.to.be.an('object');","    pm.expect(responseData.item.environment.id).to.exist.and.to.be.a('number');","    pm.expect(responseData.item.environment.name).to.exist.and.to.be.a('string');","});"],"type":"text/javascript","packages":{}}}],"id":"10d206a4-979c-4f46-bf4d-9793637435e3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/events","urlObject":{"path":["events"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"9bcc12be-676d-4a6c-b0b4-dbcb365eb4d2","name":"Create event","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"date\": \"2025-01-01\",\n    \"title\": \"great party\",\n    \"from\": \"10:00\",\n    \"till\": \"18:00\",\n    \"environment_id\": 1\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/events"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"8997d929ddee7a367662d5c9871cca93\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"a4ee99ac-e2da-4eae-b313-38400d28445d"},{"key":"X-Runtime","value":"0.030786"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 23,\n        \"created_at\": \"2025-03-19T16:11:16.621264Z\",\n        \"updated_at\": \"2025-03-19T16:11:16.621264Z\",\n        \"title\": \"great party\",\n        \"date\": \"2025-01-01\",\n        \"remarks\": null,\n        \"from\": \"10:00\",\n        \"till\": \"18:00\",\n        \"environment\": {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeuf\"\n        }\n    }\n}"}],"_postman_id":"10d206a4-979c-4f46-bf4d-9793637435e3"},{"name":"Update event","event":[{"listen":"test","script":{"id":"ed021e34-4776-482c-adbb-9d0ccc5c985f","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Item object should exist and be valid\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item).to.exist.and.to.be.an('object');","    pm.expect(responseData.item.id).to.be.a('number');","    pm.expect(responseData.item.created_at).to.be.a('string');","    pm.expect(responseData.item.updated_at).to.be.a('string');","    pm.expect(responseData.item.title).to.be.a('string');","    pm.expect(responseData.item.date).to.be.a('string');","    pm.expect(responseData.item.remarks).to.be.a('string');","    pm.expect(responseData.item.from).to.be.a('string');","    pm.expect(responseData.item.till).to.be.a('string');","    pm.expect(responseData.item.environment).to.exist.and.to.be.an('object');","    pm.expect(responseData.item.environment.id).to.be.a('number');","    pm.expect(responseData.item.environment.name).to.be.a('string');","});","","","pm.test(\"Date is in a valid date format\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.item.date).to.match(/^\\d{4}-\\d{2}-\\d{2}$/);","});","","","pm.test(\"Environment object is present and contains expected fields\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item.environment).to.exist;","    pm.expect(responseData.item.environment).to.have.property('id');","    pm.expect(responseData.item.environment).to.have.property('name');","});","","","pm.test(\"From and till fields are in a valid time format\", function () {","    const responseData = pm.response.json();","","    pm.expect(responseData.item.from).to.match(/^\\d{2}:\\d{2}$/);","    pm.expect(responseData.item.till).to.match(/^\\d{2}:\\d{2}$/);","});"],"type":"text/javascript","packages":{}}}],"id":"a80d6a4b-1fce-42a8-af34-797d1c39c531","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/events/{{event_id}}","urlObject":{"path":["events","{{event_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"6d5c76df-2025-464b-95a7-7c9c6ec1cae1","name":"Update event","originalRequest":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\n    \"date\": \"2026-01-01\",\n    \"title\": \"great party\",\n    \"from\": \"13:00\",\n    \"till\": \"18:00\",\n    \"environment_id\": 1,\n    \"remarks\": \"Let's throw a party to celebrate Ajax beating PSV with 10-0\"\n}","options":{"raw":{"language":"json"}}},"url":"-/events/{{event_id}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"b432e568d6013e11b5d120b918baabe3\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"89099f46-556a-4dba-bca3-8d897e666dda"},{"key":"X-Runtime","value":"0.038455"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 23,\n        \"created_at\": \"2025-03-19T16:11:16.621264Z\",\n        \"updated_at\": \"2025-03-19T16:11:31.027896Z\",\n        \"title\": \"great party\",\n        \"date\": \"2026-01-01\",\n        \"remarks\": \"Let's throw a party to celebrate Ajax beating PSV with 10-0\",\n        \"from\": \"13:00\",\n        \"till\": \"18:00\",\n        \"environment\": {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeuf\"\n        }\n    }\n}"}],"_postman_id":"a80d6a4b-1fce-42a8-af34-797d1c39c531"},{"name":"Delete event","id":"e32312c3-5047-424d-99e3-40374ffa0c62","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"url":"https://open-api.eitje.app/open_api/events/{{event_id}}","urlObject":{"path":["events","{{event_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"52fb373d-76df-4d49-8eba-6033186a9af6","name":"Delete event","originalRequest":{"method":"DELETE","header":[],"url":"https://open-api.eitje.app/open_api/events/{{event_id}}"},"status":"OK","code":200,"_postman_previewlanguage":"html","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"text/html; charset=utf-8"},{"key":"Cache-Control","value":"no-cache"},{"key":"X-Request-Id","value":"2eb0092f-98ed-4404-b6c6-aaaa1fc71bd2"},{"key":"X-Runtime","value":"0.038070"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":null}],"_postman_id":"e32312c3-5047-424d-99e3-40374ffa0c62"}],"id":"5760530b-d0bd-46b6-9099-087ba3bf732c","description":"<p>Events appear alongside the schedule in Eitje and are useful to let team members know something special is happening on that day.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>title</code></td>\n<td>string</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>date</code></td>\n<td>date</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>environment_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>remarks</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>from</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>till</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>kind</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>\n\n<p>Events have a 'kind' property that's an enum, with five possible values, due to legacy reasons these names are still in Dutch. Allowed kinds are <code>['sport', 'meeting', 'training', 'feest', 'overig']</code></p>\n","_postman_id":"5760530b-d0bd-46b6-9099-087ba3bf732c"},{"name":"Leave requests","item":[{"name":"List leave requests","event":[{"listen":"test","script":{"id":"3915015e-c05d-4ecd-93ee-ec2ed39358cb","exec":["pm.test(\"Response status code is 200\", function () {","    pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Response has the required content type - application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Response contains the items array\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array');","});","","","pm.test(\"Items array should be empty\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').that.is.empty;","});","","","pm.test(\"Response time is within an acceptable range\", function () {","  pm.expect(pm.response.responseTime).to.be.below(300);","});"],"type":"text/javascript","packages":{}}}],"id":"520d3dbc-a4ab-4834-b9a2-5af03cd82f50","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/leave_requests","description":"<p>Requires date filters. Limits: 90 days for <code>resource_date</code>, 14 days for <code>updated</code>.</p>\n","urlObject":{"path":["leave_requests"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"6b339d07-8bd3-4c4d-85d0-f59caad70d31","name":"List leave requests","originalRequest":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2025-01-14\",\n        \"end_date\": \"2025-02-01\"\n    }\n}","options":{"raw":{"language":"json"}}},"url":"-/leave_requests"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"80326917d7130a03785799a13f031216\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"ec413865-4101-4a14-aa84-72469e0666ef"},{"key":"X-Runtime","value":"0.036519"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 21,\n            \"created_at\": \"2025-01-13T14:22:15.441282Z\",\n            \"updated_at\": \"2025-02-10T13:38:34.689890Z\",\n            \"environment\": {\n                \"id\": 1,\n                \"name\": \"Le Grande Oeuf\"\n            },\n            \"user\": {\n                \"id\": 7,\n                \"name\": \"Amazing Admin\"\n            },\n            \"status\": \"accepted\",\n            \"process_reason\": null,\n            \"start_datetime\": \"2025-01-31T00:00:00.000000+01:00\",\n            \"end_datetime\": \"2025-01-31T23:59:59.000000+01:00\",\n            \"reason\": \"Wedding party\"\n        }\n     \n    ]\n}"}],"_postman_id":"520d3dbc-a4ab-4834-b9a2-5af03cd82f50"}],"id":"700dfcdc-2307-4b07-8e8f-72489bb33f17","description":"<p>Users can ask for leave and that turns into a leave requests. A request doesn't have restrictions on how long it can be. The status column shows us if the request has been handled by a manager yet.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>Property</strong></th>\n<th><strong>Type</strong></th>\n<th><strong>Explanation</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>start_datetime</td>\n<td>datetime</td>\n<td>start datetime of the request</td>\n</tr>\n<tr>\n<td>end_datetime</td>\n<td>datetime</td>\n<td>end datetime of the request</td>\n</tr>\n<tr>\n<td>status</td>\n<td>enum</td>\n<td>a request starts as 'pending' and then a manager can either approve (the status becomes 'approved') or deny (status becomes 'denied'). Only approved requests should be used for determing availability of users</td>\n</tr>\n<tr>\n<td>reason</td>\n<td>string</td>\n<td>reason for the leave give by the requester</td>\n</tr>\n<tr>\n<td>process_reason</td>\n<td>string</td>\n<td>note provided by the handler while handling it (never present on pending requests)</td>\n</tr>\n</tbody>\n</table>\n</div><h1 id=\"filters\">Filters</h1>\n<ul>\n<li><p>See filters above for explanation</p>\n</li>\n<li><p>Limits:</p>\n<ul>\n<li><p>updated: 14</p>\n</li>\n<li><p>resource_date: 90</p>\n</li>\n</ul>\n</li>\n</ul>\n","_postman_id":"700dfcdc-2307-4b07-8e8f-72489bb33f17"},{"name":"Planning shifts","item":[{"name":"List planning shifts","event":[{"listen":"test","script":{"id":"e351c652-0272-4240-847e-68463b0bad28","exec":["pm.test('Response status code is 200', function () {","    pm.expect(pm.response.code).to.equal(200);","})","","pm.test('Date format is valid', function () {","    const responseData = pm.response.json();","    pm.expect(responseData).to.be.an('object');","    responseData.items.forEach(function (item) {","        pm.expect(item.date).to.match(/^\\d{4}-\\d{2}-\\d{2}$/);","    });","})","","pm.test('Items array is present and contains the expected number of elements', function () {","    const responseData = pm.response.json();","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').and.to.have.lengthOf.at.least(1, 'Items array should not be empty');","})"],"type":"text/javascript","packages":{}}}],"id":"d82aeecf-5781-4e9d-bfb3-66b5142db5db","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/planning_shifts","description":"<p>Requires date filters. Unpublished shifts are only visible to managers. Pass <code>wage_cost: true</code> to include forecasted wage cost.</p>\n<p><code>allowance</code> is <code>null</code> when no allowance applies. When present, <code>percentage</code> is the extra allowance percentage, so <code>50</code> means +50%.</p>\n","urlObject":{"path":["planning_shifts"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"27e06ff6-c9c8-4499-b1bf-4a8baa7c9be5","name":"planning shifts","originalRequest":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2023-01-01\",\n        \"end_date\": \"2023-01-07\"\n    }\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/planning_shifts"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"a2ce39a4e59eb9e2ed848166d4afe8fe\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"9bdacebe-e25f-4df9-98b6-6376a0443912"},{"key":"X-Runtime","value":"0.476407"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 1209,\n            \"created_at\": \"2025-03-13T15:48:33.324089Z\",\n            \"updated_at\": \"2025-03-25T07:10:27.005551Z\",\n            \"start\": \"2024-03-25T09:00:00.000000+01:00\",\n            \"end\": \"2024-03-25T17:00:00.000000+01:00\",\n            \"remarks\": null,\n            \"break_minutes\": 0,\n            \"date\": \"2024-03-25\",\n            \"published\": true,\n            \"skill_set\": null,\n            \"shift_type\": null,\n            \"user\": {\n                \"id\": 18,\n                \"name\": \"Double-shift Debby\"\n            },\n            \"team\": {\n                \"id\": 16,\n                \"name\": \"kitchen\"\n            },\n            \"wage_cost\": 316.8,\n            \"environment\": {\n                \"id\": 1,\n                \"name\": \"Le Grande Oeufke\"\n            },\n            \"meals\": [],\n            \"published_at\": \"2025-03-13T15:48:33.324006Z\",\n            \"time_registration_shift_id\": null,\n            \"allowance\": {\n                \"id\": 42,\n                \"name\": \"Evening allowance\",\n                \"percentage\": 50\n            }\n        }\n    ]\n}"}],"_postman_id":"d82aeecf-5781-4e9d-bfb3-66b5142db5db"},{"name":"Create planning shift","event":[{"listen":"test","script":{"id":"f99cb173-a748-420e-9cd3-9bcef7cced9e","exec":["pm.test('Response status code is 200', function () {","    pm.response.to.have.status(200);","})","","pm.test('Item object should exist in the response', function () {","    const responseData = pm.response.json();","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item).to.exist;","})"],"type":"text/javascript","packages":{}}}],"id":"ea110d38-61fe-4fbc-b76c-b1c757ef3ec5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/planning_shifts","urlObject":{"path":["planning_shifts"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"7e98a698-a16a-4e68-b449-7ec8c4296489","name":"Create planning shift","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"start\": \"2025-01-03T09:05\",\n    \"end\": \"2025-01-03T10:00:00\",\n    \"break_minutes\": 20,\n    \"team_id\": 1,\n    \"published\": true\n}","options":{"raw":{"language":"json"}}},"url":"-/planning_shifts"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 1260,\n        \"created_at\": \"2025-03-19T16:14:22.760211Z\",\n        \"updated_at\": \"2025-03-19T16:14:22.760211Z\",\n        \"start\": \"2025-01-03T09:05:00.000000+01:00\",\n        \"end\": \"2025-01-03T10:00:00.000000+01:00\",\n        \"remarks\": null,\n        \"break_minutes\": 20,\n        \"date\": \"2025-01-03\",\n        \"published\": true,\n        \"skill_set\": null,\n        \"shift_type\": null,\n        \"user\": null,\n        \"team\": {\n            \"id\": 1,\n            \"name\": \"Algemeen\"\n        },\n        \"environment\": {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeufke\"\n        },\n        \"meals\": [],\n        \"published_at\": \"2025-03-19T16:14:22.760170Z\",\n        \"time_registration_shift_id\": null,\n        \"allowance\": null\n    }\n}"}],"_postman_id":"ea110d38-61fe-4fbc-b76c-b1c757ef3ec5"},{"name":"Update planning shift","event":[{"listen":"test","script":{"id":"a215a581-fc93-48f7-8558-8ebc022604ce","exec":["pm.test(\"Response status code is 200\", function () {","    pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Response has the required fields\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData).to.have.property('item');","    pm.expect(responseData.item).to.have.all.keys('id', 'created_at', 'updated_at', 'start', 'end', 'remarks', 'break_minutes', 'date', 'published', 'skill_set', 'shift_type', 'user', 'team', 'environment', 'meals', 'published_at', 'time_registration_shift_id');","});","","","pm.test(\"Item object is present in the response\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.item).to.exist;","});","","","pm.test(\"Date is in a valid date format\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.item.date).to.match(/^\\d{4}-\\d{2}-\\d{2}$/);","});","","","pm.test(\"Meals array is present and contains expected number of elements\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.meals).to.exist.and.to.be.an('array');","    pm.expect(responseData.meals).to.have.lengthOf(0);","});"],"type":"text/javascript","packages":{}}}],"id":"a716d202-9017-4cc3-8dc4-8f8be65ba608","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/planning_shifts/{{planning_shift_id}}","urlObject":{"path":["planning_shifts","{{planning_shift_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"1bd98a7b-80e5-4c8d-85a6-5c88ae857bd8","name":"Update","originalRequest":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\n    \"published\": true\n}","options":{"raw":{"language":"json"}}},"url":"-/planning_shifts/{{planning_shift_id}}"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"647cf00fba5f8c3326ca61b77081daaa\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"e315e2ee-e43f-4260-972e-eb8b6f50f737"},{"key":"X-Runtime","value":"0.039166"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 1260,\n        \"created_at\": \"2025-03-19T16:14:22.760211Z\",\n        \"updated_at\": \"2025-03-19T16:14:22.760211Z\",\n        \"start\": \"2025-01-03T09:05:00.000000+01:00\",\n        \"end\": \"2025-01-03T10:00:00.000000+01:00\",\n        \"remarks\": null,\n        \"break_minutes\": 20,\n        \"date\": \"2025-01-03\",\n        \"published\": true,\n        \"skill_set\": null,\n        \"shift_type\": null,\n        \"user\": null,\n        \"team\": {\n            \"id\": 1,\n            \"name\": \"Algemeen\"\n        },\n        \"environment\": {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeufke\"\n        },\n        \"meals\": [],\n        \"published_at\": \"2025-03-19T16:14:22.760170Z\",\n        \"time_registration_shift_id\": null,\n        \"allowance\": null\n    }\n}"}],"_postman_id":"a716d202-9017-4cc3-8dc4-8f8be65ba608"},{"name":"Delete planning shift","id":"2fddc115-4da7-4482-9404-955180c8bb17","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"url":"https://open-api.eitje.app/open_api/planning_shifts/{{planning_shift_id}}","urlObject":{"path":["planning_shifts","{{planning_shift_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"b506901f-98bd-4514-b47a-0bbd2f5985c5","name":"Delete","originalRequest":{"method":"DELETE","header":[],"url":"-/planning_shifts/{{planning_shift_id}}"},"status":"OK","code":200,"_postman_previewlanguage":"html","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"text/html; charset=utf-8"},{"key":"Cache-Control","value":"no-cache"},{"key":"X-Request-Id","value":"51ef8b87-5ccb-48cd-b400-0963fb43bc28"},{"key":"X-Runtime","value":"0.153116"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":null}],"_postman_id":"2fddc115-4da7-4482-9404-955180c8bb17"}],"id":"0e47f4f3-0779-4986-887a-5283e6e00c15","description":"<p>Planning shifts represent scheduled work in a team. A shift must have a team, can be open (<code>user: null</code>), cannot be longer than 24 hours, and cannot overlap another planning shift for the same user. A planning shift linked to a time registration shift cannot be edited.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>start</code></td>\n<td>string</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>end</code></td>\n<td>string</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>team_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>user_id</code></td>\n<td>integer</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>skill_set_id</code></td>\n<td>integer</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>shift_type_id</code></td>\n<td>integer</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>remarks</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>break_minutes</code></td>\n<td>integer</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>date</code></td>\n<td>date</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>published</code></td>\n<td>boolean</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"0e47f4f3-0779-4986-887a-5283e6e00c15"},{"name":"Revenue days","item":[{"name":"List revenue days","id":"4f52c5bf-b6db-4d3d-81ad-4ed3f5b8b2d2","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2025-03-01\",\n        \"end_date\": \"2025-04-30\"\n    }\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/revenue_days","description":"<ul>\n<li><p>See filters above for explanation</p>\n</li>\n<li><p>Limits:</p>\n<ul>\n<li><p>updated: 14</p>\n</li>\n<li><p>resource_date: 90</p>\n</li>\n</ul>\n</li>\n</ul>\n","urlObject":{"path":["revenue_days"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"e23de972-3511-445a-b7ad-ee8b71540f80","name":"List revenue days","originalRequest":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2025-03-01\",\n        \"end_date\": \"2025-04-30\"\n    }\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/revenue_days"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"80d405a3f1d4a36cc9fed196a7c54fb4\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"f780f840-f4df-457e-be6a-2b5c889eb092"},{"key":"X-Runtime","value":"0.033758"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 10,\n            \"created_at\": \"2025-04-03T14:02:38.130475Z\",\n            \"updated_at\": \"2025-04-03T14:02:38.139883Z\",\n            \"environment\": {\n                \"id\": 2,\n                \"name\": \"Little Egg Co.\"\n            },\n            \"amt_in_cents\": 50000,\n            \"forecast_amt_in_cents\": 0,\n            \"date\": \"2025-03-31\",\n            \"revenue_group\": {\n                \"id\": 83,\n                \"name\": \"Kitchen\"\n            }\n        },\n        {\n            \"id\": 11,\n            \"created_at\": \"2025-04-03T14:03:36.003485Z\",\n            \"updated_at\": \"2025-04-03T14:03:36.017083Z\",\n            \"environment\": {\n                \"id\": 2,\n                \"name\": \"Little Egg Co.\"\n            },\n            \"amt_in_cents\": 20000,\n            \"forecast_amt_in_cents\": 0,\n            \"date\": \"2025-04-01\",\n            \"revenue_group\": {\n                \"id\": 83,\n                \"name\": \"Kitchen\"\n            }\n        }\n    ]\n}"}],"_postman_id":"4f52c5bf-b6db-4d3d-81ad-4ed3f5b8b2d2"},{"name":"Create revenue day","id":"6b5aa330-baad-4b2a-bce8-c9812413cc58","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"revenue_group_id\": 83,\n  \"date\": \"2025-04-02\",\n  \"amt_in_cents\": 25000,\n  \"forecast_amt_in_cents\": 30000\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/revenue_days","description":"<p>Creates or updates one revenue day for a <code>revenue_group_id</code> + <code>date</code>. Send <code>amt_in_cents</code>, <code>forecast_amt_in_cents</code>, or both. Values must be 0 or higher.</p>\n","urlObject":{"path":["revenue_days"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"76380403-6fa3-40f5-887d-a12afa6dee31","name":"200 OK","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"revenue_group_id\": 83,\n  \"date\": \"2025-04-02\",\n  \"amt_in_cents\": 25000,\n  \"forecast_amt_in_cents\": 30000\n}","options":{"raw":{"language":"json"}}},"url":"-/revenue_days"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"c2bb91f3de435ad07c65d96af3af9248\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"c8db456e-14d8-430f-b95a-33481f4d3bfa"},{"key":"X-Runtime","value":"0.041284"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 12,\n    \"created_at\": \"2025-04-03T14:04:36.003485Z\",\n    \"updated_at\": \"2025-04-03T14:04:36.017083Z\",\n    \"environment\": {\n      \"id\": 2,\n      \"name\": \"Little Egg Co.\"\n    },\n    \"amt_in_cents\": 25000,\n    \"forecast_amt_in_cents\": 30000,\n    \"date\": \"2025-04-02\",\n    \"revenue_group\": {\n      \"id\": 83,\n      \"name\": \"Kitchen\"\n    }\n  }\n}"}],"_postman_id":"6b5aa330-baad-4b2a-bce8-c9812413cc58"}],"id":"b410475c-0a07-4463-b929-60ca6bda8783","description":"<p>All revenue in Eitje is stored daily inside a revenue day. A revenue day is always connected to a revenue group, and tells you how much revenue there was on a date for that group. Revenue is always reported in cents. The API supports fetching revenue days and creating or updating a single revenue day by revenue_group_id and date. At least one of amt_in_cents or forecast_amt_in_cents is required when uploading revenue.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>date</code></td>\n<td>date</td>\n<td>required</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>revenue_group_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>amt_in_cents</code></td>\n<td>integer</td>\n<td>optional</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>forecast_amt_in_cents</code></td>\n<td>integer</td>\n<td>optional</td>\n<td>—</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"b410475c-0a07-4463-b929-60ca6bda8783"},{"name":"Revenue Forecast","item":[{"name":"Forecast per day","id":"6ded66d7-6395-416b-80cd-8204080be36a","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\"environment_id\": 1, \"date\": \"2026-03-01\"}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/revenue/forecast","description":"<p>Returns forecasted revenue for one environment and date. <code>amount</code> is in normal currency units, unlike revenue days where revenue is returned in cents. Empty <code>items</code> means there was no usable forecast data.</p>\n","urlObject":{"path":["revenue","forecast"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"508651c1-526b-45db-86fa-a015cde45331","name":"Forecast","originalRequest":{"method":"POST","header":[],"url":"https://open-api.eitje.app/open_api/revenue/forecast"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"fc0440d87cb2fe5678e686fec3bda0c4\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"cfa1bf3e-762a-48e2-aaa6-8ed2d9ba6873"},{"key":"X-Runtime","value":"0.042444"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"revenue_group_id\": 100,\n            \"amount\": 100,\n            \"date\": \"2026-02-16\"\n        }\n    ],\n    \"forecast_mode\": \"4_week\"\n}"}],"_postman_id":"6ded66d7-6395-416b-80cd-8204080be36a"}],"id":"b360ff35-7222-475c-9ab0-006406b4b0d1","description":"<p>Revenue forecast predicts revenue per revenue group for one environment and date. Forecasts can be based on recent weekdays or the same period last year. If there is not enough data, some or all groups may be omitted.</p>\n","_postman_id":"b360ff35-7222-475c-9ab0-006406b4b0d1"},{"name":"Revenue groups","item":[{"name":"List revenue groups","event":[{"listen":"test","script":{"id":"a74898c2-ecc3-4b69-953a-f3c4e7abe0f7","exec":["pm.test(\"Response status code is 200\", function () {","  pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Validate the items array\", function () {","  const responseData = pm.response.json();","","  pm.expect(responseData.items).to.be.an('array').that.is.not.empty;","  responseData.items.forEach(function(item) {","    pm.expect(item).to.be.an('object');","    pm.expect(item.id).to.exist.and.to.be.a('number');","    pm.expect(item.created_at).to.exist.and.to.be.a('string');","    pm.expect(item.updated_at).to.exist.and.to.be.a('string');","    pm.expect(item.environment).to.exist.and.to.be.an('object');","    pm.expect(item.environment.id).to.exist.and.to.be.a('number');","    pm.expect(item.environment.name).to.exist.and.to.be.a('string');","    pm.expect(item.growth_pct).to.exist.and.to.be.a('number');","    pm.expect(item.target_pct).to.exist.and.to.be.a('number');","    pm.expect(item.revenue_team_ids).to.exist.and.to.be.an('array').that.is.not.empty;","    item.revenue_team_ids.forEach(function(id) {","      pm.expect(id).to.be.a('number');","    });","  });","});","","","pm.test(\"Each item has the required fields\", function () {","    const responseData = pm.response.json().items;","    ","    pm.expect(responseData).to.be.an('array');","    responseData.forEach(function(item) {","        pm.expect(item).to.have.property('id');","        pm.expect(item).to.have.property('created_at');","        pm.expect(item).to.have.property('updated_at');","        pm.expect(item).to.have.property('environment');","        pm.expect(item).to.have.property('growth_pct');","        pm.expect(item).to.have.property('target_pct');","        pm.expect(item).to.have.property('revenue_team_ids');","    });","});","","","pm.test(\"Validate the environment object within each item\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item.environment).to.exist.and.to.be.an('object');","        pm.expect(item.environment.id).to.exist.and.to.be.a('number');","        pm.expect(item.environment.name).to.exist.and.to.be.a('string');","    });","});","","","pm.test(\"Created_at and updated_at fields are in a valid date format\", function () {","  const responseData = pm.response.json();","","  pm.expect(responseData.items).to.be.an('array');","  responseData.items.forEach(function(item) {","    pm.expect(item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/);","    pm.expect(item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/);","  });","});"],"type":"text/javascript","packages":{}}}],"id":"e636303c-d1a4-40e7-8be8-c4c4d2d4e262","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/revenue_groups","description":"<p>Read-only revenue categories used for revenue reporting and forecasting.</p>\n","urlObject":{"path":["revenue_groups"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"f5ef4d30-1da7-4057-9b75-1dee7021cb3d","name":"List revenue groups","originalRequest":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/revenue_groups"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"4a42436c501785791fb50ee0e0871840\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"a2588369-2dbc-42a1-8842-b03e83cba1d6"},{"key":"X-Runtime","value":"0.052420"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 1,\n            \"created_at\": \"2024-10-10T09:56:01.322080Z\",\n            \"updated_at\": \"2024-10-10T09:56:01.322080Z\",\n            \"name\": \"Large Eggs\",\n            \"environment\": {\n                \"id\": 1,\n                \"name\": \"Le Grande Oeuf\"\n            },\n            \"growth_pct\": 10,\n            \"target_pct\": 35,\n            \"revenue_team_ids\": [\n                1,\n                353,\n                365,\n                377,\n                389,\n                403,\n                415,\n                439,\n                583\n            ]\n        }\n    ]\n}"}],"_postman_id":"e636303c-d1a4-40e7-8be8-c4c4d2d4e262"}],"id":"7277cb27-ef69-48d5-be60-53de390c2aad","description":"<p>Revenue groups are artibrary categories into which customers can divide revenue used for analytical purposes. A common pattern in restaurants is creating groups for 'kitchen' and for 'drinks'. Combined with revenue teams (see below), this enables the customer to compare revenue from certain products with labour costs from certain teams (eg comparing kitchen revenue with kitchen costs) to give them insight in how a part of their business is performing.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>Property</strong></th>\n<th><strong>Type</strong></th>\n<th><strong>Explanation</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>growth_pct</td>\n<td>integer</td>\n<td>Used for revenue forecasting if you choose for the '1 year in past' forecast model. Eitje will take the revenue of the past year (if it's currently the third monday of March, it will pick the third monday of March last year) and increase it with this percentage to come to a forecast</td>\n</tr>\n<tr>\n<td>target_pct</td>\n<td>integer</td>\n<td>Used to determine if your labour costs% of your revenue is healthy. If the labour costs% gets above this threshold, the UI will warn the user</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"7277cb27-ef69-48d5-be60-53de390c2aad"},{"name":"Revenue teams","item":[{"name":"List revenue teams","event":[{"listen":"test","script":{"id":"4358b90b-ba8e-4f49-9814-b0df06aff592","exec":["pm.test(\"Response status code is 200\", function () {","    pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Verify the required fields in the response\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData).to.have.property('items').that.is.an('array');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item).to.have.property('id').that.is.a('number');","        pm.expect(item).to.have.property('created_at').that.is.a('string');","        pm.expect(item).to.have.property('updated_at').that.is.a('string');","        pm.expect(item).to.have.property('team').that.is.an('object');","        pm.expect(item).to.have.property('fract').that.is.a('number');","        pm.expect(item).to.have.property('revenue_group').that.is.an('object');","    });","});","","","pm.test(\"Validate the date format of created_at and updated_at fields\", function () {","    const responseData = pm.response.json();","","    pm.expect(responseData).to.be.an('object');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/, \"Invalid date format for created_at\");","        pm.expect(item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/, \"Invalid date format for updated_at\");","    });","});","","","pm.test(\"Items array is present and contains the expected number of elements\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array');","    pm.expect(responseData.items.length).to.equal(1);","});","","","pm.test(\"Name in team and revenue_group objects should be a non-empty string\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item.team.name).to.be.a('string').and.to.have.lengthOf.at.least(1, \"Name in team object should be a non-empty string\");","        pm.expect(item.revenue_group.name).to.be.a('string').and.to.have.lengthOf.at.least(1, \"Name in revenue_group object should be a non-empty string\");","    });","});"],"type":"text/javascript","packages":{}}}],"id":"d2f4280d-a359-47a8-8e65-8f9ad300ec6e","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/revenue_teams","description":"<p>Read-only mapping of team labour cost percentages to revenue groups.</p>\n","urlObject":{"path":["revenue_teams"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"131e1ede-b73b-44b9-94a3-e2b5f516469d","name":"List revenue teams","originalRequest":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/revenue_teams"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"d0e47584b1c881f9a396335b5ec910b5\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"5f25f816-16bf-4b97-bf62-25be4a87ad4c"},{"key":"X-Runtime","value":"0.148505"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 195,\n      \"created_at\": \"2025-02-28T12:56:30.696949Z\",\n      \"updated_at\": \"2025-02-28T12:56:30.696949Z\",\n      \"team\": {\n        \"id\": 16,\n        \"name\": \"kitchen\"\n      },\n      \"fract\": 0,\n      \"revenue_group\": {\n        \"id\": 57,\n        \"name\": \"wwwwwwww\"\n      }\n    }\n  ]\n}"}],"_postman_id":"d2f4280d-a359-47a8-8e65-8f9ad300ec6e"}],"id":"c671a835-a628-4bad-a272-064abee9ba10","description":"<p>With revenue teams a customer can assign a certain % of labour costs of a team to a revenue group. They can either choose to assign the whole team (100%) or a part of the team. Sometimes, certain teams should be 'split' among the revenue groups, often due to the team not generating any revenue. Think of a 'management' team that works across all divisions, or an 'office' team that's responsible for HR.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th><strong>Property</strong></th>\n<th><strong>Type</strong></th>\n<th><strong>Explanation</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>fract</td>\n<td>integer</td>\n<td>percentage of the labour costs of this team that is assigned to the revenue group</td>\n</tr>\n<tr>\n<td>team</td>\n<td>resource</td>\n<td>team this revenue team belongs to</td>\n</tr>\n<tr>\n<td>revenue_group</td>\n<td>resource</td>\n<td>group this revenue team belongs to</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"c671a835-a628-4bad-a272-064abee9ba10"},{"name":"Salaries","item":[{"name":"List salaries","id":"da71c2ef-4829-4f79-bfd4-ee5beed0bf04","request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/salaries","description":"<p>List salaries for the authenticated organisation. amount is the employee’s hourly wage.</p>\n","urlObject":{"path":["salaries"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"8458650a-0fa9-4af6-bb2f-aa9c25b133a3","name":"salaries","originalRequest":{"method":"GET","header":[],"url":"-/salaries","description":"Returns salaries for the authenticated organisation. Response fields include start_date, end_date, and amount."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 1,\n      \"created_at\": \"2026-06-12T09:15:30.123456Z\",\n      \"updated_at\": \"2026-06-12T09:15:30.123456Z\",\n      \"environment\": {\n        \"id\": 1,\n        \"name\": \"Le Grande Oeuf\"\n      },\n      \"user\": {\n        \"id\": 10,\n        \"name\": \"Calimero Egg\"\n      },\n      \"start_date\": \"2026-01-01\",\n      \"end_date\": null,\n      \"amount\": 19.36\n    }\n  ]\n}"}],"_postman_id":"da71c2ef-4829-4f79-bfd4-ee5beed0bf04"},{"name":"Create salary","id":"47ec75eb-d58f-4a90-91ba-f5847f81106f","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"environment_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null,\n  \"amount\": 20.5\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/salaries","urlObject":{"path":["salaries"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"bd0b67d6-9003-480e-8c27-af8bb621272c","name":"Create salary","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"environment_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null,\n  \"amount\": 20.5\n}","options":{"raw":{"language":"json"}}},"url":"-/salaries","description":"Create a salary period. Required: user_id, environment_id, start_date, amount (finite number or numeric string). Optional: end_date. Does not create or change a contract. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": null,\n    \"amount\": 20.5\n  }\n}"}],"_postman_id":"47ec75eb-d58f-4a90-91ba-f5847f81106f"},{"name":"Update salary","id":"97369baa-261e-4cec-8203-5dd4b2b97cc4","request":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"amount\": 22.5\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/salaries/{{salary_id}}","urlObject":{"path":["salaries","{{salary_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"a41ac0cd-8670-4493-af99-ab62a9a7fe1d","name":"Update salary","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"amount\": 22.5\n}","options":{"raw":{"language":"json"}}},"url":"-/salaries/{{salary_id}}","description":"Partially update user_id, environment_id, start_date, end_date or amount. Only this salary record is changed. Set salary_id in your Postman environment to its returned ID. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": null,\n    \"amount\": 22.5\n  }\n}"}],"_postman_id":"97369baa-261e-4cec-8203-5dd4b2b97cc4"}],"id":"2c4ccc92-1360-43cb-b308-0e8a861274a6","description":"<p>amount is the employee’s hourly wage, not employer costs. For a pay change, end the old salary on the new start_date, then create a new salary. These are two separate requests; they are not atomic. Use PATCH on the existing salary to correct it.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>user_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>environment_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>start_date</code></td>\n<td>date</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>amount</code></td>\n<td>decimal</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>end_date</code></td>\n<td>date or null</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"2c4ccc92-1360-43cb-b308-0e8a861274a6"},{"name":"Shift types","item":[{"name":"List shift types","event":[{"listen":"test","script":{"id":"2bb0030f-e98a-440e-8680-c4626f72839a","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Content type is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Validate the items array\", function () {","    const responseData = pm.response.json();","","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array');","    responseData.items.forEach(function(item) {","        pm.expect(item).to.be.an('object');","        pm.expect(item.id).to.be.a('number');","        pm.expect(item.created_at).to.be.a('string');","        pm.expect(item.updated_at).to.be.a('string');","        pm.expect(item.name).to.be.a('string');","        pm.expect(item.hide_end).to.be.a('boolean');","        pm.expect(item.show_call).to.be.a('boolean');","        pm.expect(item.emoji).to.be.a('null');","        pm.expect(item.active).to.be.a('null');","    });","});","","","pm.test(\"Each item has non-empty id, created_at, updated_at, and name\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.items).to.be.an('array');","    ","    responseData.items.forEach(function(item) {","        pm.expect(item.id).to.exist.and.to.not.be.empty;","        pm.expect(item.created_at).to.exist.and.to.not.be.empty;","        pm.expect(item.updated_at).to.exist.and.to.not.be.empty;","        pm.expect(item.name).to.exist.and.to.not.be.empty;","    });","});","","","pm.test(\"Hide_end and show_call are boolean values\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array');","    ","    responseData.items.forEach(item => {","        pm.expect(item.hide_end).to.be.a('boolean');","        pm.expect(item.show_call).to.be.a('boolean');","    });","});"],"type":"text/javascript","packages":{}}}],"id":"63b4c1ad-4eee-478e-a52f-5de022c9af00","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/shift_types","urlObject":{"path":["shift_types"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"63e00cec-014e-454a-940b-2b9a69e946ff","name":"List shift types","originalRequest":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/shift_types"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"46fc639049303d14cc35b3b2bbe5026d\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"39e3d60f-8721-4795-8f7a-15ea9eea205b"},{"key":"X-Runtime","value":"0.019535"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 11,\n            \"created_at\": \"2025-03-13T15:27:59.081985Z\",\n            \"updated_at\": \"2025-03-13T15:27:59.081985Z\",\n            \"name\": \"Exceptional Shift\",\n            \"hide_end\": null,\n            \"show_call\": null,\n            \"active\": null\n        },\n        {\n            \"id\": 13,\n            \"created_at\": \"2025-03-13T15:31:51.392611Z\",\n            \"updated_at\": \"2025-03-13T15:31:51.392611Z\",\n            \"name\": \"More Exceptional Shift\",\n            \"hide_end\": null,\n            \"show_call\": null,\n            \"active\": true\n        }\n    ]\n}"}],"_postman_id":"63b4c1ad-4eee-478e-a52f-5de022c9af00"},{"name":"Create shift type","event":[{"listen":"test","script":{"id":"c925cdaf-68f1-4ada-b7e6-137fb4c56e77","exec":["pm.test(\"Response status code is 200\", function () {","  pm.response.to.have.status(200);","});","","","pm.test(\"Content-Type header is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Item object should exist and be an object\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item).to.exist.and.to.be.an('object');","});","","","pm.test(\"Ensure the created_at and updated_at fields are in a valid date format\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.have.property('item');","  pm.expect(responseData.item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{3}Z$/, 'created_at should be in valid date format');","  pm.expect(responseData.item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{3}Z$/, 'updated_at should be in valid date format');","});","","","pm.test(\"Name field must be a non-empty string\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.name).to.be.a('string').and.to.have.lengthOf.at.least(1, \"Name should not be empty\");","});"],"type":"text/javascript","packages":{}}}],"id":"f2ecef6e-711f-4e5f-ac4a-25d7e15220ed","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/shift_types","urlObject":{"path":["shift_types"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"e3987633-e361-42fe-a194-e7314fc27b37","name":"Create shift type","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\"name\": \"Exceptional Shift\"}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/shift_types"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"45029a3be42a28391d6aee317de891fc\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"bbcc20fc-2892-464a-b7d7-dc7590ac0542"},{"key":"X-Runtime","value":"0.024752"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 11,\n        \"created_at\": \"2025-03-13T15:27:59.081985Z\",\n        \"updated_at\": \"2025-03-13T15:27:59.081985Z\",\n        \"name\": \"Exceptional Shift\",\n        \"hide_end\": null,\n        \"show_call\": null,\n        \"active\": null\n    }\n}"}],"_postman_id":"f2ecef6e-711f-4e5f-ac4a-25d7e15220ed"},{"name":"Update shift type","event":[{"listen":"test","script":{"id":"3b49e0bd-9b07-4e72-8930-e0946d4a2f66","exec":["pm.test(\"Response status code is 200\", function () {","  pm.response.to.have.status(200);","});","","","pm.test(\"Item object should exist and be an object\", function () {","  const responseData = pm.response.json();","","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.item).to.exist.and.to.be.an('object');","});","","","pm.test(\"Ensure 'created_at' and 'updated_at' fields are in a valid date format\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/);","    pm.expect(responseData.item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/);","});","","","pm.test(\"Name is a non-empty string\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item.name).to.be.a('string').and.to.have.lengthOf.at.least(1, \"Name should not be empty\");","});","","","pm.test(\"Active property should be a boolean value\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData.item.active).to.be.a('boolean');","});"],"type":"text/javascript","packages":{}}}],"id":"5127081b-dc36-41eb-b4f1-a5eb9d2cba12","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/shift_types/{{shift_type_id}}","urlObject":{"path":["shift_types","{{shift_type_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"90aee25c-b22a-4511-9e28-a877578c7410","name":"Update shift type","originalRequest":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\"name\": \"Very Cool Type\"}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/shift_types/10"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"1e4404362d4b1c0b1aed4cd5b78b80da\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"f5280355-4316-47c6-b78c-50f9e487262d"},{"key":"X-Runtime","value":"0.048215"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 10,\n        \"created_at\": \"2025-03-13T15:27:04.291718Z\",\n        \"updated_at\": \"2025-03-13T15:28:11.165164Z\",\n        \"name\": \"Very Cool Type\",\n        \"hide_end\": null,\n        \"show_call\": null,\n        \"active\": null\n    }\n}"}],"_postman_id":"5127081b-dc36-41eb-b4f1-a5eb9d2cba12"},{"name":"Delete shift type","id":"f7aa6032-aed6-45c4-a2d0-31520d9878c1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/shift_types/{{shift_type_id}}","description":"<p>A shift type can only be deleted if it's not associated with any shift.</p>\n","urlObject":{"path":["shift_types","{{shift_type_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"73e27008-e07b-472e-9fa2-3932adef8390","name":"Delete shift type","originalRequest":{"method":"DELETE","header":[],"body":{"mode":"raw","raw":"{\"name\": \"first\"}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/shift_types/{{shift_type_id}}"},"status":"OK","code":200,"_postman_previewlanguage":"html","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"text/html; charset=utf-8"},{"key":"Cache-Control","value":"no-cache"},{"key":"X-Request-Id","value":"59396400-7b10-4fc8-a142-a9ea93b483c2"},{"key":"X-Runtime","value":"0.024808"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":null}],"_postman_id":"f7aa6032-aed6-45c4-a2d0-31520d9878c1"}],"id":"47ce061e-6d46-4d34-8be2-6eb11c5ed684","description":"<p>Shift types are the types of planning shifts (time registration shifts have fixed types). A customer can create as many types as they want to further categorize their planning, apart from teams. The <code>show_call</code> property adds a phone button to the employee's shift in the app. The <code>hide_end</code> property hides the end time for the employee (but not for the manager) and is often used if a manager is unsure when the shift will end.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>name</code></td>\n<td>string</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>hide_end</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>show_call</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>active</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>\n\n<p>Validations:</p>\n<ul>\n<li>A shift type's name must be unique within the organisation</li>\n</ul>\n<p>The <code>active</code>, <code>hide_end</code>, and <code>show_call</code> inputs currently accept string values such as <code>\"true\"</code> and <code>\"false\"</code>. When omitted on create, <code>active</code> defaults to true.</p>\n","_postman_id":"47ce061e-6d46-4d34-8be2-6eb11c5ed684"},{"name":"Skill Sets","item":[{"name":"List skill sets","event":[{"listen":"test","script":{"id":"5e80519e-a553-4cd8-8f87-da546b273890","exec":["pm.test(\"Response status code is 200\", function () {","  pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Content-Type header is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Validate the items array\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.items).to.be.an('array');","});","","","pm.test(\"Ensure the required fields are present and non-empty\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').that.is.not.empty;","","    responseData.items.forEach(function(item) {","        pm.expect(item.id).to.exist.and.to.not.be.empty;","        pm.expect(item.created_at).to.exist.and.to.not.be.empty;","        pm.expect(item.updated_at).to.exist.and.to.not.be.empty;","        pm.expect(item.name).to.exist.and.to.not.be.empty;","        pm.expect(item.color_code).to.exist.and.to.not.be.empty;","    });","});","","","pm.test(\"Validate the planning_active field is boolean\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.items).to.be.an('array');","  ","  responseData.items.forEach(function(item) {","    pm.expect(item.planning_active).to.be.a('boolean');","  });","});"],"type":"text/javascript","packages":{}}}],"id":"bc1dd3e9-08cd-4e40-94a6-49faa346bc02","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/skill_sets","urlObject":{"path":["skill_sets"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"d52826d5-5c5f-4ce4-a65d-a70c1909ffef","name":"Skill Sets","originalRequest":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/skill_sets"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"a","value":"b","description":"","type":"text"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"name\": \"egg poachers\",\n            \"color_code\": \"#FFBC2C\",\n            \"skill_ids\": [],\n            \"planning_active\": true,\n            \"abbr\": \"e\",\n            \"id\": 1,\n            \"created_at\": \"2024-10-24T08:08:46.314078Z\",\n            \"updated_at\": \"2024-10-24T08:08:46.314078Z\",\n            \"team_ids\": [\n                1\n            ]\n        }\n    ]\n}"}],"_postman_id":"bc1dd3e9-08cd-4e40-94a6-49faa346bc02"}],"id":"a15700c3-e82a-409d-9c79-85c89669e17b","description":"<p>Skill sets group skills that can be used when planning shifts. They can be linked to teams and skills.</p>\n","_postman_id":"a15700c3-e82a-409d-9c79-85c89669e17b"},{"name":"Teams","item":[{"name":"List teams","event":[{"listen":"test","script":{"id":"95d472a3-581e-4389-8101-f2a3fab538a8","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Content-Type header is 'application/json'\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Validate the items array\", function () {","  const responseData = pm.response.json();","","  pm.expect(responseData.items).to.be.an('array').and.to.have.lengthOf.at.least(1);","  responseData.items.forEach(function(item) {","    pm.expect(item).to.be.an('object');","    pm.expect(item.id).to.exist.and.to.be.a('number');","    pm.expect(item.created_at).to.exist.and.to.be.a('string');","    pm.expect(item.updated_at).to.exist.and.to.be.a('string');","    pm.expect(item.name).to.exist.and.to.be.a('string');","    pm.expect(item.scheduling_disabled).to.exist.and.to.be.a('boolean');","    pm.expect(item.revenue_active).to.exist.and.to.be.a('boolean');","    pm.expect(item.user_ids).to.exist.and.to.be.an('array');","    pm.expect(item.environment).to.exist.and.to.be.an('object');","    pm.expect(item.environment.id).to.exist.and.to.be.a('number');","    pm.expect(item.environment.name).to.exist.and.to.be.a('string');","  });","});","","","pm.test(\"Created_at and updated_at fields are in a valid date format\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.items).to.be.an('array');","    responseData.items.forEach(function(item) {","        pm.expect(item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/);","        pm.expect(item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/);","    });","});","","","pm.test(\"Name field is a non-empty string\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData.items).to.be.an('array');","  responseData.items.forEach(function(item) {","    pm.expect(item.name).to.be.a('string').and.to.have.lengthOf.at.least(1, \"Name should not be empty\");","  });","});"],"type":"text/javascript","packages":{}}}],"id":"38269229-29a0-4771-928d-0d5a9638fa2b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/teams","urlObject":{"path":["teams"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"a723c3cf-8037-480b-ad05-ea15b3c2be92","name":"teams","originalRequest":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/teams"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"380e17769893518b89c8ec7848cd3b6d\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"0f18b84d-ae48-4b38-b467-3783aec416dc"},{"key":"X-Runtime","value":"0.089699"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 1,\n            \"name\": \"The Egg Bar\",\n            \"user_ids\": [\n                10,\n                20,\n                30\n            ],\n            \"scheduling_enabled\": true,\n            \"created_at\": \"2021-02-11T15:59:50.059394Z\",\n            \"updated_at\": \"2022-07-05T20:43:06.816891Z\",\n            \"environment\": {\n                \"id\": 1,\n                \"name\": \"Le Grande Oeuf\"\n            }\n        }\n    ]\n}"}],"_postman_id":"38269229-29a0-4771-928d-0d5a9638fa2b"},{"name":"Create team","event":[{"listen":"test","script":{"id":"5d660116-f015-473e-aedc-412f025227d7","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Content type is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Item object should exist and be an object\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.item).to.exist.and.to.be.an('object');","});","","","pm.test(\"User IDs array is present and empty\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.have.property('item');","  pm.expect(responseData.item.user_ids).to.be.an('array').that.is.empty;","});","","","pm.test(\"Validate the environment object and its properties\", function () {","    const responseData = pm.response.json();","","    pm.expect(responseData.item.environment).to.exist;","    pm.expect(responseData.item.environment).to.be.an('object');","    pm.expect(responseData.item.environment.id).to.exist.and.to.be.a('number');","    pm.expect(responseData.item.environment.name).to.exist.and.to.be.a('string');","});"],"type":"text/javascript","packages":{}}}],"id":"59a30f71-37f2-4086-ab7f-0fef4133a045","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/teams","urlObject":{"path":["teams"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"d44d90dc-e9b3-4bbb-82ad-5c5fad6fede8","name":"Create team","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"Nieuwe naam\",\n    \"environment_id\": 1\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/teams"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"633c4ddac423ccf95ed6122e984ab28c\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"39b517bf-678a-4f28-8eca-48edb4e2d7cf"},{"key":"X-Runtime","value":"0.152937"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 60,\n        \"created_at\": \"2025-03-13T13:44:03.732268Z\",\n        \"updated_at\": \"2025-03-13T13:44:03.732268Z\",\n        \"user_ids\": [],\n        \"environment\": {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeuf\"\n        },\n        \"name\": \"Abbbfff\",\n        \"scheduling_enabled\": true\n    }\n}"}],"_postman_id":"59a30f71-37f2-4086-ab7f-0fef4133a045"},{"name":"Update team","event":[{"listen":"test","script":{"id":"b5f57d52-be68-4c7c-9e14-c0598ebc2b25","exec":["pm.test(\"Response status code is 200\", function () {","  pm.response.to.have.status(200);","});","","","pm.test(\"Validate the item object\", function () {","    const responseData = pm.response.json();","","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.item).to.exist.and.to.be.an('object');","    pm.expect(responseData.item.id).to.be.a('number');","    pm.expect(responseData.item.created_at).to.be.a('string');","    pm.expect(responseData.item.updated_at).to.be.a('string');","    pm.expect(responseData.item.name).to.be.a('string');","    pm.expect(responseData.item.scheduling_disabled).to.be.a('boolean');","    pm.expect(responseData.item.revenue_active).to.be.a('boolean');","    pm.expect(responseData.item.user_ids).to.be.an('array');","    pm.expect(responseData.item.environment).to.be.an('object');","    pm.expect(responseData.item.environment.id).to.be.a('number');","    pm.expect(responseData.item.environment.name).to.be.a('string');","});","","","pm.test(\"Created_at and updated_at are in a valid date format\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.item.created_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/);","    pm.expect(responseData.item.updated_at).to.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/);","});","","","pm.test(\"Name is a non-empty string\", function () {","  const responseData = pm.response.json();","  ","  pm.expect(responseData).to.be.an('object');","  pm.expect(responseData.item.name).to.be.a('string').and.to.have.lengthOf.at.least(1, \"Name should not be empty\");","});","","","pm.test(\"User_ids array is present and not empty\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.have.property('item');","    pm.expect(responseData.item.user_ids).to.be.an('array').and.to.have.lengthOf.at.least(1, \"User_ids array should not be empty\");","});"],"type":"text/javascript","packages":{}}}],"id":"22d12cc3-8d17-4e8d-b7d8-6aa4b5691bb1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/teams/{{team_id}}","urlObject":{"path":["teams","{{team_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"fbba9ed0-d599-4460-882c-2b5f8e6aa42e","name":"Update team","originalRequest":{"method":"PUT","header":[],"body":{"mode":"raw","raw":"{\n    \"name\": \"nieuwe naam 1789705665\"\n}","options":{"raw":{"language":"json"}}},"url":"-/teams/60"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"1ac918e5bc342ce478b516e0fd9f70c8\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"b8184560-26e7-4262-816c-cbdff00fcf41"},{"key":"X-Runtime","value":"0.048838"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"item\": {\n        \"id\": 60,\n        \"created_at\": \"2025-03-13T13:44:03.732268Z\",\n        \"updated_at\": \"2025-03-13T13:46:15.830304Z\",\n        \"user_ids\": [],\n        \"environment\": {\n            \"id\": 1,\n            \"name\": \"Le Grande Oeuf\"\n        },\n        \"name\": \"nieuwe naam\",\n        \"scheduling_enabled\": true\n    }\n}"}],"_postman_id":"22d12cc3-8d17-4e8d-b7d8-6aa4b5691bb1"},{"name":"Delete team","id":"2e649f38-dcb5-48c3-b298-4a6324fe8f5c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"url":"https://open-api.eitje.app/open_api/teams/{{team_id}}","description":"<p>A team can only be deleted if it's not associated with any shift</p>\n","urlObject":{"path":["teams","{{team_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"a2b5985d-f6d9-49a9-801d-0d2f3121cdf7","name":"Delete team","originalRequest":{"method":"DELETE","header":[],"url":"https://open-api.eitje.app/open_api/teams/60"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"27badc983df1780b60c2b3fa9d3a19a0\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"1cd68d77-0d3f-4344-853f-924d02393626"},{"key":"X-Runtime","value":"0.129975"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"200"}],"_postman_id":"2e649f38-dcb5-48c3-b298-4a6324fe8f5c"}],"id":"a80463e2-41cb-4375-898b-090b1eff23cc","description":"<p>Teams belong to an environment and are the main way to categorize work in Eitje. For shifts, a team is required.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>environment_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>name</code></td>\n<td>string</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>scheduling_disabled</code></td>\n<td>boolean</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>revenue_active</code></td>\n<td>boolean</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>\n\n<p>When <code>scheduling_disabled</code> is true, the team does not appear on the schedule. <code>revenue_active</code> controls whether the team counts in revenue calculations.</p>\n","_postman_id":"a80463e2-41cb-4375-898b-090b1eff23cc"},{"name":"Time registration shifts","item":[{"name":"List time registration shifts","event":[{"listen":"test","script":{"id":"328c96aa-d50d-4b1c-b21b-9e3d5369a1e9","exec":["pm.test(\"Response status code is 200\", function () {","    pm.expect(pm.response.code).to.equal(200);","});","","","pm.test(\"Response has the required 'items' field\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist;","});","","","pm.test(\"Items array is present and has expected number of elements\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.exist.and.to.be.an('array');","    pm.expect(responseData.items).to.have.lengthOf(0);","});","","","pm.test(\"Items array should be empty\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').that.is.empty;","});","","","pm.test(\"Content-Type header is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});"],"type":"text/javascript","packages":{}}}],"id":"4ffa5525-94c5-4f48-8fac-c295955b3f63","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/time_registration_shifts","description":"<p>Requires date filters. Pass <code>wage_cost: true</code> to include wage cost.</p>\n<p><code>allowance</code> is <code>null</code> when no allowance applies. When present, <code>percentage</code> is the extra allowance percentage, so <code>50</code> means +50%.</p>\n","urlObject":{"path":["time_registration_shifts"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"4bb4ab81-1265-4562-923c-7def8b8a8ae5","name":"time registration shifts","originalRequest":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"filters\": {\n        \"start_date\": \"2023-10-01\",\n        \"end_date\": \"2023-10-05\"\n    },\n    \"wage_cost\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/time_registration_shifts"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"ETag","value":"W/\"d4ba869e409818475a9e94b33136dac4\""},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"X-Request-Id","value":"34ba99b1-1a0e-45bd-b8b0-14b370289377"},{"key":"X-Runtime","value":"0.026857"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n    \"items\": [\n        {\n            \"id\": 1,\n            \"date\": \"2022-01-01\",\n            \"break_minutes\": 30,\n            \"check_in_ids\": [\n                1,\n                2\n            ],\n            \"remarks\": \"Prepare well for this busy wedding event!\",\n            \"start\": \"2022-01-01T09:00:00.000000+02:00\",\n            \"end\": \"2022-01-01T17:00:00.000000+02:00\",\n            \"user\": {\n                \"id\": 10,\n                \"name\": \"Calimero Egg\"\n            },\n            \"team\": {\n                \"id\": 1,\n                \"name\": \"Kitchen\"\n            },\n            \"environment\": {\n                \"id\": 1,\n                \"name\": \"Le Grande Oeuf\"\n            },\n            \"meals\": [\n                {\n                    \"name\": \"lunch\"\n                }\n            ],\n            \"approved\": true,\n            \"planning_shift_id\": null,\n            \"exported_to_hr_integration\": false,\n            \"type\": {\n                \"name\": \"gewerkte_uren\"\n            },\n            \"wage_cost\": 120,\n            \"created_at\": \"2021-02-11T15:59:50.059394Z\",\n            \"updated_at\": \"2022-07-05T20:43:06.816891Z\",\n            \"allowance\": {\n                \"id\": 42,\n                \"name\": \"Evening allowance\",\n                \"percentage\": 50\n            }\n        }\n    ]\n}"}],"_postman_id":"4ffa5525-94c5-4f48-8fac-c295955b3f63"}],"id":"5b3e3dcb-cbd3-4c0f-8da4-566e4ed894ea","_postman_id":"5b3e3dcb-cbd3-4c0f-8da4-566e4ed894ea","description":""},{"name":"User employment types","item":[{"name":"List user employment types","id":"5c3bb4f3-6053-4891-92a4-a8c1175b7b9f","request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/user_employment_types","description":"<p>List dated employment type assignments for the authenticated organisation.</p>\n","urlObject":{"path":["user_employment_types"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"1df5dbfd-4b14-4f4c-bfa5-e5292a05b2f0","name":"List user employment types","originalRequest":{"method":"GET","header":[],"url":"-/user_employment_types","description":"Returns dated employment type assignments for users in the authenticated organisation."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 1,\n      \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n      \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n      \"environment\": {\n        \"id\": 1,\n        \"name\": \"Le Grande Oeuf\"\n      },\n      \"user\": {\n        \"id\": 10,\n        \"name\": \"Calimero Egg\"\n      },\n      \"start_date\": \"2026-01-01\",\n      \"end_date\": null,\n      \"employment_type\": {\n        \"id\": 1,\n        \"name\": \"Uren contract\"\n      }\n    }\n  ]\n}"}],"_postman_id":"5c3bb4f3-6053-4891-92a4-a8c1175b7b9f"},{"name":"Create user employment type","id":"8b45e7bb-c5a1-484b-97ea-1fcbc0b92fc3","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"employment_type_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/user_employment_types","urlObject":{"path":["user_employment_types"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"b4a9c7dc-19fd-4189-b7f8-b5629877c088","name":"Create user employment type","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"employment_type_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null\n}","options":{"raw":{"language":"json"}}},"url":"-/user_employment_types","description":"Required: user_id, employment_type_id, start_date. Optional: end_date. The environment is derived from employment_type_id. Does not create or align any work schedule. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": null,\n    \"employment_type\": {\n      \"id\": 1,\n      \"name\": \"Uren contract\"\n    }\n  }\n}"}],"_postman_id":"8b45e7bb-c5a1-484b-97ea-1fcbc0b92fc3"},{"name":"Update user employment type","id":"ef46adc2-7ec7-4c82-aa9a-667e73667535","request":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"end_date\": \"2027-01-01\"\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/user_employment_types/{{user_employment_type_id}}","urlObject":{"path":["user_employment_types","{{user_employment_type_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"639eff2a-8ff2-4088-9637-1ae99582b271","name":"Update user employment type","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"end_date\": \"2027-01-01\"\n}","options":{"raw":{"language":"json"}}},"url":"-/user_employment_types/{{user_employment_type_id}}","description":"Partially update user_id, employment_type_id, start_date or end_date. Set user_employment_type_id in your Postman environment to the assignment's returned ID, not the definition ID. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": \"2027-01-01\",\n    \"employment_type\": {\n      \"id\": 1,\n      \"name\": \"Uren contract\"\n    }\n  }\n}"}],"_postman_id":"ef46adc2-7ec7-4c82-aa9a-667e73667535"}],"id":"7f42587c-137d-417c-a9ef-d38424c4ad31","description":"<p>Use an employment_type_id from GET /employment_types. The environment is derived from that definition; do not send environment_id. To update an assignment, use its own ID, not the employment type definition ID.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>user_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>employment_type_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>start_date</code></td>\n<td>date</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>end_date</code></td>\n<td>date or null</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"7f42587c-137d-417c-a9ef-d38424c4ad31"},{"name":"Users","item":[{"name":"List users","event":[{"listen":"test","script":{"id":"7e4938d0-7346-4782-9242-f056be11c79c","exec":["pm.test(\"Response status code is 200\", function () {","    pm.response.to.have.status(200);","});","","","pm.test(\"Content type is application/json\", function () {","    pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");","});","","","pm.test(\"Response includes an array of 'items' with at least one element\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData).to.be.an('object');","    pm.expect(responseData.items).to.be.an('array').and.to.have.lengthOf.at.least(1);","});","","","pm.test(\"Each item in the response includes the required fields\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.items).to.be.an('array').that.is.not.empty;","    responseData.items.forEach(function(item) {","        pm.expect(item).to.include.all.keys('id', 'created_at', 'updated_at', 'first_name', 'last_name', 'email', 'date_of_birth', 'address', 'external_ids', 'active', 'environments', 'teams');","    });","});","","","pm.test(\"Verify the number of elements in the 'environments' array for each 'item'\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.items).to.be.an('array');","    responseData.items.forEach(item => {","        pm.expect(item.environments).to.be.an('array').and.to.have.lengthOf.at.least(1);","    });","});","","pm.test(\"Verify the number of elements in the 'teams' array for each 'item'\", function () {","    const responseData = pm.response.json();","    ","    pm.expect(responseData.items).to.be.an('array');","    responseData.items.forEach(item => {","        pm.expect(item.teams).to.be.an('array').and.to.have.lengthOf.at.least(1);","    });","});"],"type":"text/javascript","packages":{}}}],"id":"619fd22e-24ed-4c60-ac74-665f1733d3ce","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/users","description":"<p>List all users in the authenticated organisation, including inactive users. See the folder notes for <code>active</code>, memberships and <code>out_of_service_date</code>.</p>\n","urlObject":{"path":["users"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"ce4d5b2c-8057-4b93-bb30-f7a66c4bdcb6","name":"users","originalRequest":{"method":"GET","header":[],"url":"-/users","description":"List all users in the authenticated organisation, including inactive users. See the folder notes for `active`, memberships and `out_of_service_date`."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 1,\n      \"created_at\": \"2026-06-12T09:15:30.123456Z\",\n      \"updated_at\": \"2026-06-12T09:15:30.123456Z\",\n      \"first_name\": \"Calimero\",\n      \"last_name\": \"Egg\",\n      \"email\": \"calimero@egg.shell\",\n      \"date_of_birth\": \"2000-01-01\",\n      \"phone_nr\": \"+31612345678\",\n      \"address\": {\n        \"street\": \"Lijnbaansstraat\",\n        \"house_number\": \"17-1\",\n        \"postal_code\": \"1016 ST\",\n        \"city\": \"Amsterdam\"\n      },\n      \"external_ids\": {\n        \"external\": \"44056\",\n        \"nmbrs\": \"12345\"\n      },\n      \"active\": true,\n      \"environment_ids\": [\n        1\n      ],\n      \"team_ids\": [\n        1\n      ],\n      \"time_clock_pin\": \"1234\",\n      \"cost_per_hour\": 22.5,\n      \"out_of_service_date\": null\n    }\n  ]\n}"}],"_postman_id":"619fd22e-24ed-4c60-ac74-665f1733d3ce"},{"name":"Create user","id":"7980f231-7113-47d6-a103-f759cd8aa130","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"email\": \"calimero@egg.shell\",\n  \"environment_id\": 1,\n  \"team_ids\": [\n    1\n  ],\n  \"first_name\": \"Calimero\",\n  \"last_name\": \"Egg\",\n  \"date_of_birth\": \"2000-01-01\",\n  \"phone_nr\": \"+31612345678\",\n  \"street\": \"Lijnbaansstraat\",\n  \"house_number\": \"17-1\",\n  \"postal_code\": \"1016 ST\",\n  \"city\": \"Amsterdam\",\n  \"cost_per_hour\": 22.5,\n  \"external_ids\": {\n    \"open_api\": \"00123\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/users","description":"<p>Create or add a user to one environment. Teams supplied through <code>team_ids</code> must belong to the selected environment.</p>\n<p>An existing email address reuses the existing account and returns the same user <code>id</code>; other environment memberships stay intact. Adding a formerly inactive user makes them active again. This uses the regular invitation flow, including its usual emails.</p>\n","urlObject":{"path":["users"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"54c6a24a-7db4-462d-89e6-3dd130d710e8","name":"Create user","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"email\": \"calimero@egg.shell\",\n  \"environment_id\": 1,\n  \"team_ids\": [\n    1\n  ],\n  \"first_name\": \"Calimero\",\n  \"last_name\": \"Egg\",\n  \"date_of_birth\": \"2000-01-01\",\n  \"phone_nr\": \"+31612345678\",\n  \"street\": \"Lijnbaansstraat\",\n  \"house_number\": \"17-1\",\n  \"postal_code\": \"1016 ST\",\n  \"city\": \"Amsterdam\",\n  \"cost_per_hour\": 22.5,\n  \"external_ids\": {\n    \"open_api\": \"00123\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"-/users","description":"Create or add a user to one environment. Required: `email`, `environment_id`. Optional: `team_ids`, `external_ids` and the profile fields listed in the folder notes. Teams must belong to the selected environment.\n\nAn existing email address reuses the existing account and returns the same user `id`; other environment memberships stay intact. Adding a formerly inactive user makes them active again. This uses the regular invitation flow, including its usual emails."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"first_name\": \"Calimero\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31612345678\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {\n      \"open_api\": \"00123\"\n    },\n    \"active\": true,\n    \"environment_ids\": [\n      1\n    ],\n    \"team_ids\": [\n      1\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 22.5,\n    \"out_of_service_date\": null\n  }\n}"}],"_postman_id":"7980f231-7113-47d6-a103-f759cd8aa130"},{"name":"Update user","id":"3be4337d-7ba0-42fd-a927-e5cb856a52d0","request":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"first_name\": \"Calimero Jr.\",\n  \"phone_nr\": \"+31687654321\",\n  \"cost_per_hour\": 24.5\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/users/{{user_id}}","description":"<p>Partially update a user by ID. Omitted fields stay unchanged.</p>\n<p>Parameter-specific behaviour:</p>\n<ul>\n<li><code>external_ids</code>: set or clear <code>open_api</code> as described in the folder notes.</li>\n<li><code>add_environment_ids</code>: add memberships without replacing existing ones. Already-linked IDs do nothing.</li>\n<li><code>remove_environment_ids</code>: remove memberships immediately, including the user's teams in those environments. Already-removed IDs do nothing. Removing the last environment makes the user inactive.</li>\n</ul>\n<p><code>add_environment_ids</code> and <code>remove_environment_ids</code> must contain environment IDs from the authenticated organisation. Empty arrays do nothing. The same ID cannot appear in both arrays. Invalid or foreign IDs and overlapping arrays return 400; removing an environment administrator returns 422. Rejected requests leave the profile and memberships unchanged.</p>\n<p>Do not send <code>environment_ids</code>, <code>team_ids</code> or <code>active</code> to replace memberships. Use <code>mark_out_of_service</code> to schedule a departure or open the user's shifts.</p>\n","urlObject":{"path":["users","{{user_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"3f3cba5b-dde9-470e-926e-415cff6c7d10","name":"Update user","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"first_name\": \"Calimero Jr.\",\n  \"phone_nr\": \"+31687654321\",\n  \"cost_per_hour\": 24.5\n}","options":{"raw":{"language":"json"}}},"url":"-/users/10","description":"Partially update a user by ID. Omitted fields stay unchanged. Accepts the profile fields listed in the folder notes, plus:\n\n- `external_ids`: set or clear `open_api` as described in the folder notes.\n- `add_environment_ids`: add memberships without replacing existing ones. Already-linked IDs do nothing.\n- `remove_environment_ids`: remove memberships immediately, including the user's teams in those environments. Already-removed IDs do nothing. Removing the last environment makes the user inactive.\n\n`add_environment_ids` and `remove_environment_ids` are optional arrays of environment IDs in the authenticated organisation. Empty arrays do nothing. The same ID cannot appear in both arrays. Invalid or foreign IDs and overlapping arrays return 400; removing an environment administrator returns 422. Rejected requests leave the profile and memberships unchanged.\n\nDo not send `environment_ids`, `team_ids` or `active` to replace memberships. Use `mark_out_of_service` to schedule a departure or open the user's shifts."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-08-28T10:20:00.123456Z\",\n    \"first_name\": \"Calimero Jr.\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31687654321\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {},\n    \"active\": true,\n    \"environment_ids\": [\n      1\n    ],\n    \"team_ids\": [\n      1\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 24.5,\n    \"out_of_service_date\": null\n  }\n}"},{"id":"7e704d1c-5b7e-4068-8aeb-f31e2c711fd8","name":"Add and remove environments","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"add_environment_ids\": [\n    2\n  ],\n  \"remove_environment_ids\": [\n    1\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"-/users/{{user_id}}","description":"Partially update a user by ID. Omitted fields stay unchanged. Accepts the profile fields listed in the folder notes, plus:\n\n- `external_ids`: set or clear `open_api` as described in the folder notes.\n- `add_environment_ids`: add memberships without replacing existing ones. Already-linked IDs do nothing.\n- `remove_environment_ids`: remove memberships immediately, including the user's teams in those environments. Already-removed IDs do nothing. Removing the last environment makes the user inactive.\n\n`add_environment_ids` and `remove_environment_ids` are optional arrays of environment IDs in the authenticated organisation. Empty arrays do nothing. The same ID cannot appear in both arrays. Invalid or foreign IDs and overlapping arrays return 400; removing an environment administrator returns 422. Rejected requests leave the profile and memberships unchanged.\n\nDo not send `environment_ids`, `team_ids` or `active` to replace memberships. Use `mark_out_of_service` to schedule a departure or open the user's shifts."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-09-08T10:00:00.000000Z\",\n    \"first_name\": \"Calimero\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31612345678\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {},\n    \"active\": true,\n    \"environment_ids\": [\n      2\n    ],\n    \"team_ids\": [\n      2\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 22.5,\n    \"out_of_service_date\": null\n  }\n}"},{"id":"6ba0a870-75d8-490f-bb21-856aa5d77851","name":"Set Open API external ID","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"external_ids\": {\n    \"open_api\": \"00123\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"-/users/10","description":"Partially update a user by ID. Omitted fields stay unchanged. Accepts the profile fields listed in the folder notes, plus:\n\n- `external_ids`: set or clear `open_api` as described in the folder notes.\n- `add_environment_ids`: add memberships without replacing existing ones. Already-linked IDs do nothing.\n- `remove_environment_ids`: remove memberships immediately, including the user's teams in those environments. Already-removed IDs do nothing. Removing the last environment makes the user inactive.\n\n`add_environment_ids` and `remove_environment_ids` are optional arrays of environment IDs in the authenticated organisation. Empty arrays do nothing. The same ID cannot appear in both arrays. Invalid or foreign IDs and overlapping arrays return 400; removing an environment administrator returns 422. Rejected requests leave the profile and memberships unchanged.\n\nDo not send `environment_ids`, `team_ids` or `active` to replace memberships. Use `mark_out_of_service` to schedule a departure or open the user's shifts."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-08-28T10:20:00.123456Z\",\n    \"first_name\": \"Calimero Jr.\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31687654321\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {\n      \"nmbrs\": \"12345\",\n      \"open_api\": \"00123\"\n    },\n    \"active\": true,\n    \"environment_ids\": [\n      1\n    ],\n    \"team_ids\": [\n      1\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 24.5,\n    \"out_of_service_date\": null\n  }\n}"},{"id":"f7488808-b1bb-4f64-b597-076bfe3956b6","name":"Clear Open API external ID","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"external_ids\": {\n    \"open_api\": null\n  }\n}","options":{"raw":{"language":"json"}}},"url":"-/users/10","description":"Partially update a user by ID. Omitted fields stay unchanged. Accepts the profile fields listed in the folder notes, plus:\n\n- `external_ids`: set or clear `open_api` as described in the folder notes.\n- `add_environment_ids`: add memberships without replacing existing ones. Already-linked IDs do nothing.\n- `remove_environment_ids`: remove memberships immediately, including the user's teams in those environments. Already-removed IDs do nothing. Removing the last environment makes the user inactive.\n\n`add_environment_ids` and `remove_environment_ids` are optional arrays of environment IDs in the authenticated organisation. Empty arrays do nothing. The same ID cannot appear in both arrays. Invalid or foreign IDs and overlapping arrays return 400; removing an environment administrator returns 422. Rejected requests leave the profile and memberships unchanged.\n\nDo not send `environment_ids`, `team_ids` or `active` to replace memberships. Use `mark_out_of_service` to schedule a departure or open the user's shifts."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-08-28T10:20:00.123456Z\",\n    \"first_name\": \"Calimero Jr.\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31687654321\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {\n      \"nmbrs\": \"12345\"\n    },\n    \"active\": true,\n    \"environment_ids\": [\n      1\n    ],\n    \"team_ids\": [\n      1\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 24.5,\n    \"out_of_service_date\": null\n  }\n}"}],"_postman_id":"3be4337d-7ba0-42fd-a927-e5cb856a52d0"},{"name":"Mark user out of service","id":"82934f2b-2d54-4e6c-9f73-0c523f25ba0c","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"date\": \"2026-10-01\",\n  \"convert_to_open_shifts\": false,\n  \"start_trade_requests\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/users/{{user_id}}/mark_out_of_service","description":"<p>Mark a user out of service across all environments in the authenticated organisation. Other organisations are unaffected. Returns the updated user.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Optional field</th>\n<th>Default</th>\n<th>Behaviour</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>date</code></td>\n<td>Today</td>\n<td>YYYY-MM-DD. Today removes memberships immediately; a future date schedules removal through the regular daily job. Past dates and null are rejected.</td>\n</tr>\n<tr>\n<td><code>convert_to_open_shifts</code></td>\n<td>false</td>\n<td>Immediately unassign planning shifts on or after <code>date</code>, even when departure is scheduled for later. Worked-hour registrations are unchanged.</td>\n</tr>\n<tr>\n<td><code>start_trade_requests</code></td>\n<td>false</td>\n<td>When converting shifts, publish them and enable pickup requests. Has no effect unless <code>convert_to_open_shifts</code> is true.</td>\n</tr>\n</tbody>\n</table>\n</div><p>Use JSON booleans (<code>true</code> / <code>false</code>). With both options omitted, existing shifts stay unchanged. Removing a user also removes their team memberships; it does not delete the account or historical data. An environment administrator cannot be marked out of service (422).</p>\n<p>Before a scheduled departure, <code>active</code> stays true and memberships remain present; <code>out_of_service_date</code> contains the scheduled date. After removal, <code>active</code> is false and <code>environment_ids</code> is empty. To change a scheduled date, call this endpoint again.</p>\n","urlObject":{"path":["users","{{user_id}}","mark_out_of_service"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"6ba2a065-5a29-48df-8d66-c6eca40504ff","name":"Schedule departure","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"date\": \"2026-10-01\",\n  \"convert_to_open_shifts\": false,\n  \"start_trade_requests\": false\n}","options":{"raw":{"language":"json"}}},"url":"-/users/{{user_id}}/mark_out_of_service","description":"Mark a user out of service across all environments in the authenticated organisation. Other organisations are unaffected. Returns the updated user.\n\n| Optional field | Default | Behaviour |\n| --- | --- | --- |\n| `date` | Today | YYYY-MM-DD. Today removes memberships immediately; a future date schedules removal through the regular daily job. Past dates and null are rejected. |\n| `convert_to_open_shifts` | false | Immediately unassign planning shifts on or after `date`, even when departure is scheduled for later. Worked-hour registrations are unchanged. |\n| `start_trade_requests` | false | When converting shifts, publish them and enable pickup requests. Has no effect unless `convert_to_open_shifts` is true. |\n\nUse JSON booleans (`true` / `false`). With both options omitted, existing shifts stay unchanged. Removing a user also removes their team memberships; it does not delete the account or historical data. An environment administrator cannot be marked out of service (422).\n\nBefore a scheduled departure, `active` stays true and memberships remain present; `out_of_service_date` contains the scheduled date. After removal, `active` is false and `environment_ids` is empty. To change a scheduled date, call this endpoint again."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-09-08T10:00:00.000000Z\",\n    \"first_name\": \"Calimero\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31612345678\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {},\n    \"active\": true,\n    \"environment_ids\": [\n      1\n    ],\n    \"team_ids\": [\n      1\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 22.5,\n    \"out_of_service_date\": \"2026-10-01\"\n  }\n}"},{"id":"17197861-ae7d-4375-a252-436792e0cd51","name":"Remove today (example date: 2026-09-08)","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"url":"-/users/{{user_id}}/mark_out_of_service","description":"Mark a user out of service across all environments in the authenticated organisation. Other organisations are unaffected. Returns the updated user.\n\n| Optional field | Default | Behaviour |\n| --- | --- | --- |\n| `date` | Today | YYYY-MM-DD. Today removes memberships immediately; a future date schedules removal through the regular daily job. Past dates and null are rejected. |\n| `convert_to_open_shifts` | false | Immediately unassign planning shifts on or after `date`, even when departure is scheduled for later. Worked-hour registrations are unchanged. |\n| `start_trade_requests` | false | When converting shifts, publish them and enable pickup requests. Has no effect unless `convert_to_open_shifts` is true. |\n\nUse JSON booleans (`true` / `false`). With both options omitted, existing shifts stay unchanged. Removing a user also removes their team memberships; it does not delete the account or historical data. An environment administrator cannot be marked out of service (422).\n\nBefore a scheduled departure, `active` stays true and memberships remain present; `out_of_service_date` contains the scheduled date. After removal, `active` is false and `environment_ids` is empty. To change a scheduled date, call this endpoint again."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-09-08T10:00:00.000000Z\",\n    \"first_name\": \"Calimero\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31612345678\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {},\n    \"active\": false,\n    \"environment_ids\": [],\n    \"team_ids\": [],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 22.5,\n    \"out_of_service_date\": \"2026-09-08\"\n  }\n}"},{"id":"8302f117-8cd9-460a-845b-f1aa1c841cd4","name":"Schedule departure and open shifts for pickup","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"date\": \"2026-10-01\",\n  \"convert_to_open_shifts\": true,\n  \"start_trade_requests\": true\n}","options":{"raw":{"language":"json"}}},"url":"-/users/{{user_id}}/mark_out_of_service","description":"Mark a user out of service across all environments in the authenticated organisation. Other organisations are unaffected. Returns the updated user.\n\n| Optional field | Default | Behaviour |\n| --- | --- | --- |\n| `date` | Today | YYYY-MM-DD. Today removes memberships immediately; a future date schedules removal through the regular daily job. Past dates and null are rejected. |\n| `convert_to_open_shifts` | false | Immediately unassign planning shifts on or after `date`, even when departure is scheduled for later. Worked-hour registrations are unchanged. |\n| `start_trade_requests` | false | When converting shifts, publish them and enable pickup requests. Has no effect unless `convert_to_open_shifts` is true. |\n\nUse JSON booleans (`true` / `false`). With both options omitted, existing shifts stay unchanged. Removing a user also removes their team memberships; it does not delete the account or historical data. An environment administrator cannot be marked out of service (422).\n\nBefore a scheduled departure, `active` stays true and memberships remain present; `out_of_service_date` contains the scheduled date. After removal, `active` is false and `environment_ids` is empty. To change a scheduled date, call this endpoint again."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 10,\n    \"created_at\": \"2026-08-28T10:15:30.123456Z\",\n    \"updated_at\": \"2026-09-08T10:00:00.000000Z\",\n    \"first_name\": \"Calimero\",\n    \"last_name\": \"Egg\",\n    \"email\": \"calimero@egg.shell\",\n    \"date_of_birth\": \"2000-01-01\",\n    \"phone_nr\": \"+31612345678\",\n    \"address\": {\n      \"street\": \"Lijnbaansstraat\",\n      \"house_number\": \"17-1\",\n      \"postal_code\": \"1016 ST\",\n      \"city\": \"Amsterdam\"\n    },\n    \"external_ids\": {},\n    \"active\": true,\n    \"environment_ids\": [\n      1\n    ],\n    \"team_ids\": [\n      1\n    ],\n    \"time_clock_pin\": \"12345\",\n    \"cost_per_hour\": 22.5,\n    \"out_of_service_date\": \"2026-10-01\"\n  }\n}"}],"_postman_id":"82934f2b-2d54-4e6c-9f73-0c523f25ba0c"}],"id":"3680d2fb-e4bc-4ed8-a5ed-c293f97b74ae","description":"<p>Users and their memberships are returned within the authenticated organisation. <code>active</code> is true when the user belongs to at least one of its environments; otherwise <code>environment_ids</code> is empty and <code>active</code> is false. <code>out_of_service_date</code> is the organisation-specific departure date, or null. A scheduled departure leaves the user active until removal.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>email</code></td>\n<td>string</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>environment_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>team_ids</code></td>\n<td>integer[]</td>\n<td>optional</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>first_name</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>last_name</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>date_of_birth</code></td>\n<td>date</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>phone_nr</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>street</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>house_number</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>postal_code</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>city</code></td>\n<td>string</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>cost_per_hour</code></td>\n<td>decimal</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>external_ids</code></td>\n<td>object</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>add_environment_ids</code></td>\n<td>integer[]</td>\n<td>—</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>remove_environment_ids</code></td>\n<td>integer[]</td>\n<td>—</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>\n\n<p>Store the returned user <code>id</code> for later updates; it remains usable when the email address changes.</p>\n<p>Send address fields at the top level; responses group them under <code>address</code>.</p>\n<h3 id=\"external-ids\">External IDs</h3>\n<p>POST and PATCH accept <code>external_ids: {\"open_api\": \"00123\"}</code>. This stores one Open API reference per user within the authenticated organisation. All authorised partners for that organisation share this value. GET returns it under the same <code>external_ids.open_api</code> key.</p>\n<p>Use a non-empty string without whitespace; leading zeros are preserved. Omit <code>external_ids</code>, or send <code>external_ids: {}</code>, to keep the current value. Send <code>external_ids: {\"open_api\": null}</code> to remove it. Sending <code>external_ids: null</code> is invalid.</p>\n<p>Only <code>open_api</code> is writable. Other keys (including <code>staffable</code>, <code>nmbrs</code> and the legacy <code>external_id</code>) are protected; sending them returns 400. They remain unchanged when updating or clearing <code>open_api</code>. Values must be unique within the organisation; a value already assigned to another user is rejected (422). The same value may be used in a different organisation.</p>\n","_postman_id":"3680d2fb-e4bc-4ed8-a5ed-c293f97b74ae"},{"name":"Work schedules","item":[{"name":"List work schedules","id":"545ae9dc-b6f8-48d9-8687-61f3e2ceadd5","request":{"method":"GET","header":[],"url":"https://open-api.eitje.app/open_api/work_schedules","description":"<p>List work schedules. Each work_weeks entry contains minutes_per_day with all seven weekdays.</p>\n","urlObject":{"path":["work_schedules"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"8044d615-241e-417b-8dcb-a588af28810f","name":"List work schedules","originalRequest":{"method":"GET","header":[],"url":"-/work_schedules","description":"Returns dated work schedules and their ordered weeks for the authenticated organisation. Weekday values are minutes; all seven weekdays are included in each returned week."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"items\": [\n    {\n      \"id\": 1,\n      \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n      \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n      \"environment\": {\n        \"id\": 1,\n        \"name\": \"Le Grande Oeuf\"\n      },\n      \"user\": {\n        \"id\": 10,\n        \"name\": \"Calimero Egg\"\n      },\n      \"start_date\": \"2026-01-01\",\n      \"end_date\": null,\n      \"work_weeks\": [\n        {\n          \"minutes_per_day\": {\n            \"monday\": 480,\n            \"tuesday\": 480,\n            \"wednesday\": 0,\n            \"thursday\": 0,\n            \"friday\": 0,\n            \"saturday\": 0,\n            \"sunday\": 0\n          }\n        },\n        {\n          \"minutes_per_day\": {\n            \"monday\": 360,\n            \"tuesday\": 0,\n            \"wednesday\": 480,\n            \"thursday\": 0,\n            \"friday\": 0,\n            \"saturday\": 0,\n            \"sunday\": 0\n          }\n        }\n      ]\n    }\n  ]\n}"}],"_postman_id":"545ae9dc-b6f8-48d9-8687-61f3e2ceadd5"},{"name":"Create work schedule","id":"6b755d2f-9e66-4831-aea6-feb8ed3b7042","request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"environment_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null,\n  \"work_weeks\": [\n    {\n      \"minutes_per_day\": {\n        \"monday\": 480,\n        \"tuesday\": 480\n      }\n    },\n    {\n      \"minutes_per_day\": {\n        \"monday\": 360,\n        \"wednesday\": 480\n      }\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/work_schedules","description":"<p>See the folder notes for calendar-week rules.</p>\n","urlObject":{"path":["work_schedules"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"c920887b-f882-4471-b1d5-777ad5f615e3","name":"Create work schedule","originalRequest":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"user_id\": 10,\n  \"environment_id\": 1,\n  \"start_date\": \"2026-01-01\",\n  \"end_date\": null,\n  \"work_weeks\": [\n    {\n      \"minutes_per_day\": {\n        \"monday\": 480,\n        \"tuesday\": 480\n      }\n    },\n    {\n      \"minutes_per_day\": {\n        \"monday\": 360,\n        \"wednesday\": 480\n      }\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"-/work_schedules","description":"Required: user_id, environment_id, start_date, weeks. Optional: end_date. weeks is an array of one or two week objects. Keys are monday through sunday; values are non-negative integer minutes (integer strings are accepted). Each week must specify at least one day. Missing days default to 0. With one week, that pattern applies every week. With two weeks, the first applies in even ISO week numbers and the second in odd ISO week numbers. Do not send week IDs or positions. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": null,\n    \"work_weeks\": [\n      {\n        \"minutes_per_day\": {\n          \"monday\": 480,\n          \"tuesday\": 480,\n          \"wednesday\": 0,\n          \"thursday\": 0,\n          \"friday\": 0,\n          \"saturday\": 0,\n          \"sunday\": 0\n        }\n      },\n      {\n        \"minutes_per_day\": {\n          \"monday\": 360,\n          \"tuesday\": 0,\n          \"wednesday\": 480,\n          \"thursday\": 0,\n          \"friday\": 0,\n          \"saturday\": 0,\n          \"sunday\": 0\n        }\n      }\n    ]\n  }\n}"}],"_postman_id":"6b755d2f-9e66-4831-aea6-feb8ed3b7042"},{"name":"Update work schedule","id":"722a3e9f-013c-4426-b635-8f154af62931","request":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"work_weeks\": [\n    {\n      \"minutes_per_day\": {\n        \"monday\": 480,\n        \"tuesday\": 480,\n        \"friday\": 240\n      }\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://open-api.eitje.app/open_api/work_schedules/{{work_schedule_id}}","description":"<p>Sending <code>work_weeks</code> replaces the entire pattern.</p>\n","urlObject":{"path":["work_schedules","{{work_schedule_id}}"],"host":["https://open-api.eitje.app/open_api"],"query":[],"variable":[]}},"response":[{"id":"32bcc952-bf45-4d6e-b988-a9bbd9783fe8","name":"Update work schedule","originalRequest":{"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"work_weeks\": [\n    {\n      \"minutes_per_day\": {\n        \"monday\": 480,\n        \"tuesday\": 480,\n        \"friday\": 240\n      }\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"-/work_schedules/{{work_schedule_id}}","description":"Partially update user_id, environment_id, start_date, end_date or weeks. Sending weeks replaces all existing weeks; omit weeks to keep them. Set work_schedule_id in your Postman environment to the returned ID. weeks is an array of one or two week objects. Keys are monday through sunday; values are non-negative integer minutes (integer strings are accepted). Each week must specify at least one day. Missing days default to 0. With one week, that pattern applies every week. With two weeks, the first applies in even ISO week numbers and the second in odd ISO week numbers. Do not send week IDs or positions. Dates use YYYY-MM-DD. start_date is inclusive; end_date is exclusive. Omit end_date on creation, or send null, for an open-ended period. On PATCH, omitted fields stay unchanged; end_date: null removes the end date."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"X-Frame-Options","value":"SAMEORIGIN"},{"key":"X-XSS-Protection","value":"0"},{"key":"X-Content-Type-Options","value":"nosniff"},{"key":"X-Download-Options","value":"noopen"},{"key":"X-Permitted-Cross-Domain-Policies","value":"none"},{"key":"Referrer-Policy","value":"strict-origin-when-cross-origin"},{"key":"Content-Type","value":"application/json; charset=utf-8"},{"key":"Cache-Control","value":"max-age=0, private, must-revalidate"},{"key":"Vary","value":"Origin"},{"key":"Transfer-Encoding","value":"chunked"}],"cookie":[],"responseTime":null,"body":"{\n  \"item\": {\n    \"id\": 1,\n    \"created_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"updated_at\": \"2026-09-05T09:15:30.123456Z\",\n    \"environment\": {\n      \"id\": 1,\n      \"name\": \"Le Grande Oeuf\"\n    },\n    \"user\": {\n      \"id\": 10,\n      \"name\": \"Calimero Egg\"\n    },\n    \"start_date\": \"2026-01-01\",\n    \"end_date\": null,\n    \"work_weeks\": [\n      {\n        \"minutes_per_day\": {\n          \"monday\": 480,\n          \"tuesday\": 480,\n          \"wednesday\": 0,\n          \"thursday\": 0,\n          \"friday\": 240,\n          \"saturday\": 0,\n          \"sunday\": 0\n        }\n      }\n    ]\n  }\n}"}],"_postman_id":"722a3e9f-013c-4426-b635-8f154af62931"}],"id":"e7a132b8-74f2-44ec-8be8-fe68f1617b7a","description":"<p>work_weeks contains one or two objects, each with minutes_per_day. Use weekday keys monday through sunday and non-negative integer minutes; specify at least one day per week. Missing days become 0. One week repeats every week. With two weeks, the first applies to even ISO calendar weeks and the second to odd weeks, regardless of start_date.</p>\n\n<p>Only the fields listed below are accepted. Omitted fields remain unchanged on update.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Create</th>\n<th>Update</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>user_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>environment_id</code></td>\n<td>integer</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>start_date</code></td>\n<td>date</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>work_weeks</code></td>\n<td>object[]</td>\n<td>required</td>\n<td>optional</td>\n</tr>\n<tr>\n<td><code>end_date</code></td>\n<td>date or null</td>\n<td>optional</td>\n<td>optional</td>\n</tr>\n</tbody>\n</table>\n</div>\n\n<p>On PATCH, work_weeks replaces the entire pattern, including resetting omitted days to 0. Omit work_weeks to keep it. Empty arrays and null are not accepted.</p>\n<p>For zero-hours employees without agreed contract hours, omit the work schedule. Record the contract type separately through <code>User employment types</code>.</p>\n","_postman_id":"e7a132b8-74f2-44ec-8be8-fe68f1617b7a"}],"event":[{"listen":"prerequest","script":{"id":"a014edfc-d0c8-4ed2-83d5-15a86a427416","type":"text/javascript","exec":["[","  [\"Api-Username\", \"-\"],","  [\"Api-Password\", \"-\"],","  [\"Partner-Username\", \"-\"],","  [\"Partner-Password\", \"-\"]","].forEach(([key, value]) => {","  pm.request.headers.upsert({ key, value: pm.variables.replaceIn(value) });","});"]}},{"listen":"test","script":{"id":"148bbdb5-fdba-4247-924d-7cc2038aac68","type":"text/javascript","exec":[""]}}],"variable":[{"key":"path","value":"-","type":"string"},{"key":"api_username","value":"-","type":"string"},{"key":"api_password","value":"-","type":"string"},{"key":"partner_username","value":"-","type":"string"},{"key":"partner_password","value":"-","type":"string"},{"key":"dev_path","value":"https://open-api.eitje.app/open_api","type":"string"}]}