{
	"info": {
		"_postman_id": "5a9e246e-1505-4c54-9dff-d05b8ef5931c",
		"name": "Knowledge base: Workplace Management: Generic webservices",
		"description": "# **Documentation:**\n\n[https://support.spacewell.com/space/KB/286818312/Workplace+Management:+Generic+webservices]()",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
		"_exporter_id": "9939091",
		"_collection_link": "https://interstellar-meteor-94930.postman.co/workspace/Product~75efda80-d00b-440a-afc1-398ff6a96458/collection/9939091-5a9e246e-1505-4c54-9dff-d05b8ef5931c?action=share&source=collection_link&creator=9939091"
	},
	"item": [
		{
			"name": "Generic",
			"item": [
				{
					"name": "Get a list of organizations",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Organizations_01\",\r\n    \"filterFields\":[\"Email\"],\r\n    \"filterValues\":[\"\"]\r\n}",
							"options": {
								"raw": {
									"language": "text"
								}
							}
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							],
							"query": [
								{
									"key": null,
									"value": "",
									"disabled": true
								}
							]
						},
						"description": "**Get the list of organizations**"
					},
					"response": []
				},
				{
					"name": "Get a list of persons",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Contacts_01\",\r\n    \"filterFields\":[\"Email\"],\r\n    \"filterValues\":[\"\"]\r\n}",
							"options": {
								"raw": {
									"language": "text"
								}
							}
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of contact persons**"
					},
					"response": []
				},
				{
					"name": "Get a list of buildings",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Properties_01\"\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of buildings**\n\nThis call returns all the buildings in the Workplace Management tenant\n\nThis uses the default 'completereportresult' endpoint and the following reference must be used in the body:\n\n{  \n\"reference\":\"API_Report_Properties_01\"  \n}\n\nThis call does not have any filters that can be used, it always return the whole list of buildings available in the tenant.\n\nExample result:"
					},
					"response": []
				},
				{
					"name": "Get a list of areas",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Areas_01\",\r\n    \"filterFields\":[\"Property\"],\r\n    \"filterValues\":[[1000066632]]\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of areas**"
					},
					"response": []
				},
				{
					"name": "Get a list of assets",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Asset_01\",\r\n    \"filterFields\":[\"Property\",\"Area\"],\r\n    \"filterValues\":[[],[]]\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of assets**"
					},
					"response": []
				},
				{
					"name": "Get a list of asset categories",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Asset_Categories_01\"\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of asset categories**"
					},
					"response": []
				},
				{
					"name": "Get a list of requests",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Requests_01\",\r\n    \"filterFields\":[\"CreatedSince\",\"CreatedUntil\"],\r\n    \"filterValues\":[\"2023-01-01T00:00:00Z\",\"2024-01-01T00:00:00Z\"]\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of requests**"
					},
					"response": []
				},
				{
					"name": "Get a list of problemtypes",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_ProblemTypes_01\"\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of requests**"
					},
					"response": []
				},
				{
					"name": "Get a list of members per service group",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_ServiceGroupMembers_01\"\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of requests**"
					},
					"response": []
				},
				{
					"name": "Get a list of corrective work orders",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Corrective_WorkOrders_01\",\r\n    \"filterFields\":[\"CreatedSince\",\"CreatedUntil\"],\r\n    \"filterValues\":[\"2023-01-01T00:00:00Z\",\"2024-01-01T00:00:00Z\"]\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of corrective workorders**"
					},
					"response": []
				},
				{
					"name": "Get a list of preventive work orders",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"reference\":\"API_Report_Preventive_WorkOrders_01\",\r\n    \"filterFields\":[\"CreatedSince\",\"CreatedUntil\"],\r\n    \"filterValues\":[\"2023-01-01T00:00:00Z\",\"2024-01-01T00:00:00Z\"]\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/completereportresult",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"completereportresult"
							]
						},
						"description": "**Get the list of corrective workorders**"
					},
					"response": []
				},
				{
					"name": "Create an asset",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"name\": \"Example laptop\",\r\n    \"externalReference\": \"987654321\",\r\n    \"serialNumber\": \"123456789\",\r\n    \"tradeName\": \"Demo turbo\",\r\n    \"modelName\": \"model X1\",\r\n    \"quantity\": \"1\",\r\n    \"manufacturerContactId\": \"\",\r\n    \"supplierContactId\": \"\",\r\n    \"purchaseDate\": \"2023-01-01T00:00:00Z\",\r\n    \"propertyId\": \"\",\r\n    \"areaId\": \"\",\r\n    \"parentAssetId\": \"\"\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/createupdate/Asset/1000003542",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"createupdate",
								"Asset",
								"1000003542"
							]
						},
						"description": "**Create an asset**"
					},
					"response": []
				},
				{
					"name": "Create a request",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{   \"fromContactId\": \"\",\r\n    \"name\": \"Demo work request\",\r\n    \"description\": \"This is a demo description for a work request\",\r\n    \"propertyId\": \"\",\r\n    \"areaId\": \"\",\r\n    \"assetId\": \"\"\r\n}"
						},
						"url": {
							"raw": "{{baseUrl}}/functions/createupdate/Request/",
							"host": [
								"{{baseUrl}}"
							],
							"path": [
								"functions",
								"createupdate",
								"Request",
								""
							]
						},
						"description": "**Create a request**"
					},
					"response": []
				}
			]
		}
	],
	"auth": {
		"type": "bearer",
		"bearer": [
			{
				"key": "token",
				"value": "{{bearer-token}}",
				"type": "string"
			}
		]
	},
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"packages": {},
				"exec": [
					"var uuid = require('uuid')",
					"var CryptoJS = require('crypto-js')",
					"//construct the full token endpoint",
					"authUrl = pm.collectionVariables.get(\"proto\") + \"://\" + pm.environment.replaceIn(\"{{server}}\") + \"/axxerion/aaa/registration/oauth2/token\"",
					"//authentication mode to be used [GENERIC, COBUNDU, ROUTER, ANALYTICS, MAINTENANCE]",
					"authMode = pm.environment.get(\"authentication-mode\")",
					"//username of user to request a token for",
					"username = pm.environment.get(\"username\")",
					"//appId of Axxerion ExternalApp",
					"appId = pm.environment.get(\"app-id\")",
					"//secret (AES) key from trust relation",
					"trustKey = pm.environment.get(\"secret-key\")",
					"//payload which includes ExternalAppId and username",
					"message = '{\"grant_type\": \"password\", \"username\": \"' + username + '\", \"password\": \"\", \"scope\": \"session v1 v2 v3\", \"app_id\": \"' + appId + '\"}'",
					"pm.collectionVariables.get(\"variable_key\");",
					"console.log(\"encrypting authentication message:\", message)",
					"//generate random 16 character string only consisting of hexadecimal characters",
					"// ivString = uuid.v4().replaceAll('-', '').substring(0, 16);",
					"// console.log(\"ivString:\", ivString)",
					"",
					"// function StringtoHex(str) {",
					"//     let hexString = '';",
					"//     let charCode, Hex;",
					"//     str.split('').map( i => {",
					"//         charCode = i.charCodeAt(0)",
					"//         Hex = charCode.toString(16);",
					"//         hexString = hexString + Hex;",
					"//     });",
					"//     hexString = hexString.trim();",
					"//     return hexString",
					"// }",
					"",
					"// //convert the generated 16 character string to hexadecimal (32 characters)",
					"// ivHex = StringtoHex(ivString)",
					"",
					"// //encode the hexadecimal formatted string to an actual IV (16 bytes)",
					"// iv = CryptoJS.enc.Hex.parse(ivHex)",
					"",
					"iv = CryptoJS.lib.WordArray.random(16);",
					"",
					"console.log(\"iv:\", iv.toString(CryptoJS.enc.Hex));",
					"",
					"if (authMode == \"GENERIC\") {",
					"    //AES key in byte form",
					"    const key = CryptoJS.enc.Hex.parse(trustKey)",
					"    //AES encrypt the above message with the provided IV",
					"    var encrypted = CryptoJS.AES.encrypt(message, key, { iv: iv });",
					"    //construct the oAuth header in the form of ",
					"    //{length_of_base64_encoded_ciphertext}:{base64_encoded_ciphertext}{base64_encoded_iv}",
					"    oAuthHeader = CryptoJS.enc.Base64.stringify(encrypted.ciphertext).length + \":\" + CryptoJS.enc.Base64.stringify(encrypted.ciphertext) + CryptoJS.enc.Base64.stringify(iv)",
					"} else if (authMode == \"COBUNDU\" || authMode == \"ROUTER\" || authMode == \"ANALYTICS\" || authMode == \"MAINTENANCE\") {",
					"    //secret salt (only used for internal Spacewell integration purposes)",
					"    if (authMode == \"COBUNDU\") {",
					"        salt = pm.collectionVariables.get(\"cobundu-salt\")",
					"        console.log(\"COBUNDU mode with\", salt)",
					"    } else if (authMode == \"ROUTER\") {",
					"        salt = pm.collectionVariables.get(\"router-salt\")",
					"        console.log(\"ROUTER mode with\", salt)",
					"    } else if (authMode == \"ANALYTICS\") {",
					"        salt = pm.collectionVariables.get(\"analytics-salt\")",
					"        console.log(\"ANALYTICS mode with\", salt)",
					"    } else if (authMode == \"MAINTENANCE\") {",
					"        salt = pm.collectionVariables.get(\"maintenance-salt\")",
					"        console.log(\"MAINTENANCE mode with\", salt)",
					"    }",
					"    //concatenate the salt and secret key and generate a SHA-256 hash from it",
					"    sha256hash = CryptoJS.SHA256(salt + trustKey)",
					"    //generate a md5 hash of the authentication message",
					"    md5hash = CryptoJS.MD5(message)",
					"    //convert generated md5 hash to hexadecimal",
					"    md5hex = CryptoJS.enc.Hex.stringify(md5hash)",
					"    //concatenate the authentication message and the md5 hash and decode to bytes",
					"    messagebytes = CryptoJS.enc.Utf8.parse(message + md5hex);",
					"    //base64 encode the 16 byte iv, which results in a 24 character base64 string and remove the last 2 characters (2 equals signs)",
					"    ivbase64 = CryptoJS.enc.Base64.stringify(iv).slice(0,22)",
					"    //encrypt the message (which includes the md5 hash) with the sha256 hash as key and the random iv, pad out with zeros",
					"    encrypted = CryptoJS.AES.encrypt(messagebytes, sha256hash, { iv: iv, padding: CryptoJS.pad.ZeroPadding });",
					"    //concatenate the 22 character iv with the base64 encoded ciphertext",
					"    oAuthHeader = ivbase64 + CryptoJS.enc.Base64.stringify(encrypted.ciphertext)",
					"} else {",
					"    throw new Error(\"Invalid authentication-mode parameter, must be one of [\\\"GENERIC\\\", \\\"COBUNDU\\\", \\\"ROUTER\\\", \\\"ANALYTICS\\\", \\\"MAINTENANCE\\\"]\")",
					"}",
					"    ",
					"//set the generated oAuth header as value for the \"encrypted-params\" variable, which will be used in the request body",
					"pm.environment.set(\"encrypted-params\", oAuthHeader)",
					"",
					"//send the token request",
					"pm.sendRequest({",
					"    url: authUrl,",
					"    method: 'POST',",
					"    header: {",
					"        'Authorization': 'Axx_encryption_key ' + pm.environment.get(\"x-access-id-value\"),",
					"        'Accept': 'application/json',",
					"        'Content-Type': 'application/x-www-form-urlencoded',",
					"        'axx-client-reference': pm.environment.get(\"clientRef\")",
					"    },",
					"    body: {",
					"        mode: 'urlencoded',",
					"        urlencoded: [",
					"            {key: 'encrypted-params', value: pm.environment.get(\"encrypted-params\")},",
					"        ]",
					"    }",
					"},",
					"    (err, res) => {",
					"        // Set BEARERTOKEN",
					"        if (res) {",
					"            try {",
					"                pm.environment.set(\"bearer-token\", res.json().access_token)",
					"            } catch(e) {",
					"                console.error(\"No valid json:\", res)",
					"                throw new Error(\"Token response body is no valid json\")",
					"            }",
					"        }",
					"});",
					"",
					"if (pm.environment.get(\"x-csrf-token\")) {",
					"    pm.request.headers.add({key: 'x-csrf-token', value: pm.environment.get(\"x-csrf-token\") })",
					"}"
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"packages": {},
				"exec": [
					"var template = `",
					"    <h3>Number of results: {{numberOfResults}}</h3>",
					"    <table bgcolor=\"#FFFFFF\">",
					"        <tr>",
					"        {{#each response.fields}}",
					"            <th>{{this}}</th>",
					"        {{/each}}",
					"        </tr>",
					"        {{#each response.data}}",
					"            <tr>",
					"            {{#each this}}",
					"                <td>{{this}}</td>",
					"            {{/each}}",
					"            </tr>",
					"        {{/each}}",
					"    </table>",
					"`;",
					"",
					"var responseData",
					"if (pm.response.headers.get(\"Content-Type\") === \"application/json\") {",
					"    responseData = pm.response.json().data ? pm.response.json().data : pm.response.json().payload;",
					"    // console.log(\"responseData:\", responseData, \"type:\", typeof responseData)",
					"}",
					"",
					"fieldsAndData = {",
					"    fields: [],",
					"    data: []",
					"};",
					"",
					"if (responseData) {",
					"    responseData.forEach(getFieldsAndData);",
					"}",
					"",
					"function getFieldsAndData(v, i, arr) {",
					"    // console.log(\"v:\", v, \"i:\", i, \"arr:\", arr)",
					"    if (i == 0) {",
					"        for (key in v) {",
					"            if ( (key != \"id\" && key != \"objectNameId\") || (v[key] != \"0\") ) {",
					"                fieldsAndData.fields.push(key)",
					"            }",
					"        }",
					"    }",
					"    fieldsAndData.data.push({})",
					"    for (key in v) {",
					"        if (fieldsAndData.fields.includes(key)) {",
					"            fieldsAndData.data[i][key] = v[key]",
					"        }",
					"    }",
					"}",
					"",
					"// Handlebars.registerHelper('breaklines', function(text) {",
					"//     text = Handlebars.Utils.escapeExpression(text);",
					"//     text = text.replace(/(\\r\\n|\\n|\\r)/gm, '<br>');",
					"//     return new Handlebars.SafeString(text);",
					"// });",
					"",
					"pm.visualizer.set(template, {",
					"    response: fieldsAndData,",
					"    numberOfResults: responseData ? responseData.length : 0",
					"});"
				]
			}
		}
	],
	"variable": [
		{
			"key": "proto",
			"value": "https",
			"type": "string"
		},
		{
			"key": "baseUrl",
			"value": "{{proto}}://{{server}}/webservices/{{clientRef}}/rest",
			"type": "string"
		},
		{
			"key": "router-salt",
			"value": "",
			"type": "string"
		},
		{
			"key": "analytics-salt",
			"value": "",
			"type": "string"
		},
		{
			"key": "cobundu-salt",
			"value": "",
			"type": "string"
		},
		{
			"key": "maintenance-salt",
			"value": "",
			"type": "string"
		}
	]
}