NAV
shell

Introduction

This is the documentation for the Proximity API. This is currently a 'living document', and will be continuously expanded as more endpoints are made ready.

For high level design & concepts, consider familiarizing yourself with the following documentation:

Notes on Retrieving Data

Deleted entries and Suspended Entries

Suspended entries will be returned by all LIST and GET ONE endpoints by default with intervention.

Deleted entries will not be returned by all LIST endpoints, unless the item is specified directly by being given in the ids[] search filter. In this case, this item explicitly requested item will be returned.

The same logic applies to the GET ONE. This will return deleted items if specified explicitly.

Please note, this only applies to endpoints supporting the ids[] filter for the LIST endpoint.

Authentication

To authorize, use both the client key and the authorization token:

# With shell, you can just pass the correct header with each request
curl "api_endpoint_here" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token"

Make sure you use both pieces of information.

Currently, authentication is done via external SSO idP. Once a token has been created, use the token along with the client key to make the API requests. You can obtain your client key using the /clients endpoints.

Authorization: <your-auth-token>
X-Client-Key: <client-key>

Basic schema information

The API follows (with a few exceptions) strict rules regarding REST and idempotency. When creating or saving an object, you must give the complete object. This is part of good REST practice to ensure there are no 'side effects' to other fields that you do not know about. If a field is incorrect, it will give a 400 BAD REQUEST validation error.

However, any fields prefixed with an underscore _ are an exception. These are generated fields are only exist in the return object. Examples of these are:

Permissions

Every object which supports permissions, will return a __permissions__ array. This is an array of permissions that the current logged in user can perform on each object.

Sometimes, this is omitted. The reason for this could be one that follows:

If this array is NOT given, then assume you have full permission on this object that the system permits.

Auth

These are endpoints that deal with auth events pertaining specifically to Proximity.

An example of these is the guest login. For instance, a guest login is specifically permitted to a party in Proximity and is not related to the Concert Apps suite as a whole.

Note, currently using /auth2 to avoid collision with legacy endpoints. These will eventually be changed to /auth

Without exception, these endpoints all require X-Client-Key to be given, but may or may not require a valid auth token. (Which they may not have)

POST Initiate guest login session

curl -X POST "https://<api-url>/auth2/guests/initiate" \
  -H "X-Client-Key: client-key" \
  -H "Content-Type: application/json" \
  --data '{
    "dk": "your-client-url-domain",
    "email": "your-email@sixfactor.com"
  }'

A valid response will yield a 202 ACCEPTED.

Please note that a 202 ACCEPTED will be given on all occassions. This is due to standard OWASP security practices to ensure we do not leak any information as to if an email is valid in the system or not, or if that email is permitted guest login (at which point we just indicated to a potential mal-actor that this is a valid login email they can use as an attack vactor)

An Email will then be sent to the email address if:

1) Email identity exists for a party user 2) Party/user has Allow OTP enabled.

In the email, the constructed URL uses the given dk (domain key). This is what you used on the original sign in to find out which client/tenant the vanity domain belongs to. In this case, we use the same to match back to ensure the domain belongs to the tenant, and then construct a URL for the email recipient to go to.

The link will be:

https://[domain-key]/auth/guest?token=[token]

You will use the token (the OTP) in your next request with the API to get a JWT issued.

POST Confirm guest login session with OTP

curl "-X POST https://<api-url>/auth2/guests/confirm" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "token": "the-otp-token"
  }'

A valid response will yield a 200 OK.

{
  "data": {
    "session": {
      "dk": "your domain key",
      "user_id": "user id for the user",
      "email": "the email used",,
      "app_id": "what app this belongs to, ie proximity"
    },
    "access_token": "the-access-token-jwt"
  }
}

Once this operation is complete, use access_token as you would any other JWT.

Assets

NOTE Section still under development - new fields and endpoints will be added as time goes on

Methods for dealing with the Asset object in the system.

Assets are essentially what we understand as locations in the system. They can be configured with different types. This new name is to replace the existing location type in the system.

LIST Assets

curl "https://<api-url>/assets" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "deadc0de-1111-4b7a-a990-111111111111",
    "name": "Asset A",
    "description": "Asset A description",
    "type_id": "deadc0de-1111-4aaf-a965-e4a096bd3f99",
    "entity_id": "deadc0de-1111-4b7a-a990-777777777777",
    "parent_id": "deadc0de-1111-4b7a-a990-222222222222",
    "stats": [{
      "contracts": 10,
      "services": 5,
      "assets": 2,
      "entities": 2
    }],
    "legacy": {
      "building_id": null,
      "location_id": "deadc0de-1111-4b7a-a990-111111111111"
    },
    "is_hidden": false,
    "suspended_at": null,
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2021-07-02T16:32:48.638Z",
    "deleted_at": null
  }, {
    "id": "deadc0de-1111-4b7a-a990-222222222222",
    "name": "Building A",
    "description": "Building Desc A",
    "type_id": "deadc0de-2222-4565-92ca-13d996d92ed1",
    "entity_id": null,
    "parent_id": null,
    "stats": [{
      "contracts": 0,
      "services": 0,
      "assets": 0,
      "entities": 0
    }],
    "legacy": {
      "building_id": "deadc0de-1111-4b7a-a990-222222222222",
      "location_id": null
    },
    "is_hidden": false,
    "suspended_at": null,
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2022-07-02T16:32:48.638Z",
    "deleted_at": null,
    "__permissions__": [
      "asset.view",
      "asset.create",
      "asset.update"
    ]
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "total": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of assets, with any given filters applied.

HTTP Request

GET https://<api-url>/assets

Query Parameters

Parameter Default Description
ids[] null Filter results by these asset IDs
keywords null Filter results by the given keywords. Keywords search across name.
type_id null Filter results by the given type ID
party_id null Filter results by the given party ID
entity_id null Filter results by the given entity ID
service_id null Filter results by the given service ID
contract_id null Filter results by the given contract ID
parent_id null Filter results by the given parent ID
exclude_containers null Exclude containers from the result set.
include[] null Include extra embeded non-resource elements (See list below)
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Include Parameters

Option Description
stats Includes object stats. This includes total contracts and services at this point.

Note, entities and assets will be completed following the db upgrades

Sorting fields

Field Description
name Sort by name
description Sort by description
type Sort by type
entity_name Sort by entity name
total_contracts Sort by total contract count
total_parties Sort by total parties count
created Sort by create date
updated Sort by update date

Note, these will be completed following db upgrades

total_entities | Sort by total entities total_assets | Sort by total number of child assets

LIST Asset Types

These are types for the assets. See Asset Type

curl "https://<api-url>/assets/~/types" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "Site",
    "config": {
      "require_parent": false,
      "allow_parents": [],
      "can_inherit": false,
      "permit_address": true,
      "permit_geo": true,
      "geo_update_freq": null,
      "is_container": true,
      "is_system": true,
    },
    "created_at": "2021-08-24T15:22:50.557Z",
    "updated_at": "2021-08-24T15:22:50.557Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Building",
    "config": {
      "require_parent": false,
      "allow_parents": [
        "deadc0de-1111-4aaf-a965-e4a096bd3f99",
        "deadc0de-2222-4aaf-a965-e4a096bd3f99"
      ],
      "can_inherit": true,
      "permit_address": true,
      "permit_geo": true,
      "geo_update_freq": null,
      "is_container": true,
      "is_system": true,
    },
    "created_at": "2021-08-24T15:22:50.557Z",
    "updated_at": "2021-08-24T15:22:50.557Z",
    "deleted_at": null
  }]
}

This endpoint retrieves a result set of asset types. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

HTTP Request

GET https://<api-url>/assets/~/types

GET an Asset

curl "https://<api-url>/assets/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "deadc0de-1111-4b7a-a990-111111111111",
    "name": "Asset A",
    "description": "Asset A description",
    "type_id": "deadc0de-1111-4aaf-a965-e4a096bd3f99",
    "entity_id": "deadc0de-1111-4b7a-a990-777777777777",
    "parent_id": "deadc0de-1111-4b7a-a990-222222222222",
    "phone": "+15551112222",
    "floor_unit": "123",
    "year_built": null,
    "building_floor": "11",
    "num_floors_units": null,
    "strata": null,
    "service_ids": [
      "deadc0de-1111-4849-a096-444444444444",
      "deadc0de-2222-4849-a096-444444444444"
    ],
    "party_ids": [
      "deadc0de-1111-4849-a096-555555555555",
      "deadc0de-2222-4849-a096-555555555555"
    ],
    "address": {
      "unit": "100",
      "street": "station road",
      "locale": "collingham",
      "city": "newark",
      "region": "nottinghamshire",
      "postal": null,
      "country": "gb",
      "lat": 53.144647814788804,
      "long": -0.7552475559891426
    },
    "geo": {
      "lat": null,
      "long": null,
      "radius": null,
      "wkt": null
    },
    "images": [
      "http://image.url"
    ],
    "legacy": {
      "building_id": null,
      "location_id": "deadc0de-1111-4b7a-a990-111111111111"
    },
    "is_hidden": false,
    "suspended_at": null,
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2021-07-02T16:32:48.638Z",
    "deleted_at": null,
    "__permissions__": [
      "asset.view",
      "asset.create",
      "asset.update"
    ]
  }
}

In the case that no asset is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific asset by the given id.

HTTP Request

GET https://<api-url>/assets/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the asset to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eAssetNotFound The asset could not be found / invalid ID.

Include Parameters

Option Description
parentage NOTE Appears to be implemented, please verify. May allow viewing of Assets' parentage.
images Includes a list of image URLs for this asset

CREATE a new Asset

curl -X POST "https://<api-url>/assets" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "A created asset",
    "description": "A brand new asset",
    "type_id": "deadc0de-1111-4aaf-a965-e4a096bd3f99",
    "entity_id": "deadc0de-1111-4b7a-a990-777777777777",
    "parent_id": "deadc0de-1111-4b7a-a990-222222222222",
    "phone": "+15551112222",
    "floor_unit": "123",
    "year_built": null,
    "building_floor": "11",
    "num_floors_units": null,
    "strata": null,
    "service_ids": [
      "deadc0de-1111-4849-a096-444444444444",
      "deadc0de-2222-4849-a096-444444444444"
    ],
    "party_ids": [
      "deadc0de-1111-4849-a096-555555555555",
      "deadc0de-2222-4849-a096-555555555555"
    ],
    "address": {
      "unit": "100",
      "street": "station road",
      "locale": "collingham",
      "city": "newark",
      "region": "nottinghamshire",
      "postal": null,
      "country": "gb",
      "lat": 53.144647814788804,
      "long": -0.7552475559891426
    },
    "geo": null,
    "is_hidden": false,
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "A created asset",
    "description": "A brand new asset",
    "type_id": "deadc0de-1111-4aaf-a965-e4a096bd3f99",
    "entity_id": "deadc0de-1111-4b7a-a990-777777777777",
    "parent_id": "deadc0de-1111-4b7a-a990-222222222222",
    "phone": "+15551112222",
    "floor_unit": "123",
    "year_built": null,
    "building_floor": "11",
    "num_floors_units": null,
    "strata": null,
    "service_ids": [
      "deadc0de-1111-4849-a096-444444444444",
      "deadc0de-2222-4849-a096-444444444444"
    ],
    "party_ids": [
      "deadc0de-1111-4849-a096-555555555555",
      "deadc0de-2222-4849-a096-555555555555"
    ],
    "address": {
      "unit": "100",
      "street": "station road",
      "locale": "collingham",
      "city": "newark",
      "region": "nottinghamshire",
      "postal": null,
      "country": "gb",
      "lat": 53.144647814788804,
      "long": -0.7552475559891426
    },
    "geo": null,
    "is_hidden": false,
    "suspended_at": "2023-01-01T12:45:00.000Z",
    "__permissions__": [
      "asset.view",
      "asset.create",
      "asset.update"
    ]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an asset with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/assets

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type_id uuid Valid asset type ID Entity Type Yes
entity_id uuid Valid entity ID Yes
parent_id uuid Valid parent ID, depending on restrictions given by type Yes
phone string Valid e164 number format Yes
floor_unit string Max length 150, unit number Yes
year_built string Max length 50, if building, year built. Will move to custom field. Yes
building_floor string Max length 50. Will move to custom field. Yes
num_floors_units string Max length 50. For buildings, number of floors or units. Will move to custom field. Yes
stata string Max length 50. Stata ID for building. Will move to custom fields Yes
service_ids uuid[] Valid service ids. Use empty array for empty. No
party_ids uuid[] Valid party ids. Use empty array for empty. No
address Address If type permits address, otherwise null Yes
geo GeoZone If type permits geo, otherwise null Yes
is_hidden boolean True if this asset is hidden
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eAssetTypeNotFound Asset type ID given could not be found
400 BAD REQUEST eAddressNotPermitted Asset type does not permit an address
400 BAD REQUEST eGeoNotPermitted Asset type does not permit geo
400 BAD REQUEST eParentNotPermitted Asset type does not permit a parent, or a parent of the type given.
400 BAD REQUEST eParentRequired Asset type requires a parent
400 BAD REQUEST eEntityNotPermitted Asset type does not permit entities assigned to it.
400 BAD REQUEST eEntityNotFound Entity ID given could not be found
400 BAD REQUEST eAssetRequiresEntity Asset requires an entity
400 BAD REQUEST eAssetRequiresLocationInfo Asset requires location information (ie, geo or address)
400 BAD REQUEST eAssetRequiresParent Asset requires a parent
400 BAD REQUEST eContainerTypeChangeRestricted You cannot change an asset from a container type to a non-container type and vice versa
400 BAD REQUEST eAssignedObjectsNotPermitted This asset type does not permit assigned objects.
400 BAD REQUEST eAttemptSaveWithMissingParties One or more of the parties given do not exit
400 BAD REQUEST eAttemptSaveWithMissingServices One or more of the services given do not exit

UPDATE an Asset

curl -X PUT "https://<api-url>/assets/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "An updated asset",
    "description": "An updated new asset",
    "type_id": "deadc0de-1111-4aaf-a965-e4a096bd3f99",
    "entity_id": "deadc0de-1111-4b7a-a990-777777777777",
    "parent_id": "deadc0de-1111-4b7a-a990-222222222222",
    "phone": "+15551112222",
    "floor_unit": "123",
    "year_built": null,
    "building_floor": "11",
    "num_floors_units": null,
    "strata": null,
    "service_ids": [
      "deadc0de-1111-4849-a096-444444444444",
      "deadc0de-2222-4849-a096-444444444444"
    ],
    "party_ids": [
      "deadc0de-1111-4849-a096-555555555555",
      "deadc0de-2222-4849-a096-555555555555"
    ],
    "address": {
      "unit": "100",
      "street": "station road",
      "locale": "collingham",
      "city": "newark",
      "region": "nottinghamshire",
      "postal": null,
      "country": "gb",
      "lat": 53.144647814788804,
      "long": -0.7552475559891426
    },
    "geo": {
      "lat": 53.144647814788804,
      "long": -0.7552475559891426,
      "radius": 343,
      "wkt": "POLYGON(23,343,234,23)"
    },
    "is_hidden": false,
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "A created asset",
    "description": "A brand new asset",
    "type_id": "deadc0de-1111-4aaf-a965-e4a096bd3f99",
    "entity_id": "deadc0de-1111-4b7a-a990-777777777777",
    "parent_id": "deadc0de-1111-4b7a-a990-222222222222",
    "phone": "+15551112222",
    "floor_unit": "123",
    "year_built": null,
    "building_floor": "11",
    "num_floors_units": null,
    "strata": null,
    "service_ids": [
      "deadc0de-1111-4849-a096-444444444444",
      "deadc0de-2222-4849-a096-444444444444"
    ],
    "party_ids": [
      "deadc0de-1111-4849-a096-555555555555",
      "deadc0de-2222-4849-a096-555555555555"
    ],
    "address": {
      "unit": "100",
      "street": "station road",
      "locale": "collingham",
      "city": "newark",
      "region": "nottinghamshire",
      "postal": null,
      "country": "gb",
      "lat": 53.144647814788804,
      "long": -0.7552475559891426
    },
    "geo": {
      "lat": 53.144647814788804,
      "long": -0.7552475559891426,
      "radius": 343,
      "wkt": "POLYGON(23,343,234,23)"
    },
    "is_hidden": false,
    "suspended_at": "2023-01-01T12:45:00.000Z",
    "__permissions__": [
      "asset.view",
      "asset.create",
      "asset.update"
    ]
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing asset with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/assets/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the asset to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type_id uuid Valid asset type ID Entity Type Yes
entity_id uuid Valid entity ID Yes
parent_id uuid Valid parent ID, depending on restrictions given by type Yes
phone string Valid e164 number format Yes
floor_unit string Max length 150, unit number Yes
year_built string Max length 50, if building, year built. Will move to custom field. Yes
building_floor string Max length 50. Will move to custom field. Yes
num_floors_units string Max length 50. For buildings, number of floors or units. Will move to custom field. Yes
stata string Max length 50. Stata ID for building. Will move to custom fields Yes
service_ids uuid[] Valid service ids. Use empty array for empty. No
party_ids uuid[] Valid party ids. Use empty array for empty. No
contract_ids uuid[] Valid contract ids. Use empty array for empty. No
address Address If type permits address, otherwise null Yes
geo GeoZone If type permits geo, otherwise null Yes
is_hidden boolean True if this asset is hidden
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eAssetNotFound Asset ID given could not be found
400 BAD REQUEST eAssetTypeNotFound Asset type ID given could not be found
400 BAD REQUEST eAddressNotPermitted Asset type does not permit an address
400 BAD REQUEST eGeoNotPermitted Asset type does not permit geo
400 BAD REQUEST eParentNotPermitted Asset type does not permit a parent, or a parent of the type given.
400 BAD REQUEST eParentRequired Asset type requires a parent
400 BAD REQUEST eEntityNotPermitted Asset type does not permit entities assigned to it.
400 BAD REQUEST eEntityNotFound Entity ID given could not be found
400 BAD REQUEST eAssetRequiresEntity Asset requires an entity
400 BAD REQUEST eAssetRequiresLocationInfo Asset requires location information (ie, geo or address)
400 BAD REQUEST eAssetRequiresParent Asset requires a parent
400 BAD REQUEST eContainerTypeChangeRestricted You cannot change an asset from a container type to a non-container type and vice versa
400 BAD REQUEST eAssignedObjectsNotPermitted This asset type does not permit assigned objects.
400 BAD REQUEST eAttemptSaveWithMissingParties One or more of the parties given do not exit
400 BAD REQUEST eAttemptSaveWithMissingServices One or more of the services given do not exit

BATCH UPDATE Assets

curl -X PATCH "https://<api-url>/assets" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "entity_id": "2bd2846a-018c-4131-92eb-fbbba8ac4eeb",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "entity_id": "1a48ea14-24a7-420f-998a-78d498034cf6",
      "parent_id": "910abce5-2846-44ab-84c8-cf8a0581c197",
      "party_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
      "party_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
      "service_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
      "service_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
      "suspended_at": "2023-01-01T12:35:00.000Z",
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "entity_id": null,
      "parent_id": null,
      "suspended_at": null,
      "deleted_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "entity_id": "2bd2846a-018c-4131-92eb-fbbba8ac4eeb",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "entity_id": "1a48ea14-24a7-420f-998a-78d498034cf6",
    "parent_id": "910abce5-2846-44ab-84c8-cf8a0581c197",
    "party_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
    "party_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
    "service_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
    "service_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
    "suspended_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "entity_id": null,
    "suspended_at": null,
    "deleted_at": null
  }]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch Asset fields. To help maintain the integrity of an asset, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The party, contract, and service ID fields will allow assigning and unassigning party, contract, and services from the given entity. Note, only one can be given at a time for each asset.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/assets

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
parent_id uuid Valid parent id Yes
entity_id uuid Valid entity id Yes
party_id_assign uuid None Yes, but will no-op
party_id_unassign uuid None Yes, but will no-op
service_id_assign uuid None Yes, but will no-op
service_id_unassign uuid None Yes, but with no-op
suspended_at datetime Will de-activate (suspend) the asset if set to a date. null means re-activate Yes
deleted_at datetime Will delete the asset if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' assets endpoint.

Config

Returns the current configuration for the environment based on the current signed in user's permissions.

This includes various information which can be used to configure the environment the frontend provides to that user, such as:

GET config

curl "https://<api-url>/config" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"
{
  "data": {
    "theme": [{
      "key": "login.logo",
      "value": "https://via.placeholder.com/250",
      "domain": "login"
    }, {
      "key": "bg.color",
      "value": "#fefefe",
      "domain": "crud-admin"
    }],
    "phrasing": [{
      "key": "login.welcome",
      "value": "Welcome to the custom text for the login page",
      "locale": "en-CA"
    }],
    "vocab": [{
      "key": "customer",
      "locale": "en-CA",
      "singular": "Contact",
      "plural": "Contacts"
    }, {
      "key": "asset",
      "locale": "en-CA",
      "singular": "Location",
      "plural": "Locations"
    }],
    "settings": [{
      "key": "some.key.1",
      "value": "configuration setting 1",
      "domain": "login"
    }],
    "permissions": [
      "contracts.create",
      "contracts.view"
    ]
  }
}

Returns all the current configuration for Proximity for the given tenant & signed in user.

Theme

This current theme information provided for this Proximity instance for the tenant.

Phrasing

These are custom messages and phrases specific to the given tenant

Vocab

These are changes in system names for the given tenant. For instance, Assets could be set to Locations.

settings

These are settings specific to the current user

permissions

A list of permissions for the current user. These are a collection of all permissions avaiable. These do not include permission access that is also derived from the Operational Group or Groups the current user is also in.

GET Theme Config

curl "https://<api-url>/config/theme" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"
{
  "data": [{
    "key": "login.logo",
    "value": "https://via.placeholder.com/250",
    "domain": "login"
  }, {
    "key": "bg.color",
    "value": "#fefefe",
    "domain": "crud-admin"
  }]
}

Contracts

NOTE Section still under development

Methods for dealing with the Contract object in the system.

All contracts will have a provider and a consumer. These fields will come soon as the data model from the existing system is upgraded. (Currently only one-sided behaviour is permitted limited to entities only.)

Note on development

Currently, this endpoint is providing a 'facade' for the legacy contract endpoint in the system. The id for the contracts are the same as the contract_id for the existing contracts. Legacy endpoints at this juncture can still be used interchangably, but newer functionality should be preferred where possible as older legacy endpoints will be deprecated as the data model is migrated.

LIST contracts

curl "https://<api-url>/contracts" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Contract A",
    "description": "Contract description",
    "starts_at": "2022-01-01T12:35:00.000Z",
    "expires_at": "2023-01-01T12:35:00.000Z",
    "url": "https://drive.google.com/some-document.pdf",
    "stats": [{
      "entites": 4,
      "assets": 2
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Contract B",
    "starts_at": null,
    "expires_at": null,
    "url": null,
    "stats": [{
      "entities": 0,
      "assets": 0
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "contracts.view",
      "contracts.create",
      "contracts.update"
    ]
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "total": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of contracts, with any given filters applied.

HTTP Request

GET https://<api-url>/contracts

Query Parameters

Parameter Default Description
ids[] null Filter results by these contract IDs
party_id null Filter results for those associated with this party ID
service_id null Filter results for those associated with this service ID
asset_id null Filter results for those associated with this contract ID
entity_ids null Filter results for those associated with these entity IDs (string[])
keywords null Filter results by the given keywords. Keywords search across name.
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Embed/Include Parameters

Option Description
counts Includes object count totals, including resources and assets.

Sorting fields

Field Description
name Sort by name.
description Sort by description
total_assets Sort by total asset count
total_entities Sort by total entities count
expiry Sort by expiry
created Sort by create date
updated Sort by update date

LIST Contract Roles

These are role associations for the contract's contacts and owners. See Contract Role Type

curl "https://<api-url>/contracts/~/roles" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "Customer Success",
    "description": "Some description",
    "type": "owner",
    "created_at": "2023-04-28T20:46:27.270Z"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Primary Contact",
    "description": "Some description",
    "type": "contact",
    "created_at": "2023-04-28T20:46:27.270Z"
  }]
}

This endpoint retrieves a result set of contract roles. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

HTTP Request

GET https://<api-url>/contracts/~/roles

GET a Contract

curl "https://<api-url>/contracts/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Contract A",
    "description": "Contract description",
    "starts_at": "2022-01-01T12:35:00.000Z",
    "expires_at": "2023-01-01T12:35:00.000Z",
    "url": "https://drive.google.com/some-document.pdf",
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "party_ids": [
      "deadc0de-a110-4e58-a166-73c6e25cab04",
      "deadc0de-ba81-45f3-a6ae-321d893ec3df"
    ],
    "service_ids": [
      "deadc0de-5555-4849-a096-5800072f28c2",
      "deadc0de-5555-4b26-89eb-4ed6de8baa53"
    ],
    "asset_ids": [
      "deadc0de-7777-4849-a096-5800072f28c2",
      "deadc0de-7777-4b26-89eb-4ed6de8baa53"
    ],
    "entity_ids": [
      "deadc0de-8888-4849-a096-5800072f28c2",
      "deadc0de-8888-4b26-89eb-4ed6de8baa53"
    ],
    "media_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "contracts.view",
      "contracts.create",
      "contracts.update"
    ]
  }
}

In the case that no contract is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific contract by the given id.

HTTP Request

GET https://<api-url>/contracts/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the contract to retrieve

Embed/Include Parameters

Option Description
counts Includes object count totals, including resources and assets.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eContractNotFound The contract could not be found / invalid ID.

CREATE a new Contract

curl -X POST "https://<api-url>/contracts" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "A created contract",
    "description": "Created contract description",
    "starts_at": "2022-01-01T12:35:00.000Z",
    "expires_at": "2023-01-01T12:35:00.000Z",
    "url": "https://drive.google.com/some-document.pdf",
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "party_ids": [
      "deadc0de-a110-4e58-a166-73c6e25cab04",
      "deadc0de-ba81-45f3-a6ae-321d893ec3df"
    ],
    "service_ids": [
      "deadc0de-5555-4849-a096-5800072f28c2",
      "deadc0de-5555-4b26-89eb-4ed6de8baa53"
    ],
    "asset_ids": [
      "deadc0de-7777-4849-a096-5800072f28c2",
      "deadc0de-7777-4b26-89eb-4ed6de8baa53"
    ],
    "entity_ids": [
      "deadc0de-8888-4849-a096-5800072f28c2",
      "deadc0de-8888-4b26-89eb-4ed6de8baa53"
    ],
    "media_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "A created Entity",
    "description": "Created Entity description",
    "starts_at": "2022-01-01T12:35:00.000Z",
    "expires_at": "2023-01-01T12:35:00.000Z",
    "url": "https://drive.google.com/some-document.pdf",
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "party_ids": [
      "deadc0de-a110-4e58-a166-73c6e25cab04",
      "deadc0de-ba81-45f3-a6ae-321d893ec3df"
    ],
    "service_ids": [
      "deadc0de-5555-4849-a096-5800072f28c2",
      "deadc0de-5555-4b26-89eb-4ed6de8baa53"
    ],
    "asset_ids": [
      "deadc0de-7777-4849-a096-5800072f28c2",
      "deadc0de-7777-4b26-89eb-4ed6de8baa53"
    ],
    "entity_ids": [
      "deadc0de-8888-4849-a096-5800072f28c2",
      "deadc0de-8888-4b26-89eb-4ed6de8baa53"
    ],
    "media_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "suspended_at": "2023-01-01T12:45:00.000Z",
    "__permissions__": [
      "contracts.view",
      "contracts.create",
      "contracts.update"
    ]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an entity with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

Media IDs can be added from uploaded media via the media endpoint. This design will come later. Use an empty array for now

HTTP Request

POST https://<api-url>/entities

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
starts_at datetime Use ISO8601 compliant timestamp Yes
expires_at datetime Use ISO8601 compliant timestamp Yes
url string Max length 1000 Yes
owners PartyAssociation[] Use empty array for empty No
contacts PartyAssociation[] Use empty array for empty No
party_ids uuid[] Valid party ids. Use empty array to empty. No
service_ids uuid[] Valid service ids. Use empty array for empty. No
asset_ids uuid[] Valid asset ids. Use empty array for empty. No
entities_ids uuid[] Valid entity ids. Use empty array for empty. No
media_ids uuid[] Valid media ids. Use empty array for empty. No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eAttemptSaveWithMissingServices Some of the service ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingParties Some of the parties ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingRoles Some of the role ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingOwners Some or all of the owner ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingContacts Some or all of the contacts ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingMedia Some or all of the media ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingEntities Some or all of the entity ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingAssets Some or all of the asset ids you've given do not exist

UPDATE a Contract

curl -X PUT "https://<api-url>/contracts/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "An updated contract",
    "description": "Updated contract description",
    "starts_at": "2022-01-01T12:35:00.000Z",
    "expires_at": "2023-01-01T12:35:00.000Z",
    "url": "https://drive.google.com/some-document.pdf",
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "party_ids": [
      "deadc0de-a110-4e58-a166-73c6e25cab04",
      "deadc0de-ba81-45f3-a6ae-321d893ec3df"
    ],
    "service_ids": [
      "deadc0de-5555-4849-a096-5800072f28c2",
      "deadc0de-5555-4b26-89eb-4ed6de8baa53"
    ],
    "asset_ids": [
      "deadc0de-7777-4849-a096-5800072f28c2",
      "deadc0de-7777-4b26-89eb-4ed6de8baa53"
    ],
    "entity_ids": [
      "deadc0de-8888-4849-a096-5800072f28c2",
      "deadc0de-8888-4b26-89eb-4ed6de8baa53"
    ],
    "media_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "An updated contract",
    "description": "Updated contract description",
    "starts_at": "2022-01-01T12:35:00.000Z",
    "expires_at": "2023-01-01T12:35:00.000Z",
    "url": "https://drive.google.com/some-document.pdf",
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "party_ids": [
      "deadc0de-a110-4e58-a166-73c6e25cab04",
      "deadc0de-ba81-45f3-a6ae-321d893ec3df"
    ],
    "service_ids": [
      "deadc0de-5555-4849-a096-5800072f28c2",
      "deadc0de-5555-4b26-89eb-4ed6de8baa53"
    ],
    "asset_ids": [
      "deadc0de-7777-4849-a096-5800072f28c2",
      "deadc0de-7777-4b26-89eb-4ed6de8baa53"
    ],
    "entity_ids": [
      "deadc0de-8888-4849-a096-5800072f28c2",
      "deadc0de-8888-4b26-89eb-4ed6de8baa53"
    ],
    "media_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "suspended_at": "2023-01-01T12:45:00.000Z",
    "__permissions__": [
      "contracts.view",
      "contracts.create",
      "contracts.update"
    ]
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing contract with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

Media IDs can be added from uploaded media via the media endpoint. This design will come later. Use an empty array for now

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/contract/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the contract to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
starts_at datetime Use ISO8601 compliant timestamp Yes
expires_at datetime Use ISO8601 compliant timestamp Yes
url string Max length 1000 Yes
owners PartyAssociation[] Use empty array for empty No
contacts PartyAssociation[] Use empty array for empty No
party_ids uuid[] Valid party ids. Use empty array to empty. No
service_ids uuid[] Valid service ids. Use empty array for empty. No
asset_ids uuid[] Valid asset ids. Use empty array for empty. No
entities_ids uuid[] Valid entity ids. Use empty array for empty. No
media_ids uuid[] Valid media ids. Use empty array for empty. No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eContractNotFound Entity ID given could not be found
400 BAD REQUEST eAttemptSaveWithMissingServices Some of the service ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingParties Some of the parties ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingRoles Some of the role ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingOwners Some or all of the owner ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingContacts Some or all of the contacts ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingEntities Some or all of the entity ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingAssets Some or all of the asset ids you've given do not exist

BATCH UPDATE Contracts

curl -X PATCH "https://<api-url>/contracts" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "suspended_at": "2023-01-01T12:35:00.000Z",
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "party_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
      "party_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
      "asset_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
      "asset_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
      "service_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
      "service_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
      "entity_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
      "entity_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
      "suspended_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "suspended_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "party_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
    "party_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
    "asset_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
    "asset_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
    "service_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
    "service_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
    "entity_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
    "entity_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
    "suspended_at": null
  }]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch contract fields. To help maintain the integrity of a contract, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The party & service ID fields will allow assigning and unassigning party and services from the given entity. Note, only one can be given at a time for each contract.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/contracts

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
party_id_assign uuid None Yes, but will no-op
party_id_unassign uuid None Yes, but will no-op
service_id_assign uuid None Yes, but will no-op
service_id_unassign uuid None Yes, but with no-op
entity_id_assign uuid None Yes, but will no-op
entity_id_unassign uuid None Yes, but with no-op
asset_id_assign uuid None Yes, but will no-op
asset_id_unassign uuid None Yes, but with no-op
suspended_at datetime Will de-activate (suspend) the entity if set to a date. null means re-activate Yes
deleted_at datetime Will delete the entity if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' datazones endpoint.

DELETE a Contract

curl -X DELETE "https://<api-url>/contracts/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given contract by id.

HTTP Request

DELETE https://<api-url>/contracts/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eContractNotFound The contract could not be found / invalid ID.

Datazones

Methods for dealing with the DataZone object in the system.

Datazones in the system have 2 possible base types (See DataZone Types)

A geo datazone is a zone described by various geo parameters. These include

The geo datazone an also have the following properties:

A commercial datazone can have the following propreties:

The following hard rules are applied:

  1. A Commercial datazone cannot contain any geo information, addresses.
  2. A Geo datazone cannot contain at industries.

See the Groups section, and the diagram within to better understand how datazones fall into the bigger picture of groups and operational groups.

Dynamic & static datazones

The is_dynamic flag can be applied to both types of datazone.

When set to true on the commercial type, industries are used to gauge the commercial zone and the explicit contract_ids and entity_ids are ignored. Please note, these are kept, and can still be saved and edited. This is to permit easier modification, and the ability to switch between the two modes without data loss.

For the geo datazone type, setting the is_dynamic field will mean that the datazone will be using the geozones belonging to it, versus the civic addresses in the addresses array.

Pulling external data

Pull outside data has to be done using the resource endpoints of the data you wish to achieve. The API has been deliberately designed this way (Domain Driven & Bounded Context), to enable better future scaling within a microservice based architecture.

Where to go for the external data

For DataZone Type Data Where to go
geo geocode This endpoint, namely /datazones/{id}/geozones
commercial entities Endpoint: /entities
commercial contracts Endpoint: /contracts
commercial industries Endpoint /industries

Differences between list resource and single resource

In the interest of performance and scaling, the resource representation in the list response is shortened compared to the full resource response as seen in the "single" get, post, and put responses.

Items that do not exist on the list response include:

LIST DataZones

curl "https://<api-url>/datazones" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Vancouver Greater",
    "type": "commercial",
    "is_dynamic": true,
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "stats": [{
      "operational": 4
    }],
    "geo_zones": [],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "datazone.commercial.view",
      "datazone.commercial.update"
    ]
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Calgary",
    "type": "geo",
    "is_dynamic": false,
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "stats": [{
      "operational": 2
    }],
    "geo_zones": [{
      "id": "bc9d1a95-b6d1-4e8e-99a3-408b338931a0",
      "name": "My office",
      "long": 100.213,
      "lat": 48.234,
      "radius": 0,
      "wkt": null
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "datazone.commercial.view",
      "datazone.geo.update"
    ]
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "items": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }]
}

This endpoint retrieves a result set of datazones, with any given filters applied.

By default, this payload does not include any stats, since this operational can be expensive. Adding counts to the include array will cause this to be calculated and returned.

HTTP Request

GET https://<api-url>/datazones

Query Parameters

Parameter Default Description
ids[] null Filter results by these contract IDs
type null Filter results by the given type ID
keywords null Filter results by the given keywords. Keywords search across name and description. Min characters 2.
entity_id null Filter the results by the datazones with these entities.
include[] null Include extra embeded non-resource elements (See list below)
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Embed/Include Parameters

Option Description
counts Includes all the inherited object counts from users, territories, & features.
geozones Includes all available geozones

Sorting fields

Field Description
name Sort by name.
description Sort by description
total_operational_groups Sort by total operational groups
created Sort by create date
updated Sort by update date

Note, sorting on individual object counts will come at a future time

LIST GeoZones for DataZone

curl "https://<api-url>/datazones/6fd5b5c4-0978-49f6-b301-85f60434c1b9/geozones" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found. This data is absolute and contains no pagination or sorting.

{
  "data": [{
    "id": "a0ece4bf-5d87-4d4c-89e8-f06fd0074c5f",
    "name": "Downtown vancouver",
    "long": null,
    "lat": null,
    "radius": null,
    "wkt": "POLYGON(100.2341,48.3425,101.342,48.567)"
  }, {
    "id": "bc9d1a95-b6d1-4e8e-99a3-408b338931a0",
    "name": "My office",
    "long": 100.213,
    "lat": 48.234,
    "radius": 0,
    "wkt": null
  }, {
    "id": "6893814e-6f3e-4e38-bf2a-cd60dd2fe1c4",
    "name": "Somewhere else",
    "long": 99.111,
    "lat": 44.222,
    "radius": 30,
    "wkt": null
  }]
}

This endpoint retrieves a result set of GeoZones, belonging to a specifc datazone of type geo.

Requesting this of a datazone that is commercial will always return an empty dataset.

HTTP Request

GET https://<api-url>/datazones/<id>/geozones

GET a DataZone

curl "https://<api-url>/datazones/abfe045b-814e-4d31-98f5-f3d0a23437f1" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Vancouver Greater",
    "type": "commercial",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "is_dynamic": true,
    "addresses": [],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "industry_ids": [
      "975ce5ab-3a37-4a4f-a50f-82df38897d43"
    ],
    "entity_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "contract_ids": [
      "eeb586b1-5095-4ca8-96d4-288446cea05c"
    ],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

The baseline response for a geo object with addresses

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Vancouver Greater",
    "type": "commercial",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "is_dynamic": false,
    "addresses": [{
      "name": "Center",
      "unit": "100",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "lat": "52.023432",
      "long": "-0.126345"
    }, {
      "country": "gb",
      "region": "lincolnshire"
    }],
    "industry_ids": [],
    "contract_ids": [],
    "entity_ids": [],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "datazone.commercial.view",
      "datazone.commercial.update",
      "datazone.commercial.remove"
    ]
  }
}

An expanded result will include all the sub objects and their counts. Note, that although the counts will apply to the sub objects, the expanded "GET ONE" form with the industry, entity etc ids, will only apply to the parent object.

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Vancouver Greater",
    "type": "commercial",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "is_dynamic": true,
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "industry_ids": [
      "975ce5ab-3a37-4a4f-a50f-82df38897d43"
    ],
    "entity_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "contract_ids": [
      "eeb586b1-5095-4ca8-96d4-288446cea05c"
    ],
    "stats": [{
      "operational": 4
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "datazone.commercial.view",
      "datazone.commercial.update",
      "datazone.commercial.remove"
    ]
  }
}

In the case that no datazones are found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific datazone by the given id.

HTTP Request

GET https://<api-url>/datazones/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the datazone to retrieve
include[] null Include extra embeded non-resource elements.

Embed/Include Parameters

Option Description
counts Includes all the inherited object counts from users, territories, & features.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eDataZoneNotFound The datazone could not be found / invalid ID.

CREATE a DataZone

curl -X POST "https://<api-url>/datazones" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Vancouver Greater",
    "type": "commercial",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "is_dynamic": true,
    "industry_ids": [
      "975ce5ab-3a37-4a4f-a50f-82df38897d43"
    ],
    "entity_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "contract_ids": [
      "eeb586b1-5095-4ca8-96d4-288446cea05c"
    ],
    "suspended_at": null,
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Vancouver Greater",
    "type": "commercial",
    "is_dynamic": true,
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "industry_ids": [
      "975ce5ab-3a37-4a4f-a50f-82df38897d43"
    ],
    "entity_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "contract_ids": [
      "eeb586b1-5095-4ca8-96d4-288446cea05c"
    ],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "datazone.commercial.view",
      "datazone.commercial.update",
      "datazone.commercial.remove"
    ]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create a datazone with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/datazones

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type DataZone Type One of the valid types No
is_dynamic boolean If the datazone is dynamic or not. No
addresses Address[] For geo only, use empty [] otherwise No
owner_ids uuid[] Valid party IDs (Can use legacy user ids) No
industry_ids array of uuids Valid Industry IDs No
entity_ids array of uuids Valid Entity IDs No
contract_ids array of uuids Valid Contract IDs No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eAttemptTypeChange You cannot change the datazone type once created.
400 BAD REQUEST eAttemptSaveWithMissingContracts One or more of the contract_ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingIndustries One or more of the industry_ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingEntities One or more of the entity_ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingOwners One or more of the owner_ids you've given do not exist.

UPDATE a DataZone

curl -X PUT "https://<api-url>/datazones/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Vancouver Greater",
    "type": "commercial",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "is_dynamic": true,
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "industry_ids": [
      "975ce5ab-3a37-4a4f-a50f-82df38897d43"
    ],
    "entity_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "contract_ids": [
      "eeb586b1-5095-4ca8-96d4-288446cea05c"
    ],
    "suspended_at": null,
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Vancouver Greater",
    "type": "commercial",
    "is_dynamic": true,
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "industry_ids": [
      "975ce5ab-3a37-4a4f-a50f-82df38897d43"
    ],
    "entity_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "contract_ids": [
      "eeb586b1-5095-4ca8-96d4-288446cea05c"
    ],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "datazone.commercial.view",
      "datazone.commercial.update",
      "datazone.commercial.remove"
    ]
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing datazone with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/datazones/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the datazone to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type DataZone Type One of the valid types No
is_dynamic boolean Is the datazone dynamic or not No
addresses Address[] For geo only, use empty [] otherwise No
owner_ids uuid[] Valid party IDs (Can use legacy user ids) No
industry_ids array of uuids Valid Industry IDs No
entity_ids array of uuids Valid Entity IDs No
contract_ids array of uuids Valid Contract IDs No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eDataZoneNotFound The datazone could not be found / invalid ID.
400 BAD REQUEST eAttemptTypeChange You cannot change the datazone type once created.
400 BAD REQUEST eAttemptSaveWithMissingContracts One or more of the contract_ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingIndustries One or more of the industry_ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingEntities One or more of the entity_ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingOwners One or more of the owner_ids you've given do not exist.

UPDATE GeoZones for a DataZone

curl -X PUT "https://<api-url>/datazones/6fd5b5c4-0978-49f6-b301-85f60434c1b9/geozones" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "a0ece4bf-5d87-4d4c-89e8-f06fd0074c5f",
      "name": "Downtown Vancouver",
      "long": null,
      "lat": null,
      "radius": null,
      "wkt": "POLYGON(100.2341,48.3425,101.342,48.567)"
    }, {
      "id": "bc9d1a95-b6d1-4e8e-99a3-408b338931a0",
      "name": "Office",
      "long": 100.213,
      "lat": 48.234,
      "radius": 0,
      "wkt": null
    }, {
      "id": "6893814e-6f3e-4e38-bf2a-cd60dd2fe1c4",
      "name": "Other place",
      "long": 99.111,
      "lat": 44.222,
      "radius": 30,
      "wkt": null
    }]
  }'  

Note, this endpoint is idempotent, and expects an attribute data containing an array of all geozones for that datazone. A valid response will be a 200 OK, with the new state of geozones as an array

{
  "data": [{
    "id": "a0ece4bf-5d87-4d4c-89e8-f06fd0074c5f",
    "name": "Downtown Vancouver",
    "long": null,
    "lat": null,
    "radius": null,
    "wkt": "POLYGON(100.2341,48.3425,101.342,48.567)"
  }, {
    "id": "bc9d1a95-b6d1-4e8e-99a3-408b338931a0",
    "name": "Office",
    "long": 100.213,
    "lat": 48.234,
    "radius": 0,
    "wkt": null
  }, {
    "id": "6893814e-6f3e-4e38-bf2a-cd60dd2fe1c4",
    "name": "Other place",
    "long": 99.111,
    "lat": 44.222,
    "radius": 30,
    "wkt": null
  }]
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint is idempontent and will update all the geozones for the given datazone.

The body should be an array of all geozones within the attribute data. New attributes should have id set to null. Existing attributes should have their existing ids, and will be updated. Any existing geozones excluded from the list will be deleted.

If you try to update a geozone with an ID that does not exist (or exists for another datazone), this ID will be replaced.

The response from this method gives the new state of geozones for the datazones, will all IDs completed.

To summarize:

Geozone in list Action
id set to null Create this new geozone for the the datazone
id set to existing uuid Update this geozone
Geozone is omitted Geozone deleted.

HTTP Request

PUT https://<api-url>/datazones/<id>/geozones

URL Parameters

Parameter Data Type Description
ID uuid The ID of the datazone to update the geozones for

Parameters

Attribute Type Restrictions Null allowed
id uuid If not null, valid ID Yes, will create.
name string Less than 150 chars Yes
long number Between -180 and 180 Yes, if wkt given
lat number Between -90 and 90 Yes, if wkt given
radio integer Above 0 Yes
wkt string Must be given in long/lat are null Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eDataZoneNotFound The datazone could not be found / invalid ID.
400 BAD REQUEST eAttemptSaveGeoOnIncorrectType You are trying to update geozones on a commercial type datazone. This is not permitted.

BATCH UPDATE DataZones

curl -X PATCH "https://<api-url>/datazones" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "entity_id_assign": "b08e291e-2aee-4777-adf2-60c1115fd84a",
      "entity_id_unassign": "e74fe103-8bf6-4e98-be26-33a13c373ebb",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "suspended_at": "2023-01-01T12:35:00.000Z",
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "suspended_at": null,
      "deleted_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "entity_id_assign": "b08e291e-2aee-4777-adf2-60c1115fd84a",
    "entity_id_unassign": "e74fe103-8bf6-4e98-be26-33a13c373ebb",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "suspended_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "suspended_at": null,
    "deleted_at": null
  }]
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch DataZone fields. To help maintain the integrity of DataZones, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/datazones

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
suspended_at datetime Will de-activate (suspend) the datazone if set to a date. null means re-activate Yes
deleted_at datetime Will delete the datazone if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' datazones endpoint.

DELETE a DataZone

curl -X DELETE "https://<api-url>/datazones/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given datazone by id.

HTTP Request

DELETE https://<api-url>/datazones/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eDataZoneNotFound The datazone could not be found / invalid ID.

Dynamic Fields

Dynamic fields are an extensive method of allowing custom fields and values to individual relationships in the system. Although dynamic, the sub-system has been restricted to various types for database query efficiency (for things such as reporting on aggregate values), and to retain our complex IAM system.

Core concepts

Taking inspiration from the basic building blocks of English grammar, each relationship for which a custom field exists is described in two parts:

Subjects

Currently, the following subjects are supported:

Objects

The following objects are supported:

When the object and subject type match (ie, asset and an asset), it is asummed that the asset has a relationship with another asset (such as the standard asset heirachy, ie sites, buildings, locations). When the object is vacant, it is assumed this is a dynamic field belonging to the base object itself, and is not part of any relationship.

Fields

These are the dynamic fields as defined. They can be used across the system for any combination of subject or object.

The following field types are supported.

Field Type Customization Options Schema
text max length, multiline or not. { max: number, multiline: boolean }
number min and max values, scalefactor for decimals { max: number, min: number, scalefactor: number }
dateOnly none {}
dateTime none {}
dropdown options, key/value array { options: { key: string, value: string}[]}
multiselect options, key/value array { options: { key: string, value: string}[]}
checkbox none {}

Values

These are the values for the fields. The value contains the subject/object combination, as well as a link to the field, and the value itself.

The following value formats will be returned for the given field type:

Field Type Value Type Explanation
text string
number integer For precision (ie decimal shift) see config of field
dateOnly string ISO formatted date string
dateTime Timestamp ISO 8601 formatted
dropdown string Key for the selected option
multiselect string Keys for the selection options, comma separated.
checkbox boolean

Layouts

These are the template layouts used to display the custom screen as used by the tabs.

Currently, you can load and edit layouts, and lookup a specific layout for a given OBJECT and a SUBJECT (currently given as forAssetId).

When using forAssetId, the API endpoint will return exactly one layout. This will either be:

1) A matching layout for the assicated Entity's industry 2) If this does not exist, then the default layout for this subject(asset)/object combination is given.

Cards

Layouts contain cards, which are collections (Groups) of content.

Items

These are the individual pieces of content within a card. They each have a type:

If field is given, then field_id cannot be null. This means that this item is a dynamic field.

Every other type must have a null in the field_id column. These other types signify to the frontend where specific content should be places in that part of the card, instead of a dynamic field

For instance, an item with the type skillset, will mean to load the current party's skillsets in this place for editing. The template for this editing table would be held within the frontend, and then the frontend would handle updates via the existing skill infrastructure and outside of dynamic fields, because this is not a dynamic field.

This allows non-dynamic field content to be interlaced around dynamic fields

Important note

There is no validation at this time to ensure that an item type belongs in the current subject/object that this layout belongs to. This is entirely down to the frontend because it is outside of the dynamic field system. To ensure system integrity, the following should be put in place:

Working with 'industries'

A different layout is to be presented depending on the asset entities' industry. Note, that one layout can have several industries, but it cannot have an industry belonging to another layout. If you try to add an industry that is already in use from an existing layout, then the save request will be refused.

Layout and Field relationship

Input/output schema information

This area of the system is new, and some of the schema definitions may change. For the latest schema, visit the files under this folder.

Once the schema has stablized, it will be abstracted out here.

concert-services repo - proximity/api/src/modules/dynamicfields/lib/schemas - proximity/api/src/modules/dynamicfields/routes.ts

LIST Layouts

curl "https://<api-url>/dynamicfields/layouts" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Layout A",
    "description": "Layout A description",
    "subject_type": "asset",
    "object_type": "contract",
    "industry_ids": [
      "1f57219a-c836-4077-aeb6-8b2adaf56971"
    ],
    "is_default": true,
    "cards": [{
      "title": "Card title within the layout",
      "description": "This is the description of the card, and is used as text in the card.",
      "items": [{
        "item_type": "field",
        "field_id": "c0e409b0-2245-43fd-acb6-d60d3664b31b",
        "field": {
          "label": "This is a field label if item_type is field",
          "description": "This is the help text for the field",
          "field_type": "text",
          "config": {
            "max": 150,
            "multiline": true
          }
        }
      }]
    }],
    "updated_at": "2022-01-01T12:35:00.000Z"
  }]
}

This endpoint retrieves a result set of layouts, with any given filters applied.

Special note on for_asset_id: When this is invoked, the fields will automatically be appended to the return query for efficiency, otherwise, you will have to fetch the fields in a subsequent query. The reason for this is for efficiency (since invoking for_asset_id is likely because you're looking to display a layout), and avoiding large return payloads—the most for_asset_id will ever return is 2—the default, the the custom for that industry.

HTTP Request

GET https://<api-url>/dynamicfields/layouts

Query Parameters

asset contract service party

Parameter Default Description
ids[] null Filter results by these layout IDs
for_asset_id null For automatically returning the layouts pertaining to industries belonging to the entities of this asset id
object_type null Required: the object type, currently either asset, contract, service, or party.

CREATE a layout

curl -X POST "https://<api-url>/dynamicfields/layouts" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Layout A",
    "description": "Layout A description",
    "subject_type": "asset",
    "object_type": "contract",
    "industry_ids": [
      "1f57219a-c836-4077-aeb6-8b2adaf56971"
    ],
    "is_default": false,
    "cards": [{
      "title": "Card title within the layout",
      "description": "This is the description of the card, and is used as text in the card.",
      "items": [{
        "item_type": "field",
        "field_id": "c0e409b0-2245-43fd-acb6-d60d3664b31b"
      }]
    }]
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Layout A",
    "description": "Layout A description",
    "subject_type": "asset",
    "object_type": "contract",
    "industry_ids": [
      "1f57219a-c836-4077-aeb6-8b2adaf56971"
    ],
    "is_default": false,
    "cards": [{
      "title": "Card title within the layout",
      "description": "This is the description of the card, and is used as text in the card.",
      "items": [{
        "item_type": "field",
        "field_id": "c0e409b0-2245-43fd-acb6-d60d3664b31b"
      }]
    }]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an entity with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/dynamicfields/layouts

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
subject_id enum Only asset allowed at this point No
object_id enum One of asset, contract, service, or party No
industry_ids uuid[] Valid industry ID Industry No
is_default bool MUST be false, since trues are controlled by the system No
cards obj See 'cards' below No

Cards

Attribute Type Restrictions Null allowed
title string Max length 150 No
description string Max length 5000 No
items obj See 'items' below No

Items

Attribute Type Restrictions Null allowed
item_type enum Either field (in which field is required), or one of the predefined item_types No
field_id uuid Valid v4 UUID, field must exist Yes, if item_type is not field.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eFieldNotFound One of the field IDs given do not exist
400 BAD REQUEST eFieldObjectTypeMismatch The field ID given is for a different object type.
400 BAD REQUEST eIndustriesAlreadyAssigned You're assigning industries to a layout that already are assigned to another layout.

UPDATE a layout

curl -X PUT "https://<api-url>/dynamicfields/layouts/05e4b9a3-3f84-4fe0-a7ba-5e60ff9fea69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Layout A",
    "description": "Layout A description",
    "subject_type": "asset",
    "object_type": "contract",
    "industry_ids": [
      "1f57219a-c836-4077-aeb6-8b2adaf56971"
    ],
    "is_default": false,
    "cards": [{
      "title": "Card title within the layout",
      "description": "This is the description of the card, and is used as text in the card.",
      "items": [{
        "item_type": "field",
        "field_id": "c0e409b0-2245-43fd-acb6-d60d3664b31b"
      }]
    }]
  }'  

A valid response will be a 200 OK, with the created object in the data atttribute

{
  "data": {
    "id": "05e4b9a3-3f84-4fe0-a7ba-5e60ff9fea69",
    "name": "Layout A",
    "description": "Layout A description",
    "subject_type": "asset",
    "object_type": "contract",
    "industry_ids": [
      "1f57219a-c836-4077-aeb6-8b2adaf56971"
    ],
    "is_default": false,
    "cards": [{
      "title": "Card title within the layout",
      "description": "This is the description of the card, and is used as text in the card.",
      "items": [{
        "item_type": "field",
        "field_id": "c0e409b0-2245-43fd-acb6-d60d3664b31b"
      }]
    }]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an entity with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

Default Layouts

Note, you can edit default layouts even though these are system layouts. This is so you can create a default that is relevant to your use case.

However, there are some extra rules. In addition to not being able to create default layouts, you cannot change the status of a default layout. You cannot update is_default to a value different than it already has. Ie, you cannot make a non-default layout default, or vice-versa.

HTTP Request

PUT https://<api-url>/dynamicfields/layouts/<id>

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
subject_id enum Only asset allowed at this point No
object_id enum One of asset, contract, service, or party No
industry_ids uuid[] Valid industry ID Industry No
is_default bool MUST be false, since trues are controlled by the system No
cards obj See 'cards' below No

Cards

Attribute Type Restrictions Null allowed
title string Max length 150 No
description string Max length 5000 No
items obj See 'items' below No

Items

Attribute Type Restrictions Null allowed
item_type enum Either field (in which field is required), or one of the predefined item_types No
field_id uuid Valid v4 UUID, field must exist Yes, if item_type is not field.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eLayoutNotFound Layout does not exist
400 BAD REQUEST eAttemptDeactivateDefaultLayout You cannot archive the default layout
400 BAD REQUEST eFieldNotFound One of the field IDs given do not exist
400 BAD REQUEST eFieldObjectTypeMismatch The field ID given is for a different object type.
400 BAD REQUEST eIndustriesAlreadyAssigned You're assigning industries to a layout that already are assigned to another layout.

DELETE a layout

curl -X DELETE "https://<api-url>/dynamicfields/layouts/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given layout by id.

HTTP Request

DELETE https://<api-url>/dynamicfields/layouts/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eLayoutNotFound The layout could not be found / invalid ID.
400 BAD REQUEST AttemptDeactivateDefaultLayout You cannot delete or archive a default layout.

LIST fields

curl "https://<api-url>/dynamicfields/fields" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "label": "Field A",
    "description": "Field A description",
    "field_type": "text",
    "config": {
      "max": 150,
      "multiline": true
    },
    "archived_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z"
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "total": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }]
}

This endpoint retrieves a result set of fields, with any given filters applied.

HTTP Request

GET https://<api-url>/dynamicfields/fields

Query Parameters

Parameter Default Description
object_type enum Must be one of the valid object types
ids[] null Filter results by these field IDs
field_type_in string[] Filter results by those of these field types
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Embed/Include Parameters

Option Description
counts Includes all items associated with this entity. Includes assets, contracts, datazones, and operational groups.

Sorting fields

Field Description
label Sort by label.

CREATE a field

curl -X POST "https://<api-url>/dynamicfields/fields" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "label": "Field A",
    "description": "Field A description",
    "field_type": "text",
    "config": {
      "max": 150,
      "multiline": true
    },
    "archived_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "label": "Field A",
    "description": "Field A description",
    "field_type": "text",
    "config": {
      "max": 150,
      "multiline": true
    },
    "archived_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z"
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create a field with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/dynamicfields/fields

Parameters

Attribute Type Restrictions Null allowed
label string Max length 150 No
description string Max length 5000 No
field_type enum One of the accepted field types No
config obj Follow specific object config patterns for each field type No
archived_at datetime When set to not-null, will archive the field Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details

UPDATE a field

curl -X PUT "https://<api-url>/dynamicfields/fields/8f768eb4-7d9a-48de-87e1-6aff65c65355" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "label": "Field A",
    "description": "Field A description",
    "field_type": "text",
    "config": {
      "max": 150,
      "multiline": true
    },
    "archived_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z"
  }'  

A valid response will be a 200 OK, with the created object in the data atttribute

{
  "data": {
    "id": "8f768eb4-7d9a-48de-87e1-6aff65c65355",
    "label": "Field A",
    "description": "Field A description",
    "field_type": "text",
    "config": {
      "max": 150,
      "multiline": true
    },
    "archived_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z"
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create a field with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

PUT https://<api-url>/dynamicfields/fields/<id>

Parameters

Attribute Type Restrictions Null allowed
label string Max length 150 No
description string Max length 5000 No
field_type enum One of the accepted field types No
config obj Follow specific object config patterns for each field type No
archived_at datetime When set to not-null, will archive the field Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eFieldNotFound The field ID could not be found.

DELETE a field

curl -X DELETE "https://<api-url>/dynamicfields/fields/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given field by id.

HTTP Request

DELETE https://<api-url>/dynamicfields/fields/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eFieldNotFound The field could not be found / invalid ID.

LIST VALUES for a field

curl "https://<api-url>/dynamicfields/8e0f909d-6084-4276-be16-9fe2d7e0117f/values" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "field_id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "subject_type": "asset",
    "object_type": "contract",
    "object_id": "7863f96f-b6ae-4bf0-95b4-5881c745208b",
    "subject_id": "8e0f909d-6084-4276-be16-9fe2d7e0117f",
    "value": "Field value for subject/object",
    "updated_by": "75e386d3-af45-463f-9137-fad5c52e9889",
    "updated_at": "2022-01-01T12:35:00.000Z"
  }]
}

This endpoint retrieves a result set of fields, with any given filters applied.

HTTP Request

GET https://<api-url>/dynamicfields/<subjectId>/values

Query Parameters

Parameter Default Description
subject_type enum Must be one of the valid subject types
object_type enum Must be one of the valid object types
field_ids[] null Filter results by these field IDs
object_ids[] null Filter results by these object IDs

SET VALUES for a field

curl -X POST "https://<api-url>/dynamicfields/values" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "values": [{
      "label": "Field A",
      "description": "Field A description",
      "field_type": "text",
      "config": {
        "max": 150,
        "multiline": true
      },
      "archived_at": null,
      "created_at": "2022-01-01T12:35:00.000Z",
      "updated_at": "2022-01-01T12:35:00.000Z"
    }]
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": [{
    "object_type": "contract",
    "subject_type": "asset",
    "subject_id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "object_id": "8b393765-dd82-4538-be28-93f4a9e77c77",
    "value": "Field value for this subject/object combination."
  }],
  "warnings": [
    "Some error due to one of the items in the payload"
  ]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will assign values to the given fields. Note, you can assign values to multiple fields at once.

NOTE The subject IDs in the values MUST match that in your URI.

NOTE2 Due to the bulk nature of this request, individual validation errors and warnings will be given with the warnings output array. Regardless, I would rely on UI validation first and paramount.

HTTP Request

POST https://<api-url>/dynamicfields/values

Parameters

Attribute Type Restrictions Null allowed
object_type enum Valid object type No
subject_type enum Valid subject type No
field_id UUID Valid field type No
subject_id UUID Must match the UUID in the URI No
object_id UUID Must exist (will use object type to look it up) No
value mixed The value of the field. It will be validated against the field ID type. Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eFieldNotFound One or more of the fields given do not exist.

Entities

NOTE Section still under development - new fields and endpoints will be added as time goes on

Methods for dealing with the Entity object in the system.

Entities are organizations, bodies, or legal entities in the system that can be configured with different types. This new name is to replace the existing resource type in the system, which was poorly descriptive.

LIST Entities

curl "https://<api-url>/entities" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Entity A",
    "description": "Entity A description",
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": "deadc0de-9c89-4812-af13-8f3f8bcc4ca5",
    "phone": "+17785551122",
    "url": "https://google.com/boop",
    "stats": [{
      "assets": 2,
      "contracts": 5,
      "datazones": 6,
      "operational": 2
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "entities.view",
      "entities.update"
    ]
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Account Entity B",
    "description": null,
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": null,
    "phone": null,
    "url": null,
    "stats": [{
      "assets": 0,
      "contracts": 0,
      "datazones": 0,
      "operational": 0
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "entities.view"
    ]
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "total": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }]
}

This endpoint retrieves a result set of enitites, with any given filters applied.

HTTP Request

GET https://<api-url>/entities

Query Parameters

Parameter Default Description
ids[] null Filter results by these entity IDs
keywords null Filter results by the given keywords. Keywords search across name.
include[] null Include extra embeded non-resource elements (See list below)
type_id null Filter results for entities with this type ID (see types from entity type endpoint)
contract_id null Filter results for those associated with this contract ID
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Embed/Include Parameters

Option Description
counts Includes all items associated with this entity. Includes assets, contracts, datazones, and operational groups.

Sorting fields

Field Description
name Sort by name.
description Sort by description
type Sort by type
total_contracts Sort by total contracts
total_assets Sort by total assets
total_datazones Sort by total datazones
total_operational_groups Sort by total operational groups
created Sort by create date
updated Sort by update date

LIST Entity Types

These are types for the entities. See Entity Type

curl "https://<api-url>/entities/~/types" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "External client",
    "description": "Some description",
    "base_type": "client",
    "created_at": "2023-04-28T20:46:27.270Z"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Internal client",
    "description": "Some description",
    "base_type": "client",
    "created_at": "2023-04-28T20:46:27.270Z"
  }]
}

This endpoint retrieves a result set of entity types. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

Base Types define the behaviour of this type in the system. See Entity Type object for a description of the base types.

HTTP Request

GET https://<api-url>/entities/~/types

LIST Entity Roles

These are role associations for the entities contacts and owners. See Entity Role Type

curl "https://<api-url>/entities/~/roles" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "Customer Success",
    "description": "Some description",
    "type": "owner",
    "created_at": "2023-04-28T20:46:27.270Z"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Primary Contact",
    "description": "Some description",
    "type": "contact",
    "created_at": "2023-04-28T20:46:27.270Z"
  }]
}

This endpoint retrieves a result set of entity roles. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

You can also filter this result by type.

HTTP Request

GET https://<api-url>/entities/~/roles

Query Parameters

Parameter Default Description
type null Filter results for only given role types. Valid entries are contact or owner.

GET an Entity

curl "https://<api-url>/entities/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Entity A",
    "description": "Entity A description",
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": "deadc0de-9c89-4812-af13-8f3f8bcc4ca5",
    "phone": "+17785551122",
    "url": "https://google.com/boop",
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "3f24a0f4-6c83-49bd-81ba-c0d7a13bfa1c"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "4e50a5f8-e1e7-4c1d-827c-7ac328f8bab3"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "896e1914-2738-43ef-b15e-a88070e22245"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "4a7225f3-0b86-4430-937e-51b331b131d8"
    }],
    "service_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null,
    "__permissions__": [
      "entities.view",
      "entities.update"
    ]
  }
}

In the case that no entity is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific entity by the given id.

HTTP Request

GET https://<api-url>/entities/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the entity to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eEntityNotFound The entity could not be found / invalid ID.

CREATE a new Entity

curl -X POST "https://<api-url>/entities" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "A created Entity",
    "description": "Created Entity description",
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": "deadc0de-9c89-4812-af13-8f3f8bcc4ca5",
    "phone": "+17785551122",
    "url": "https://google.com/boop",
    "service_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "A created Entity",
    "description": "Created Entity description",
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": "deadc0de-9c89-4812-af13-8f3f8bcc4ca5",
    "phone": "+17785551122",
    "url": "https://google.com/boop",
    "service_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z",
    "__permissions__": [
      "entities.view",
      "entities.create",
      "entities.update"
    ]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an entity with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/entities

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type_id uuid Valid entity type ID Entity Type Yes
industry_id uuid Valid industry ID Industry Yes
phone string Valid e164 number format Yes
url string Max length 1000 Yes
addresses Address[] Use empty array for none No
owners PartyAssociation[] Use empty array for empty No
contacts PartyAssociation[] Use empty array for empty No
service_ids uuid[] Valid service ids. Use empty array for empty. No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eEntityTypeNotFound Entity type ID given could not be found
400 BAD REQUEST eAttemptSaveWithMissingIndustries The industry ID you've given could not be found
400 BAD REQUEST eAttemptSaveWithMissingServices One or more of the service ids you've given do not exist.
400 BAD REQUEST eAttemptSaveWithMissingRoles Some of the role ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingOwners Some or all of the owner ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingContacts Some or all of the contacts ids you've given do not exist

UPDATE an Entity

curl -X PUT "https://<api-url>/entities/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "An updated Entity",
    "description": "Updated Entity description",
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": "deadc0de-9c89-4812-af13-8f3f8bcc4ca5",
    "phone": "+17785551122",
    "url": "https://google.com/boop",
    "service_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "An updated Entity",
    "description": "Updated Entity description",
    "type_id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "industry_id": "deadc0de-9c89-4812-af13-8f3f8bcc4ca5",
    "phone": "+17785551122",
    "url": "https://google.com/boop",
    "service_ids": [
      "deadc0de-2222-4849-a096-5800072f28c2",
      "deadc0de-2222-4b26-89eb-4ed6de8baa53"
    ],
    "owners": [{
      "id": "deadc0de-3333-4849-a096-5800072f28c2",
      "role_id": "deadc0de-d372-477d-8544-8eed6511427f"
    }, {
      "id": "deadc0de-3333-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-5af6-40bd-9118-401f5bc03c89"
    }],
    "contacts": [{
      "id": "deadc0de-4444-4849-a096-5800072f28c2",
      "role_id": "deadc0de-44b6-4ab9-bb57-9175396a59aa"
    }, {
      "id": "deadc0de-4444-4b26-89eb-4ed6de8baa53",
      "role_id": "deadc0de-40b3-4379-a8b6-d44149e18586"
    }],
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z",
    "__permissions__": [
      "entities.view",
      "entities.update"
    ]
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing entity with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/entities/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the entity to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type_id uuid Valid entity type ID Entity Type Yes
industry_id uuid Valid industry ID Industry Yes
phone string Valid e164 number format Yes
url string Max length 1000 Yes
addresses Address[] Use empty array for none No
owners PartyAssociation[] Use empty array for empty No
contacts PartyAssociation[] Use empty array for empty No
service_ids uuid[] Valid service ids. Use empty array for empty. No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eEntityNotFound Entity ID given could not be found
400 BAD REQUEST eEntityTypeNotFound Entity type ID given could not be found
400 BAD REQUEST eAttemptSaveWithMissingIndustries The industry ID you've given could not be found
400 BAD REQUEST eAttemptSaveWithMissingServices One or more of the service ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingRoles Some of the role ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingOwners Some or all of the owner ids you've given do not exist
400 BAD REQUEST eAttemptSaveWithMissingContacts Some or all of the contacts ids you've given do not exist

BATCH UPDATE Entities

curl -X PATCH "https://<api-url>/entities" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "suspended_at": "2023-01-01T12:35:00.000Z",
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "service_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
      "service_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
      "suspended_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "suspended_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "service_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
    "service_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
    "suspended_at": null
  }]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch Entity fields. To help maintain the integrity of Entity, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The contract & service ID fields will allow assigning and unassigning contracts and services from the given entity. Note, only one can be given at a time for each entity.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/entities

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
contract_id_assign uuid None Yes, but will no-op
contract_id_unassign uuid None Yes, but will no-op
service_id_assign uuid None Yes, but will no-op
service_id_unassign uuid None Yes, but with no-op
suspended_at datetime Will de-activate (suspend) the entity if set to a date. null means re-activate Yes
deleted_at datetime Will delete the entity if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' entities endpoint.

BATCH Assign Contract to Entities

curl -X PATCH "https://<api-url>/entities/~/actions/assign_contract" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "contract_id": "dba81a06-4985-491a-8d64-d39898477b28",
    "push": [
      "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "e3d53daf-87d4-4427-a215-000cce6d0f99"
    ],
    "pull: [
      "aa122ac3-54b0-4b90-93cd-d32e907980c8"
    ]
  }'  

A valid response will be a 204 NO CONTENT. In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the one-time adding/removing a single contract to and from multiple entity IDs. This is not a standard REST endpoint, but a convenience one to ensure efficient API usage.

HTTP Request

POST https://<api-url>/entities/~/actions/assign_contract

Paramaters

Attribute Type Restrictions Null allowed Description
contract_id uuid Required No The contract to batch add/remove from the entities
push uuid[] Required No All the entity IDs to add this contract_id to
pull uuid[] Required No All the entity IDs to remove this contract_id from

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eEntitiesNotFound Some of the given entities could not be found. See message for ids.
400 BAD REQUEST eAttemptSaveWithMissingContracts The contract ID given could not be found.

BATCH Assign Service to Entities

curl -X PATCH "https://<api-url>/entities/~/actions/assign_service" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "service_id": "dba81a06-4985-491a-8d64-d39898477b28",
    "push": [
      "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "e3d53daf-87d4-4427-a215-000cce6d0f99"
    ],
    "pull: [
      "aa122ac3-54b0-4b90-93cd-d32e907980c8"
    ]
  }'  

A valid response will be a 204 NO CONTENT. In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the one-time adding/removing a single service to and from multiple entity IDs. This is not a standard REST endpoint, but a convenience one to ensure efficient API usage.

HTTP Request

POST https://<api-url>/entities/~/actions/assign_service

Paramaters

Attribute Type Restrictions Null allowed Description
service_id uuid Required No The service to batch add/remove from the entities
push uuid[] Required No All the entity IDs to add this service_id to
pull uuid[] Required No All the entity IDs to remove this service_id from

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eEntitiesNotFound Some of the given entities could not be found. See message for ids.
400 BAD REQUEST eAttemptSaveWithMissingServices The service ID given could not be found.

DELETE an Entity

curl -X DELETE "https://<api-url>/entities/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given entity by id.

HTTP Request

DELETE https://<api-url>/entities/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eEntityNotFound The entity could not be found / invalid ID.

Features

NOTE Section still under development - new fields and endpoints will be added as time goes on

Methods for dealing with the Feature object in the system. There are two noteworthy fields on each feature set:

permission

This is a tag used by the system to denote the actual ability that this feature allows. Currently, only one is accepted, but with plans to permit multiples in the future.

is_system

This is whether the feature is a system feature or not. System features are delivered on provisioning, and cannot be edited or deleted.

Note on development

Currently, this endpoint is slowly migrating the existing "features" functionality in the system.

LIST features

curl "https://<api-url>/features" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Feature A",
    "permission": "contracts.view",
    "is_system": true,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Feature B",
    "permission": "contracts.update",
    "is_system": true,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "total": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }]
}

This endpoint retrieves a result set of features, with any given filters applied.

HTTP Request

GET https://<api-url>/features

Query Parameters

Parameter Default Description
ids[] null Filter results by these feature IDs
keywords null Filter results by the given keywords. Keywords search across name.
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Sorting fields

Field Description
name Sort by name.
created Sort by create date
updated Sort by update date

LIST Feature Categories

These are categories for the features. See Feature Category

The sys_name field allows for two things. First, it identifies a category as a system category and thus cannot be deleted or modified. Also, it gives a static 'tag' for the field, so appropriate vocabulary renaming can be done for the client.

curl "https://<api-url>/features/~/categories" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Service",
    "sys_name": "service",
    "parent_id": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Dashboard",
    "sys_name": "dashboard",
    "parent_id": "abfe045b-814e-4d31-98f5-f3d0a23437f1"
  }]
}

This endpoint retrieves a result set of feature categories. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

HTTP Request

GET https://<api-url>/features/~/categories

GET a Feature

curl "https://<api-url>/features/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Feature A",
    "permission": "contracts.view",
    "is_system": true,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case that no feature is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific feature by the given id.

HTTP Request

GET https://<api-url>/features/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the feature to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eFeatureNotFound The feature could not be found / invalid ID.

Groups

Methods for dealing with the Group object in the system.

Groups in the system have 4 possible base types (See Group Types)

The first three, are groups containing their self-described subjects. The forth -- the "operational" group -- contains a collection of the former three. These provide functionality to the users for the included features and territories.

In the groups response, the following hard rules are applied:

  1. Only operational groups may have a combination of different group types in it's "inherited" groups. All other groups may only inherit the same time.
  2. Only operational groups may inherit from operational groups3. The data array is context specific to the base group type
  3. Groups without supplementary data may have their meta attribute set to null, if they do not have any additional data.

How groups are structured

Groups Examples

Differences between list resource and single resource

In the interest of performance and scaling, the resource representation in the list response is shortened compared to the full resource response as seen in the "single" get, post, and put responses.

Items that do not exist on the list response include:

System Groups

Some groups are considered "system" groups. At the time of writing, only features may have system groups. These are groups that are set on client creation, and cannot be edited or deleted. These groups convey a base functionality that exist in every client.

The attribute for system groups is is_system.

Group Items

Item IDs are items the group contains. The following group types are paired with the accepted items:

Group Type Item Type Notes
user party of type user These are currently what we call 'users' in the system
feature features
territories datazones
operational None The items array is ignored.

Item lists, inherited group lists, and counts

All group and item lists are those directly relating to the given group. Count stats are aggregates from of all items of this group, and all groups it recursively inherits from.

When fetching and editing groups, items and inherit_ids are a list of UUIDs.

Note, saving the group requires an array of UUIDs only for items and inherit_ids. This operation does not accept full objects.

LIST Groups

curl "https://<api-url>/groups" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "North America",
    "type": "territory",
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "stats": [{
      "territory": 14,
      "user": 0,
      "feature": 0,
      "inherits": 4
    }],
    "meta": {
      "email": "communications@gmail.com"
    },
    "is_system": false,
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Operational Group 1",
    "type": "operational",
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "stats": [{
      "territory": 2,
      "user": 3,
      "feature": 31,
      "inherits": 4
    }],
    "meta": {
      "email": "communications@gmail.com"
    },
    "is_system": false,
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "items": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }]
}

This endpoint retrieves a resultset of groups, with any given filters applied.

By default, this payload only includes the items directly associated with the group. Inherited groups are not given.

HTTP Request

GET https://<api-url>/groups

Query Parameters

Parameter Default Description
ids[] null Filter results by these contract IDs
type null Filter results by the given type ID
keywords null Filter results by the given keywords. Keywords search across name and description. Min characters 2.
party_id null Filter results for those associated with this party ID
entity_id null Filter results by groups that are associated with this entity ID. This is a recursive filter, and will includes all inherited groups too.
datazone_id null Filter results by only those containing the given datazone (will return only territory groups)
include[] null Include extra embeded non-resource elements (See list below)
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Embed/Include Parameters

Option Description
counts Includes object count totals, such as all users, datazones, features, and inherited groups. Note this is a total of all inherited too.

Sorting fields

Field Description
name Sort by name.
description Sort by description
total_user Sort by total user count
total_datazone Sort by total datazone count
total_feature Sort by total feature count
total_inherited Sort by total inherited count
created Sort by create date
updated Sort by update date

Note, sorting on individual object counts will come at a future time

GET a Group

curl "https://<api-url>/groups/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Sales Group A",
    "type": "operational",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "inherit_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1",
    ],
    "items": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],,
    "meta": {
      "email": "communications@gmail.com"
    },
    "is_system": false,
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

An expanded result will include all the sub objects and their counts.

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Sales Group A",
    "type": "operational",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "inherit_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1",
    ],
    "items": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "meta": {
      "email": "communications@gmail.com"
    },
    "is_system": false,
    "stats": [{
      "territory": 2,
      "user": 3,
      "feature": 31,
      "inherits": 5
    }],
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case that no group is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific group by the given id.

HTTP Request

GET https://<api-url>/groups/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the group to retrieve
include[] null Include extra embeded non-resource elements.

Embed/Include Parameters

Option Description
counts Includes object count totals, such as all users, datazones, features, and inherited groups. Note this is a total of all inherited too.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eGroupNotFound The group could not be found / invalid ID.

CREATE a new Group

curl -X POST "https://<api-url>/groups" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "North America",
    "type": "user",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "inherit_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1",
      "cfedec18-339e-4570-a971-4b1e9d1f811a"
    ],
    "items": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],,
    "meta": {
      "email": "communications@gmail.com"
    },
    "suspended_at": null
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "North America",
    "type": "user",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "inherit_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1",
      "cfedec18-339e-4570-a971-4b1e9d1f811a"
    ],
    "items": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],,
    "meta": {
      "email": "communications@gmail.com"
    },
    "is_system": false,
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will create a group with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/groups

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type Group Type One of the valid types No
owner_ids uuid[] Valid party IDs (can also use legacy user ids)
inherit_ids uuid[] Valid group IDs No, use empty array
items array of uuids Valid IDs for this group type if not operational. No
meta Key/Value[] As per key/value type Yes
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eAttemptGroupTypeChange You cannot change the group type once created.
400 BAD REQUEST eAttemptSaveWithMissingInherits One or more of the inherit_ids you've given do not exist.
400 BAD REQUEST eAttemptNonOperationalOtherTypeInherit You tried to mix group types in the inherit array for a non-operational type.
400 BAD REQUEST eAttemptSaveWithMissingItems Some of the item ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingOwners Some or all of the owner ids you've given do not exist

UPDATE a Group

curl -X PUT "https://<api-url>/groups/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "North America",
    "type": "user",
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "inherit_id": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1",
      "cfedec18-339e-4570-a971-4b1e9d1f811a"
    ],
    "items": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "meta": {
      "email": "communications@gmail.com"
    },
    "suspended_at": null
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "3823424f-dcc3-40b1-82e5-d71b0a194c69",
    "name": "North America",
    "type": "user",
    "owner_ids": [
      "d76273ac-a300-469f-9d88-14c44de1ad6b"
    ],
    "description": "Lorem ipsum dolor sit amet, consectetur...",
    "inherit_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1",
      "cfedec18-339e-4570-a971-4b1e9d1f811a"
    ],
    "items": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "meta": {
      "email": "communications@gmail.com"
    },
    "is_system": false,
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing group with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/groups/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the group to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
type Group Type One of the valid types No
owner_ids uuid[] Valid party IDs (can also use legacy user ids)
inherit_ids uuid[] Valid group IDs No, use empty array
items array of uuids Valid IDs for this group type if not operational. No
meta Key/Value[] As per key/value type Yes
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eGroupNotFound The group could not be found / invalid ID.
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eAttemptGroupTypeChange You cannot change the group type once created.
400 BAD REQUEST eAttemptSaveWithMissingInherits One or more of the inherit_ids you've given do not exist.
400 BAD REQUEST eAttemptNonOperationalOtherTypeInherit You tried to mix group types in the inherit array for a non-operational type.
400 BAD REQUEST eAttemptSaveWithMissingItems Some of the item ids you've given were missing
400 BAD REQUEST eAttemptSaveWithMissingOwners Some or all of the owner ids you've given do not exist

BATCH UPDATE Groups

curl -X PATCH "https://<api-url>/groups" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "suspended_at": "2023-01-01T12:35:00.000Z",
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "owner_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
      "owner_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
      "item_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
      "item_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
      "suspended_at": null,
      "deleted_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "suspended_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "owner_id_assign": "b9a34a93-f003-4a48-b8a0-bd932762f814",
    "owner_id_unassign": "ac9eef4d-5205-4b3c-b1a9-4a5d2f447ecd",
    "item_id_assign": "cc561e38-f782-4a48-946f-1a0b28a8b10c",
    "item_id_unassign": "4253e456-6f8f-4025-b133-e757f0cc866e",
    "suspended_at": null,
    "deleted_at": null
  }]
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch group fields. To help maintain the integrity of groups, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/groups

Accepted PATCH Parameters within 'data' array

Attribute Type Restrictions Null allowed
id uuid Required No
owner_id_assign uuid None Yes, but will no-op
owner_id_unassign uuid None Yes, but will no-op
item_id_assign uuid None Yes, but will no-op
item_id_unassign uuid None Yes, but with no-op
suspended_at datetime Will de-activate (suspend) the group if set to a date. null means re-activate Yes
deleted_at datetime Will delete the group if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' group endpoint.

BATCH Assign Item to Groups

curl -X PATCH "https://<api-url>/groups/~/actions/assign_item" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "item_id": "dba81a06-4985-491a-8d64-d39898477b28",
    "push": [
      "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "e3d53daf-87d4-4427-a215-000cce6d0f99"
    ],
    "pull: [
      "aa122ac3-54b0-4b90-93cd-d32e907980c8"
    ]
  }'  

A valid response will be a 204 NO CONTENT. In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the one-time adding/removing a single item to and from multiple group IDs. This is not a standard REST endpoint, but a convenience one to ensure efficient API usage.

HTTP Request

POST https://<api-url>/groups/~/actions/assign_item

Paramaters

Attribute Type Restrictions Null allowed Description
item_id uuid Required No The item to batch add/remove from the groups
push uuid[] Required No All the group IDs to add this item_id to
pull uuid[] Required No All the group IDs to remove this item_id from

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eGroupsNotFound Some of the given groups could not be found. See message for ids.
400 BAD REQUEST eItemUpdateWithVaryingGroupTypes Some of the groups in your arrays have differing group types. All groups must be the same type.
400 BAD REQUEST eAttemptSaveWithMissingItems The item ID given could not be found. Please ensure the item is the correct type for the groups given.

BATCH Assign an Owner to Groups

curl -X PATCH "https://<api-url>/groups/~/actions/assign_owner" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "party_id": "dba81a06-4985-491a-8d64-d39898477b28",
    "push": [
      "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "e3d53daf-87d4-4427-a215-000cce6d0f99"
    ],
    "pull: [
      "aa122ac3-54b0-4b90-93cd-d32e907980c8"
    ]
  }'  

A valid response will be a 204 NO CONTENT. In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the one-time adding/removing a single party owner to and from multiple group IDs. This is not a standard REST endpoint, but a convenience one to ensure efficient API usage.

HTTP Request

POST https://<api-url>/groups/~/actions/assign_owner

Paramaters

Attribute Type Restrictions Null allowed Description
party_id uuid Required No The party to batch add/remove as an owner from the groups
push uuid[] Required No All the group IDs to add this party_id owner to
pull uuid[] Required No All the group IDs to remove this party_id owner from

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eGroupsNotFound Some of the given groups could not be found. See message for ids.
400 BAD REQUEST ePartyNotFound The party ID given could not be found.

DELETE a Group

curl -X DELETE "https://<api-url>/groups/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given group by id.

Note, this group will be deleted. Any groups inheriting from it will not be affected directly, only losing their inherited properties

HTTP Request

DELETE https://<api-url>/groups/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eGroupNotFound The group could not be found / invalid ID.

Heatmaps

Methods for dealing with Heatmap configuration object in the system.

These are effective individual heatmap configurations. Once executed, they generate a heatmap result.

LIST Heatmaps

curl "https://<api-url>/heatmaps" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "deadc0de-1111-4b7a-a990-111111111111",
    "name": "Heatmap A",
    "description": "Heatmap A description",
    "type": "business",
    "stats": [{
      "groups.operational": 7,
      "groups.user": 4
    }],
    "suspended_at": null,
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2021-07-02T16:32:48.638Z",
    "deleted_at": null
  }, {
    "id": "deadc0de-2222-4b7a-a990-222222222222",
    "name": "Heatmap B",
    "description": "Heatmap B description",
    "type": "system",
    "stats": [{
      "groups.operational": 0,
      "groups.user": 0
    }],
    "suspended_at": null,
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2021-07-02T16:32:48.638Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "total": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of heatmaps, with any given filters applied.

HTTP Request

GET https://<api-url>/heatmaps

Query Parameters

Parameter Default Description
ids[] null Filter results by these heatmap IDs
keywords null Filter results by the given keywords. Keywords search across name and description.
include[] null Include extra embeded non-resource elements (See list below)
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Include Parameters

Option Description
stats Includes object stats. This includes total contracts and services at this point.

Sorting fields

Field Description
name Sort by name
description Sort by description
type Sort by type
total_user_groups Sort by total user group count
total_op_groups Sort by total operational group count
created Sort by create date
updated Sort by update date

GET a Heatmap

curl "https://<api-url>/heatmap/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "deadc0de-1111-4b7a-a990-111111111111",
    "name": "Heatmap A",
    "description": "Heatmap A description",
    "type": "business",
    "owner_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1"
    ],
    "group_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "metrics": [{
      "field_id": null,
      "label": "Total count",
      "ref": "number",
      "calc": "sum",
      "ranges": null
    }, {
      "field_id": "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0",
      "label": "Total Sq Floor floor area",
      "ref": "size",
      "calc": "avg",
      "ranges": [0, 24, 50, 75, 100]
    }, {
      "field_id": "cdab8d4f-4498-4165-9be2-aabf0ae05f7b",
      "label": "Some label for this field",
      "ref": "color",
      "calc": "max",
      "ranges": [0, 50, 100]
    }, {
      "field_id": "b59b2f68-a736-47e4-a2e8-4b8d259942c9",
      "label": "Some label",
      "ref": "shadow",
      "calc": "max",
      "ranges": [0, 10, 30, 100]
    }],
    "stats": [{
      "groups.operational": 7,
      "groups.user": 4
    }],
    "suspended_at": null,
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2021-07-02T16:32:48.638Z",
    "deleted_at": null
  }
}

In the case that no heatmap is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific heatmap by the given id.

HTTP Request

GET https://<api-url>/heatmap/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the heatmap to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eHeatmapNotFound The heatmap could not be found / invalid ID.

CREATE a new Heatmap

curl -X POST "https://<api-url>/heatmap" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Created Heatmap",
    "description": "Created Heatmap Description",
    "type": "business",
    "owner_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1"
    ],
    "group_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "metrics": [{
      "field_id": null,
      "label": "Total count",
      "ref": "number",
      "calc": "sum",
      "ranges": null
    }, {
      "field_id": "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0",
      "label": "Total Sq Floor floor area",
      "ref": "size",
      "calc": "avg",
      "ranges": [0, 24, 50, 75, 100]
    }, {
      "field_id": "cdab8d4f-4498-4165-9be2-aabf0ae05f7b",
      "label": "Some label for this field",
      "ref": "color",
      "calc": "max",
      "ranges": [0, 50, 100]
    }, {
      "field_id": "b59b2f68-a736-47e4-a2e8-4b8d259942c9",
      "label": "Some label",
      "ref": "shadow",
      "calc": "max",
      "ranges": [0, 10, 30, 100]
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Created Heatmap",
    "description": "Created Heatmap Description",
    "type": "business",
    "owner_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1"
    ],
    "group_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "metrics": [{
      "field_id": null,
      "label": "Total count",
      "ref": "number",
      "calc": "count",
      "ranges": null
    }, {
      "field_id": "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0",
      "label": "Total Sq Floor floor area",
      "ref": "size",
      "calc": "avg",
      "ranges": [0, 24, 50, 75, 100]
    }, {
      "field_id": "cdab8d4f-4498-4165-9be2-aabf0ae05f7b",
      "label": "Some label for this field",
      "ref": "color",
      "calc": "max",
      "ranges": [0, 50, 100]
    }, {
      "field_id": "b59b2f68-a736-47e4-a2e8-4b8d259942c9",
      "label": "Some label",
      "ref": "shadow",
      "calc": "max",
      "ranges": [0, 10, 30, 100]
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an heatmap with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/heatmaps

Parameters

Attribute Type Null allowed Restrictions
name string No The name of the heatman
description string Yes Description for the heatmap
type enum No Type of Heatmap, one of system, business, or user
owner_ids* uuid[] No Valid party ids. Use empty array for empty.
group_ids* uuid[] No Valid group ids. Use empty array for empty.
metrics Heatmap Metric[] No Valid array of metrics to caculate
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eInvalidMetricField There was a problem with of the metric fields given
400 BAD REQUEST eGroupNotFound One of the groups given could not be found
400 BAD REQUEST eOwnerNotFound One of the owners given could not be found

UPDATE an Heatmap

curl -X PUT "https://<api-url>/heatmaps/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Updated Heatmap",
    "description": "Updated Heatmap Description",
    "type": "business",
    "owner_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1"
    ],
    "group_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "metrics": [{
      "field_id": null,
      "label": "Total count",
      "ref": "number",
      "calc": "sum",
      "ranges": null
    }, {
      "field_id": "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0",
      "label": "Total Sq Floor floor area",
      "ref": "size",
      "calc": "avg",
      "ranges": [0, 24, 50, 75, 100]
    }, {
      "field_id": "cdab8d4f-4498-4165-9be2-aabf0ae05f7b",
      "label": "Some label for this field",
      "ref": "color",
      "calc": "max",
      "ranges": [0, 50, 100]
    }, {
      "field_id": "b59b2f68-a736-47e4-a2e8-4b8d259942c9",
      "label": "Some label",
      "ref": "shadow",
      "calc": "max",
      "ranges": [0, 10, 30, 100]
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Updated Heatmap",
    "description": "Updated Heatmap Description",
    "type": "business",
    "owner_ids": [
      "fbe2c9e2-089c-4cf3-aaf9-ad56a4799c79",
      "cfedec18-339e-4570-a971-4b1e9d1f811a",
      "5ffd53c3-97ec-40fe-a73f-f95a83f31dc1"
    ],
    "group_ids": [
      "6ccad6a4-bbbd-4d3e-9f64-2132bee25a84",
      "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0"
    ],
    "metrics": [{
      "field_id": null,
      "label": "Total count",
      "ref": "number",
      "calc": "sum",
      "ranges": null
    }, {
      "field_id": "337cc5bf-5f74-4a0c-a0c3-bf1911611fb0",
      "label": "Total Sq Floor floor area",
      "ref": "size",
      "calc": "avg",
      "ranges": [0, 24, 50, 75, 100]
    }, {
      "field_id": "cdab8d4f-4498-4165-9be2-aabf0ae05f7b",
      "label": "Some label for this field",
      "ref": "color",
      "calc": "max",
      "ranges": [0, 50, 100]
    }, {
      "field_id": "b59b2f68-a736-47e4-a2e8-4b8d259942c9",
      "label": "Some label",
      "ref": "shadow",
      "calc": "max",
      "ranges": [0, 10, 30, 100]
    }],
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing heatmap with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/heatmaps/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the heatmap to update

Parameters

Attribute Type Restrictions Null allowed
name string No The name of the heatman
description string Yes Description for the heatmap
type enum No Type of Heatmap, one of system, business, or user
owner_ids* uuid[] No Valid party ids. Use empty array for empty.
group_ids* uuid[] No Valid group ids. Use empty array for empty.
metrics Heatmap Metric[] No Valid array of metrics to caculate
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eHeatmapNotFound The Heatmap with the ID given could not be found
400 BAD REQUEST eInvalidMetricField There was a problem with of the metric fields given
400 BAD REQUEST eGroupNotFound One of the groups given could not be found
400 BAD REQUEST eOwnerNotFound One of the owners given could not be found

DELETE a Heatmap

curl -X DELETE "https://<api-url>/heatmaps/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given heatmap by id.

HTTP Request

DELETE https://<api-url>/heatmaps/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eHeatmapNotFound The heatmap could not be found / invalid ID.

QUERY a Heatmap

curl "https://<api-url>/heatmaps/f24600bf-2ed4-489e-a838-83d66a022b27/query" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "zoom": 5,
    "bound": "POLYGON((40.000 100.000 52.1232 123.023))",
    "clusters": [{
      "datazone_id": "90983be0-31da-49db-8c72-46b80ce959d9",
      "pins": [{
        "lat": "48.34234234234",
        "long": "-101.3426234234",,
        "field": null,
        "count": "2",
        "metrics": [{
          "field_id": "f137e119-52b7-4411-a249-40c5f4ca1134",
          "label": "Total count",
          "ref": "number",
          "percent": "67",
          "total": "123151"
        }, {
          "field_id": "2426c56e-2c8a-411d-be40-30159b455836",
          "label": "Total Sq Floor floor area",
          "ref": "size",
          "percent": "23",
          "total": "324"
        }, {
          "field_id": "f081cd89-67a7-4a3b-a0c7-bd24d03321be",
          "label": "Some label for this field",
          "ref": "color",
          "percent": "100",
          "total": "214"
        }, {
          "field_id": "c1eb55d2-5aab-4cc9-b60e-b1e98999f1c9",
          "label": "Total count",
          "ref": "shadow",
          "percent": "10",
          "total": "12"
        }],
        "items": null
      }, {
        "lat": "51.11231",
        "long": "-95.992315",
        "field": null,
        "count": "1",
        "metrics": [{
          "field_id": "f137e119-52b7-4411-a249-40c5f4ca1134",
          "label": null,
          "ref": "number",
          "percent": "67",
          "total": "123151"
        }, {
          "field_id": "2426c56e-2c8a-411d-be40-30159b455836",
          "label": null,
          "ref": "size",
          "percent": "23",
          "total": "324"
        }, {
          "field_id": "f081cd89-67a7-4a3b-a0c7-bd24d03321be",
          "label": null,
          "ref": "color",
          "percent": "100",
          "total": "214"
        }, {
          "field_id": "c1eb55d2-5aab-4cc9-b60e-b1e98999f1c9",
          "label": null,
          "ref": "shadow",
          "percent": "10",
          "total": "12"
        }],
        "items": [
          "fad9e63f-4426-4caf-807e-def3681ef642"
        ]
      }]
    }, {
      "datazone_id": "e72401b3-8851-498d-8434-6c877b16a1ae",
      "pins": []
    }, {
      "datazone_id": null,
      "pins": []
    }]
  }],
  "warnings": []
}

This endpoint executes a heatmap query. It returns the results of the Heatmap Query Result

HTTP Request

GET https://<api-url>/heatmaps/f24600bf-2ed4-489e-a838-83d66a022b27/query

Query Parameters

Parameter Default Description
zoom* n/a Integer 0-16, Zoom level
bound* n/a String WKT. Bounding box for the operation. Default, send screen viewport.
keywords '' String, Search terms for locations to heatmap against. Will be restricted to bound
group_type cluster` Determines the grouping to do on all the datapoints.
types [asset,entity] Enum. Types to search against.
show_items_below_size integer Default 5. If the count of items in a cluster is below this size, given them in items
datazones string[] Constrain to these datazones
query string Mapping keyword query to run in conjuction with the bounding box
type enum On what to run the mapping query (*required if query given)

* Required fields

Datapoint grouping types

When cluster is the grouping type, then long and lat are completed. If any of the others are selected, then long and lat are null and field contains the grouping value.

TEMPORARY Query Parameters

These highly influence the way the clustering algorithm is used. Please use these to manipulate the results.

  1. When we reach stablility, I will remove these query params and make these fields the default.
  2. If there are any we want to keep, for customer configuration etc, we will then adjust so they remain a query parameter.
  3. Please avoid changing node_size if possible, it affects performance.
Parameter Default Description (from the library docs)
min_cluster_size 2 Minimum number of points to form a cluster.
radius 40 Cluster radius, in pixels.
extent 512 (Tiles) Tile extent. Radius is calculated relative to this value.
node_size 64 Size of the KD-tree leaf node. Affects performance.

Note, the library we're using is here: https://www.npmjs.com/package/supercluster

Industries

Methods for dealing with the Industry object in the system.

Since this is a catalog endpoint, and is infrequently edited, there is no pagination or sorting. The whole result is returned. Sorting and filtering can be formed in-stu in the client.

LIST Industries

curl "https://<api-url>/industries" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Mining",
    "created_at": "2022-01-01T12:35:00.000Z",
    "archived_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Shipping",
    "created_at": "2022-01-01T12:35:00.000Z",
    "archived_at": null
  }],
  "warnings": []
}

This endpoint retrieves a result set of industries.

HTTP Request

GET https://<api-url>/industries

GET an Industry

curl "https://<api-url>/industries/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Mining",
    "created_at": "2022-01-01T12:35:00.000Z",
    "archived_at": null
  }
}

In the case that no industry is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific contract by the given id.

HTTP Request

GET https://<api-url>/industries/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the industry to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eIndustryNotFound The industry could not be found / invalid ID.

CREATE an Industry

curl -X POST "https://<api-url>/industries" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "A created Industry",
    "archived_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "A created Industry",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create an industry with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/industries

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
archived_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details

UPDATE an Industry

curl -X PUT "https://<api-url>/industries/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "An updated Industry",
    "archived_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "An updated Industry",
    "archived_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing industry with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/industries/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the industry to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
archived_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eIndustryNotFound Industry ID given could not be found

DELETE an Industry

curl -X DELETE "https://<api-url>/industries/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given industry by id.

HTTP Request

DELETE https://<api-url>/industries/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eIndustryNotFound The industry could not be found / invalid ID.

Job Titles

Methods for dealing with the Job Title object in the system.

Since this is a catalog endpoint, and is infrequently edited, there is no pagination or sorting. The whole result is returned. Sorting and filtering can be formed in-stu in the client.

LIST Job Titles

curl "https://<api-url>/jobtitles" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Manager",
    "created_at": "2022-01-01T12:35:00.000Z",
    "archived_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Trainee",
    "created_at": "2022-01-01T12:35:00.000Z",
    "archived_at": null
  }],
  "warnings": []
}

This endpoint retrieves a result set of job titles.

HTTP Request

GET https://<api-url>/jobtitles

Parties

NOTE Section still under development

Methods for dealing with the Party object in the system.

Parties are individuals, or "people" in the system. They are defined by a configurable type, which are split into two fundamenetal base types:

Identities

Identities are how a user logs into a service. They are decoupled from the actual user/person record themselves as standard practice. Even if the business logic only dictates a 1-1 relationship, having it 1-many will allow future changes if multiple login methods are required.

As an example, a single user could log-in with one or more of the following:

  1. Work SSO Email
  2. Personal Email
  3. Mobile Phone Number
  4. Username
  5. Private/Public Key identification (ie, keytags)

All these are examples of identities. They would all correlate to the user/person record.

To meet the initial spec of Proximity, fix all users to one 'email' identity. Examples of identities are given here: PartyIdentity.

Profile

These are effectively custom profile fields for users/contacts. A list of currently accepted keys are given here: PartyProfile

Other base attributes such as "email" and "phone" may be moved into this format in the future.

Future plans, this profile is to follow the same format as system-wide custom fields.

LIST Parties

curl "https://<api-url>/parties" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "f983e02d-732b-4b7a-a990-c911ed4a56ad",
    "type_id": null,
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "avatar_media_id": null,
    "avatar_url": "https://avatar.url",
    "phone": null,
    "job_title_id": "8ff4cf0e-353b-483c-8079-b3f580959f4c",
    "stats": [{
      "groups.user": 14,
      "contracts": 10,
      "assets": 5,
      "skillsets": 4
    }],
    "updated_at": "2021-07-02T16:32:48.638Z",
    "created_at": "2021-07-02T16:32:48.638Z",
    "deleted_at": null
  }, {
    "id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
    "type_id": "2ddb59f4-133a-4fb0-9161-ca2417587154",
    "first_name": "Test",
    "last_name": "Contact 1",
    "job_title_id": null,
    "phone": "+14035551234",
    "email": "contact1@sixfactorsolutions.com",
    "avatar_media_id": null,
    "avatar_url": null,
    "stats": [{
      "groups.user": 0,
      "contract": 0,
      "asset": 0,
      "skillset": 0
    }],
    "updated_at": "2021-06-24T04:18:12.066Z",
    "created_at": "2021-06-24T04:18:12.066Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "items": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of parties, with any given filters applied.

Note, skillsets can be added to this result as part of the skillsets include option. Skillsets however, need to be modified by the speciific parties/skillsets endpoint.

HTTP Request

GET https://<api-url>/parties

Query Parameters

Parameter Default Description
ids[] null Filter results by these party IDs
group_id null Filter results by parties belonging to this group id
type_id null Filter results by the given type id
skillset_id null Filter results by this skillset id
keywords null Filter results by the given keywords. Keywords search across name and description.
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Embed/Include Parameters

Option Description
stats Includes stats totals. This includes contracts, assets, groups, and skillsets.

Sorting fields

Field Description
name Sort by name.
first_name Sort by their first name
last_name Sort by their last name
type Sort by their type
phone Sort by their phone number
email Sort by their email
last_signin Sort by their last signin
job_title_id Sort by their job title
total_identities Sort by the total number of identities
total_groups Sort by the total number of groups they are in
total_contracts Sort by the total contracts they are assocated with
total_skillsets Sort by the total skillets they have
total_assets Sort by the total assets they have
created Sort by create date
updated Sort by update date

LIST Party Types

These are types for the parties. See Party Type

curl "https://<api-url>/parties/~/types" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "Contractor",
    "description": "Some description",
    "created_at": "2023-04-28T20:46:27.270Z"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Employee",
    "description": "Some description",
    "created_at": "2023-04-28T20:46:27.270Z"
  }]
}

This endpoint retrieves a result set of party types. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

Base Types define the behaviour of this type in the system. See Party Type object for a description of the base types.

HTTP Request

GET https://<api-url>/parties/~/types

LIST SkillSets for Party

Get a list of the skill sets and their properties for a specific party. See Party SkillSet

curl "https://<api-url>/parties/~/skillsets?party_id=e00bc820-6f56-4752-a50f-7d9b4e9ab50a" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "party_id": "e00bc820-6f56-4752-a50f-7d9b4e9ab50a",
    "skillset_id": "f983e02d-732b-4b7a-a990-c911ed4a56ad",
    "effective_at": "2022-01-01T12:50:00.000Z",
    "expires_at": "2023-01-01T12:50:00.000Z",
    "doc_url": "https://google.com",
    "created_at": "2023-01-01T12:35:00.000Z",
    "updated_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "party_id": "e00bc820-6f56-4752-a50f-7d9b4e9ab50a",
    "skillset_id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
    "effective_at": "2022-02-01T12:50:00.000Z",
    "expires_at": "2023-02-01T12:50:00.000Z",
    "doc_url": "https://google.com/2",
    "created_at": "2023-01-01T12:35:00.000Z",
    "updated_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": null
  }]
}

No pagination or sorting exists on this endpoint. It will return all the skillsets available for the given Party ID. If no skillsets are available, then an empty array is returned.

Note if the Party ID or the SkillSet ID does not exist, then an empty array will be returned.

HTTP Request

GET https://<api-url>/parties/~/skillsets

Query Parameters

Parameter Default Description
party_id null Return all the results for this party ID
skillset_id null Return all the results for this SkillSet ID

Note, skillset_id OR party_id MUST be given

LIST Favorites for a Party

curl "https://<api-url>/parties/8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7/favorites" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "item_id": "f983e02d-732b-4b7a-a990-c911ed4a56ad",
    "category": "heatmap",
    "type": "pin"
  }, {
    "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "item_id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
    "category": "entity",
    "type": "favorite"
  }, {
    "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "item_id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
    "category": "heatmap",
    "type": "favorite"
  }],
  "warnings": []
}

This endpoint retrieves the favorites for a given party/user.

NOTE, you can only change and retrieve favourites for the current logged in user

HTTP Request

GET https://<api-url>/parties/8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7/favorites

Query Parameters

Parameter Default Description
type null Filter results by this type
category null Filter results by this category

See 'Update' call for valid type / categories.

GET a Party

curl "https://<api-url>/parties/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "f983e02d-732b-4b7a-a990-c911ed4a56ad",
    "type_id": null,
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "phone": null,
    "avatar_media_id": null,
    "avatar_url": "https://avatar.url",
    "job_title_id": "8ff4cf0e-353b-483c-8079-b3f580959f4c",
    "profile": [{
      "key": "title", "val": "watchman",
      "key": "dob", "val": "2000-01-01"
    }],
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case that no party is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific party by the given id.

HTTP Request

GET https://<api-url>/parties/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the party to retrieve

Embed/Include Parameters

Option Description
counts Includes object count totals. This includes contracts, assets, groups, and skillsets.

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST ePartyNotFound The party could not be found / invalid ID.

CREATE a new Party

curl -X POST "https://<api-url>/parties" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "type_id": null,
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "avatar_media_id": null,
    "avatar_url": "https://avatar.url",
    "phone": null,
    "job_title_id": "8ff4cf0e-353b-483c-8079-b3f580959f4c",
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "profile": [{
      "key": "job_title_id", "val": "watchman",
      "key": "welcome_template", "val": "template_key"
    }]
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "type_id": null,
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "avatar_media_id": null,
    "avatar_url": "https://avatar.url",
    "phone": null,
    "job_title_id": "8ff4cf0e-353b-483c-8079-b3f580959f4c",
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "profile": [{
      "key": "job_title_id", "val": "watchman",
      "key": "welcome_template", "val": "template_key"
    }]
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create a party with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

base_type is a convenience field, and will be overwritten by whatever base type belongs in the party assigned type_id

HTTP Request

POST https://<api-url>/parties

Parameters

Attribute Type Restrictions Null allowed
type_id uuid The type of party Entity Type Yes
first_name string Max length 150 No
last_name string Max length 150 No
email string Valid email Yes
phone string Valid e164 number format Yes
avatar_media_id uuid Valid media ID for the avatar Yes
avatar_url string Public URL for an avatar (ie, via Google)
job_title_id uuid Valid job title ID Yes
addresses Address[] Use empty array for none No
profile PartyProfile[] Use empty array for none No

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST ePartyTypeNotFound Entity type ID given could not be found
400 BAD REQUEST eJobTitleNotFound Job Title ID given could not be found
400 BAD REQUEST eProfileKeyNotFound One or more of your profile keys do not exist.

UPDATE a Party

curl -X PUT "https://<api-url>/parties/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "type_id": null,
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "avatar_media_id": null,
    "avatar_url": "https://avatar.url",
    "phone": null,
    "job_title_id": null,
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "profile": [{
      "key": "job_title_id", "val": "watchman",
      "key": "welcome_template", "val": "template_key"
    }]
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "type_id": null,
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "avatar_media_id": null,
    "avatar_url": "https://avatar.url",
    "phone": null,
    "job_title_id": null,
    "addresses": [{
      "name": "Main Office",
      "country": "gb",
      "region": "nottinghamshire",
      "city": "newark",
      "locale": "collingham",
      "street": "station road",
      "unit": null,
      "postal": null,
      "lat": "52.023432",
      "long": "-0.126345"
    }],
    "profile": [{
      "key": "job_title_id", "val": "watchman",
      "key": "welcome_template", "val": "template_key"
    }]
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing party with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/parties/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the party to update

Parameters

Attribute Type Restrictions Null allowed
type_id uuid Valid entity type ID Entity Type Yes
first_name string Max length 150 No
last_name string Max length 150 No
email string Valid email Yes
phone string Valid e164 number format Yes
avatar_media_id uuid Valid media ID for the avatar Yes
avatar_url string Avatar URL for a public image (ie via Google)
job_title_id uuid Valid Job Title ID Yes
addresses Address[] Use empty array for none No
profile PartyProfile[] Use empty array for none No

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST ePartyNotFound The party could not be found / invalid ID.
400 BAD REQUEST ePartyTypeNotFound The party type could not be found / invalid ID.
400 BAD REQUEST eJobTitleNotFound Job Title ID given could not be found
400 BAD REQUEST eProfileKeyNotFound One or more of your profile keys do not exist.

UPDATE SkillSets for Parties

curl -X PUT "https://<api-url>/parties/~/skillsets" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "party_id": "b54245c3-e668-46fb-80f6-acc268659bd1",
      "skillset_id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
      "effective_at": "2023-01-01T12:35:00.000Z",
      "expires_at": "2023-02-02T12:35:00.000Z",
      "doc_url": "http://test-doc.com",
      "deleted_at": "2023-03-03T12:35:00.000Z"
    }, {
      "party_id": "a4c63ede-59b7-416c-9419-6b2804f75fcc",
      "skillset_id": "de45c0e0-595f-4392-8c75-e7fade75dc09",
      "effective_at": null,
      "expires_at": null,
      "doc_url": null,
      "deleted_at": null
      }]
    }'  

Note, this endpoint is idempotent. It will only edit the party/skillset combination given. A valid response will be a 200 OK, with the new state of geozones as an array

{
  "data": [{
    "party_id": "b54245c3-e668-46fb-80f6-acc268659bd1",
    "skillset_id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
    "effective_at": "2023-01-01T12:35:00.000Z",
    "expires_at": "2023-02-02T12:35:00.000Z",
    "doc_url": "http://test-doc.com",
    "deleted_at": "2023-03-03T12:35:00.000Z"
  }, {
    "party_id": "a4c63ede-59b7-416c-9419-6b2804f75fcc",
    "skillset_id": "de45c0e0-595f-4392-8c75-e7fade75dc09",
    "effective_at": null,
    "expires_at": null,
    "doc_url": null,
    "deleted_at": null
  }]
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint is idempontent and will update all given skillsets give for each party.

You can update multiple different parties and different skillsets in one request, up to a maximum of 50.

Note, unlike some previous endpoints, omitting skillsets will not delete them. This is because this array can have different parties and skillsets mixed.

To delete a party-skillset

Set the deleted_at to a date. null will undelete.

The deleted skillset will appear in the result payload, but will be omitted from all future lookup payloads.

HTTP Request

PUT https://<api-url>/parties/~/skillsets

Parameters

Attribute Type Restrictions Null allowed
party_id uuid Valid Party ID No
skillset_id uuid Valid SkillSet ID No
effected_at datetime Valid datetime Yes
expires_at datetime Valid datetime Yes
doc_url string Max length 5000 Yes
deleted_at datetime Valid datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST ePartiesNotFound Some or all of the party IDs given could not be found (Missing IDs given in the error message)
400 BAD REQUEST eAttemptSaveWithMissingSkillSets Some or more of the skillsets given could not be found. (Missing IDs given in error message.)

UPDATE Favorites for a Party

curl -X PATCH "https://<api-url>/parties/8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7/favorites" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
        "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
        "item_id": "aa22e6df-867f-4504-a700-18db11b8abd3",
        "category": "heatmap",
        "type": "pin",
        "deleted_at": "2023-03-03T12:35:00.000Z"
      }, {
        "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
        "item_id": "26e58965-3023-4bd0-b1ca-d82654cb14fe",
        "category": "heatmap",
        "type": "favorite",
        "deleted_at": null
      }]
    }'  

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "item_id": "aa22e6df-867f-4504-a700-18db11b8abd3",
    "category": "heatmap",
    "type": "pin",
    "deleted_at": "2023-03-03T12:35:00.000Z"
  }, {
    "party_id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "item_id": "26e58965-3023-4bd0-b1ca-d82654cb14fe",
    "category": "heatmap",
    "type": "favorite",
    "deleted_at": null
  }]
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint is idempontent and will update all given favourites for the given party, up to a maximum of 50 per request

Note, unlike some previous endpoints, omitting favorites will not delete them.

Missing item_ids

The external associations are loosely coupled; therefore, no validation lookups will occur to validate the given item_ids are correct.

Using party_id

For REST consistency, every element must have a party_id. It should only be the same user as that in the URL - however, it must also be that of the current user.

To delete a party-favourite

Set the deleted_at to a date. null will perform no action.

The deleted favorite will appear in the result payload, but will be omitted from all future lookup payloads.

HTTP Request

PATCH https://<api-url>/parties/:id/favorites

Parameters

Attribute Type Restrictions Null allowed
item_id uuid Valid item ID for the foreign object No
type enum Valid supported type No
category enum Valid supported category No
deleted_at datetime Valid datetime Yes

Supported categories

Supported types

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST ePartyNotFound Party with the given ID could not be found
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details

BATCH UPDATE Parties

curl -X PATCH "https://<api-url>/parties" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9"
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8"
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa"
      "deleted_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9"
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "deleted_at": null
  }]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch Party fields. To help maintain the integrity of Party, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/parties

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
suspended_at datetime Will de-activate (suspend) the party if set to a date. null means re-activate Yes
deleted_at datetime Will delete the party if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' parties endpoint.

DELETE a Party

curl -X DELETE "https://<api-url>/parties/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given party by id.

HTTP Request

DELETE https://<api-url>/parties/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST ePartyNotFound The party could not be found / invalid ID.

LIST Users

curl "https://<api-url>/parties/~/users" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "f983e02d-732b-4b7a-a990-c911ed4a56ad",
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "username": "test-username",
    "system_admin": true,
    "allow_sso": true,
    "allow_otp": false,
    "last_signin": "2021-06-24T04:18:12.066Z",
    "suspended_at": null
  }, {
    "id": "8b9fbb06-c350-49b8-8622-6b35338b9353",
    "first_name": "Test",
    "last_name": "Contact 1",
    "email": "contact1@sixfactorsolutions.com",
    "username": "Bob",
    "system_admin": false,
    "allow_sso": true,
    "allow_otp": false,
    "last_signin": "2023-06-24T04:18:12.066Z",
    "suspended_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20,
    "items": 2
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of users, with any given filters applied.

Please note: - party_id Is the same as the party this party belongs to - first_name, last_name, email belong to the party, and are just given here for convenience.`

HTTP Request

GET https://<api-url>/parties/~/users

Query Parameters

Parameter Default Description
ids[] null Filter results by these party IDs
keywords null Filter results by the given keywords. Keywords search across name and description.
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Sorting fields

Field Description
name Sort by name.
first_name Sort by their first name
last_name Sort by their last name
email Sort by their email
last_signin Sort by their last signin
created Sort by create date
updated Sort by update date

GET a Party's User

curl "https://<api-url>/parties/:id/users" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "id": "f983e02d-732b-4b7a-a990-c911ed4a56ad",
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "username": "test-username",
    "system_admin": true,
    "allow_sso": true,
    "allow_otp": false,
    "identities": [{
      "type": "email",
      "value": "sso_email@example.com"
    }],
    "last_signin": "2021-06-24T04:18:12.066Z",
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "suspended_at": null
  }
}

In the case that no party is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific party by the given id.

Please note: - id this is the party ID for which the user will relate to

HTTP Request

GET https://<api-url>/parties/<id>/users

URL Parameters

Parameter Data Type Description
ID uuid The ID of the party to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST ePartyNotFound The party could not be found / invalid ID.

UPDATE a Party User

curl -X PUT "https://<api-url>/parties/3823424f-dcc3-40b1-82e5-d71b0a194c69/users" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "username": "test-username",
    "system_admin": true,
    "allow_sso": true,
    "allow_otp": false,
    "last_signin": "2021-06-24T04:18:12.066Z",
    "identities": [{
      "type": "email",
      "value": "sso_email@example.com"
    }],
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "suspended_at": null
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "first_name": "Test",
    "last_name": "User1",
    "email": "test1@sixfactorsolutions.com",
    "username": "test-username",
    "system_admin": true,
    "allow_sso": true,
    "allow_otp": false,
    "last_signin": "2021-06-24T04:18:12.066Z",
    "identities": [{
      "type": "email",
      "value": "sso_email@example.com"
    }],
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "suspended_at": null
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

Will update the user for the given party ID. If the party does not have a user, then one is created.

HTTP Request

PUT https://<api-url>/parties/<id>/users

URL Parameters

Parameter Data Type Description
ID uuid The ID of the party to update

Parameters

Attribute Type Restrictions Null allowed
username string Max length 45 Yes
system_admin boolean Only a system admin can elevate or remove a system admin from a user No
allow_sso boolean boolean No
allow_otp boolean boolean No
identities PartyIdentity[] Use empty array for none No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST ePartyNotFound The party could not be found / invalid ID.
400 BAD REQUEST eIdentityNotValid One or more of your identities are not valid.
400 BAD REQUEST eIdentityNotUnique One or more of your identities is currently in use by another user.

GET Settings for a Party User

curl "https://<api-url>/parties/8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7/users/settings" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": {
    "id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "settings": [{
      "key": "welcome_template_id",
      "val": "deadc0de-732b-4b7a-a990-c911ed4a56ad",
    }],
    "application_state": {
      "some_state": 123
    }
  },
  "warnings": []
}

This endpoint retrieves the settings for a given party/user.

Please note the following: - application_state is the legacy storage medium, and will be phased out in place of settings

NOTE, you can only change and retrieve settings for the current logged in user

HTTP Request

GET https://<api-url>/parties/8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7/users/settings

UPDATE Favorites for a Party

curl -X PATCH "https://<api-url>/parties/8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7/users/settings" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": {
      "id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
      "settings": [{
        "key": "welcome_template_id",
        "val": "deadc0de-732b-4b7a-a990-c911ed4a56ad",
      }],
      "application_state": {
        "some_state": 123
      }
    }'  

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": {
    "id": "8d2c4dff-8055-4d5d-ab53-bfe10ba6bde7",
    "settings": [{
      "key": "welcome_template_id",
      "val": "deadc0de-732b-4b7a-a990-c911ed4a56ad",
    }],
    "application_state": {
      "some_state": 123
    }
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

Will update the settings for the user.

NOTE, you can only change and retrieve settings for the current logged in user

HTTP Request

PATCH https://<api-url>/parties/:id/users/settings

Parameters

Attribute Type Restrictions Null allowed
id uuid Valid party ID No
application_state any Legacy state
settings PartySettings[] Use empty array for none No
suspended_at timestamp Valid timestamp Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST ePartyNotFound Party with the given ID could not be found
400 BAD REQUEST eSettingKeyNotFound One or more of your profile keys do not exist.
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details

BATCH UPDATE Users

curl -X PATCH "https://<api-url>/parties/~/users" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99"
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "suspended_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "suspended_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99"
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "suspended_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "suspended_at": null
  }]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch user fields. To help maintain the integrity of a party's user, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/parties/~/users

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
suspended_at datetime Will de-activate (suspend) the party if set to a date. null means re-activate Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' parties endpoint.

Search

Endpoints for searching for resources across the system.

Important information for changes

The existing endpoints give all the information required in one endpoint. While this is incredibly efficient for the frontend especially while the dataset is small, this is not scalable.

As the system expands, we will be increasing the number of potential results in one request. Furthermore, there will be the possibility of many different objects, where a one-schema-fits-all approach will no longer be effective.

Remember, one of the biggest causes of slow APIs is not the data lookup or processing, but the transferrance of large payloads from the backend to the frontend. In many times, it's not just the data, but the schema itself that carries a heavy tax.

So, to make this scalable, we need to

  1. Make the return schema minimally descriptive
  2. Make the schema relevant to all returned resources
  3. Make the schema minimal to handle large payloads.

With the information returned, it is likely you're going to need more. To this end, you can use the type along with the collated ids, to perform one further lookup per resource type, to and endpoint to retrieve that information, for instance:

/entities?ids[]={id}&ids[]={id}

While this means a search function may now need 2 or 3 requests as opposed to 1, it also saves returning huge amounts of data when only 1 skinny request is required. It opens the door to many other scalable strategies such as lazy loading, deferred loading, etc.

Future Considerations

While the current format deals with result sets numbered potentially in the hundreds, moving into the thousands is going to start being problematic.

When this occurs, we will start to implement a cursoring style result, where each result set will be limited to x number, with a cursor given for the next result set.

curl "https://<api-url>/search/locations?bound[]=POLYGON((50 -100, 51, -101))&keywords=Calgary&types[]=asset&types[]=entity" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "dd4e2c04-7c40-43a8-9eb9-bb9af322f800",
    "type": "asset",
    "name": "Example Result 1",
    "wkt": null,
    "lat": "51.232",
    "long": "105.123"
  }, {
    "id": "e9c72528-e52b-4cc8-960d-2d9726a4b0bb",
    "type": "asset",
    "name": "Another Example Result",
    "wkt": null,
    "lat": "52.121",
    "long": "104.111"
  }, {
    "id": "6f643b1e-40cb-45a8-abf9-0701ff227829",
    "type": "entity",
    "name": "A result C",
    "wkt": null,
    "lat": "51.555",
    "long": "105.105",
    "assets": [{
      "id": "dd4e2c04-7c40-43a8-9eb9-bb9af322f800",
      "type": "asset",
      "name": "An asset belonging to an entity",
      "wkt": null,
      "lat": "51.232",
      "long": "105.123"
    }]
  }, {
    "id": "7ebfd79f-83d0-464c-b87c-39cc99a438ab",
    "type": "entity",
    "name": "Further result",
    "wkt": null,
    "lat": "48.121",
    "long": "99.111",
    "assets": []
  }],
  "warnings": []
}

This endpoint retrieves a result set of locations, with any given filters applied.

HTTP Request

GET https://<api-url>/search/locations?bound[]={bounding-boxes}&types[]={types}&keywords={keywords}

Query Parameters

Parameter Default Description
types[] [asset, entity] Only include these types. See Search Result Types. If asset AND entity is given, then each entity will have a sub attribute named assets, which will contain all the assets under this entity.
keywords null Filter results by the given keywords. See below for possible filter choices.
bound[] null Wkt, REQUIRED: Restrict results to this bounding box.

The Keywords Filter

  1. All words given are performed in an AND fashion
  2. You can use keywords: AND, OR, and NOT
  3. You can use brackets to make the order of presidence explict
  4. Will search across NAME, ADDRESS, details of the given types[]

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eInvalidKeywordQuery There was an error in your keyword query. Ie, check brackets are terminated etc.

Services

NOTE Section still under development

Methods for dealing with the Service object in the system.

Note on development

Currently, this endpoint is providing a 'facade' for the legacy service endpoint in the system. The id for the services are the same as the service_id for the existing services. Legacy endpoints at this juncture can still be used interchangably, but newer functionality should be preferred where possible as older legacy endpoints will be deprecated as the data model is migrated.

LIST services

curl "https://<api-url>/services" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Catering",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "email": "serviceemail@example.com",
    "phone": "+17789891122",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Floor Cleaning",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "email": "floorcleaning@example.com",
    "phone": "+17789889888",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": "2023-01-02T12:23:44.000Z",
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of services, with any given filters applied.

HTTP Request

GET https://<api-url>/services

Query Parameters

Parameter Default Description
ids[] null Filter results by these service IDs
keywords null Filter results by the given keywords. Keywords search across name.
type_id null Filter results by this type id
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Sorting fields

Field Description
name Sort by name.
description Sort by description
category Sort by category
type Sort by type
created Sort by create date
updated Sort by update date

LIST Service Types

These are types for the services. See Service Type

curl "https://<api-url>/services/~/types" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "Service Type A",
    "created_at": "2023-04-28T20:46:27.270Z"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Service Type B",
    "created_at": "2023-04-28T20:46:27.270Z"
  }]
}

This endpoint retrieves a result set of service types. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

HTTP Request

GET https://<api-url>/services/~/types

LIST Service Categories

These are categories for the services. See Service Category

curl "https://<api-url>/services/~/categories" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "300d1740-7b7c-4aaf-a965-e4a096bd3f99",
    "name": "Service Category A",
    "created_at": "2023-04-28T20:46:27.270Z"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Service Category B",
    "created_at": "2023-04-28T20:46:27.270Z"
  }]
}

This endpoint retrieves a result set of service categories. Note, this is a catalogue endpoint which will return the entirity of the dataset. No sorting or pagination is done since it is expected this will be done on the receiver side.

HTTP Request

GET https://<api-url>/services/~/categories

GET a service

curl "https://<api-url>/services/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A valid response will contain the single result in the data attribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Catering",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "email": "serviceemail@example.com",
    "phone": "+17789891122",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case that no service is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific service by the given id.

HTTP Request

GET https://<api-url>/services/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the service to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eServiceNotFound The contract could not be found / invalid ID.

CREATE a new Service

curl -X POST "https://<api-url>/services" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "A created service",
    "description": "Created service description",
    "email": "serviceemail@example.com",
    "phone": "+17789891122",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "A created Entity",
    "description": "Created service description",
    "email": "serviceemail@example.com",
    "phone": "+17789891122",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create a service with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/services

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
email string Valid email Yes
phone string Valid e164 phone Yes
type_id uuid Valid entity type ID Service Type Yes
category_id uuid Valid industry ID Service Category Yes
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eServiceTypeNotFound Service type ID given could not be found
400 BAD REQUEST eServiceCategoryNotFound Service category ID given could not be found

UPDATE a Service

curl -X PUT "https://<api-url>/services/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "An updated service",
    "description": "Updated service description",
    "email": "serviceemail@example.com",
    "phone": "+17789891122",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "An updated service",
    "description": "Updated service description",
    "email": "serviceemail@example.com",
    "phone": "+17789891122",
    "category_id": "7fa79cdd-7ffe-4628-a057-d8212eee421a",
    "type_id": "0fc66bc3-b6af-47c3-8a0f-76dbf2eb7f8c",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing service with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/services/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the service to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
email string Valid email Yes
phone string Valid e164 phone Yes
type_id uuid Valid entity type ID Service Type Yes
category_id uuid Valid industry ID Service Category Yes
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eServiceNotFound Service ID given could not be found
400 BAD REQUEST eServiceTypeNotFound Service type ID given could not be found
400 BAD REQUEST eServiceCategoryNotFound Service category ID given could not be found

BATCH UPDATE Entities

curl -X PATCH "https://<api-url>/services" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "data": [{
      "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
      "suspended_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
      "deleted_at": "2023-01-01T12:35:00.000Z",
    }, {
      "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
      "suspended_at": "2023-01-01T12:35:00.000Z",
      "deleted_at": "2023-01-01T12:35:00.000Z"
    }, {
      "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
      "suspended_at": null,
      "deleted_at": null
    }]
  }'  

A valid response will be a 200 OK. Any errors encountered when batch updating the objects will be returned in the errors array.

{
  "data": [{
    "id": "6fd5b5c4-0978-49f6-b301-85f60434c1b9",
    "suspended_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "e3d53daf-87d4-4427-a215-000cce6d0f99",
    "deleted_at": "2023-01-01T12:35:00.000Z",
  }, {
    "id": "aa122ac3-54b0-4b90-93cd-d32e907980c8",
    "suspended_at": "2023-01-01T12:35:00.000Z",
    "deleted_at": "2023-01-01T12:35:00.000Z"
  }, {
    "id": "48dd8d74-0aee-4fae-8417-d0466c74fbaa",
    "suspended_at": null,
    "deleted_at": null
  }]
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint facilitates the updating of batch service fields. To help maintain the integrity of a service, only selected fields can be updated in this manner.

For this, send an array in data with an id for each group object you wish to update, and the attributes you wish to update on that object.

The response to this endpoint is an array of errors with any errors that occurred during this operation. An empty array means the operation was successful and there were no failures.

HTTP Request

PATCH https://<api-url>/services

Accepted PATCH Parameters

Attribute Type Restrictions Null allowed
id uuid Required No
suspended_at datetime Will de-activate (suspend) the service if set to a date. null means re-activate Yes
deleted_at datetime Will delete the service if set to a date. null means undeleted. Yes

Note, for delete, the date will be overriden with the current date that the operation took place.

Error Responses

These will appear in the errors array using the Batch Update Error format. For possible errors, see the list given for the 'update' services endpoint.

DELETE a Service

curl -X DELETE "https://<api-url>/services/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given service by id.

HTTP Request

DELETE https://<api-url>/services/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eServiceNotFound The service could not be found / invalid ID.

SkillSets

NOTE Section still under development

Methods for dealing with the SkillSet object in the system.

LIST SkillSet

curl "https://<api-url>/skillsets" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Fire Extinguisher",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Snow Safety",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": "2023-01-02T12:23:44.000Z",
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves a result set of skillsets, with any given filters applied.

HTTP Request

GET https://<api-url>/skillsets

Query Parameters

Parameter Default Description
ids[] null Filter results by these skillset IDs
keywords null Filter results by the given keywords. Keywords search across name.
sort +name Sorts by the given field & direction (-/+).
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

Sorting fields

Field Description
name Sort by name.
description Sort by description
total_parties Sort by total parties with this skillset
total_expired Sort by total parties where this skillset has expired
created Sort by create date
updated Sort by update date

GET a SkillSet

curl "https://<api-url>/skillsets/:id" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A valid response will contain the single result in the data attribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Fire Extinguisher",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": null,
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }
}

In the case that no skillset is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves a specific skillset by the given id.

HTTP Request

GET https://<api-url>/skillsets/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the skillset to retrieve

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eSkillSetNotFound The contract could not be found / invalid ID.

CREATE a new SkillSet

curl -X POST "https://<api-url>/skillsets" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Fire Extinguisher",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 201 CREATED, with the created object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Fire Extinguisher",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an validation error, a 400 BAD REQUEST will be returned.

This endpoint will create a skillset with the given properties. Note, id is not accepted, and will be automatically generated and assigned.

HTTP Request

POST https://<api-url>/skillsets

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eSkillSetTypeNotFound SkillSet type ID given could not be found
400 BAD REQUEST eSkillSetCategoryNotFound SkillSet category ID given could not be found

UPDATE a SkillSet

curl -X PUT "https://<api-url>/skillsets/3823424f-dcc3-40b1-82e5-d71b0a194c69" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Fire Extinguisher",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }'  

A valid response will be a 200 OK, with the updated object in the data atttribute

{
  "data": {
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Fire Extinguisher",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing...",
    "suspended_at": "2023-01-01T12:45:00.000Z"
  }
}

In the case of an valdiation error, a 400 BAD REQUEST will be returned.

This endpoint will update an existing skillset with the new payload. The endpoint expects the entire object to be given in the parameters to better fulfill the goal of REST idempotency.

ID is not accepted as a body parameter, and should only be given in the URL.

HTTP Request

PUT https://<api-url>/skillsets/<id>

URL Parameters

Parameter Data Type Description
ID uuid The ID of the skillset to update

Parameters

Attribute Type Restrictions Null allowed
name string Max length 150 No
description string Max length 5000 No
suspended_at datetime When set to not-null, will override with current datetime Yes

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eValidationError Parameters given were invalid. Check error message for details
400 BAD REQUEST eSkillSetNotFound SkillSet ID given could not be found

DELETE a SkillSet

curl -X DELETE "https://<api-url>/skillsets/deadc0de-4333-49d8-bec8-6454ca3f6ce9" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

A successful delete with return a 204 NO CONTENT

The endpoint will delete the given skillset by id.

HTTP Request

DELETE https://<api-url>/skillsets/<id>

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eSkillSetNotFound The skillset could not be found / invalid ID.

Templates

NOTE Section still under development - new fields and endpoints will be added as time goes on

Currently only returning ID/name/type

LIST Templates

curl "https://<api-url>/templates" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Welcome Template 2023",
    "type_id": "0e1d0780-bff5-4df5-b3dc-7bd0e25cd524",
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Terms of Use acceptance 2020",
    "type_id": "0e1d0780-bff5-4df5-b3dc-7bd0e25cd524",
    "created_at": "2022-01-01T12:35:00.000Z",
    "updated_at": "2022-01-01T12:35:00.000Z",
    "deleted_at": null
  }],
  "pagination": {
    "page": 0,
    "per_page": 20
  },
  "sort": [{
    "field": "name",
    "dir": "asc"
  }],
  "warnings": []
}

This endpoint retrieves all templates.

HTTP Request

GET https://<api-url>/templates

Query Parameters

Parameter Default Description
keywords null Filters results by the given keywords
sort_by +name Sorts by the given field & direction (-/+). Fields permitted are name, locations, status
page 0 Pagination: which page to view
per_page 20 Pagination: how many results per page to show

LIST Template Types

curl "https://<api-url>/templates/~/types" \
  -H "X-Client-Key: client-key" \
  -H "Authorization: your-auth-token" \
  -H "Content-Type: application/json"

All results will be returned in a 'data' array. An empty array means no results were found.

{
  "data": [{
    "id": "abfe045b-814e-4d31-98f5-f3d0a23437f1",
    "name": "Welcome Template"
  }, {
    "id": "a88fe8d7-f04a-4089-aed9-8df56b2c7a12",
    "name": "Terms of Use Acceptance"
  }]
}

This endpoint retrieves all template types. This is considered a catalog endpoint, and is not paginated. There are no filters or modifiers available.

HTTP Request

GET https://<api-url>/templates/~/types

Users

These are endpoints for dealing with user access in the system ONLY. For detail on the actual party/user profile, see the Parties endpoint

GET current login configuration

curl "https://<api-url>/users/me" </span>
  -H "X-Client-Key: client-key" </span>
  -H "Authorization: your-auth-token" </span>
  -H "Content-Type: application/json"

The baseline response will look like the following

{
  "data": {
    "party_id": "a0b460d0-2bfb-44c8-9c50-e86dbbcc0b0a",
    "permissions": [{
      "op_group_id": null,
      "permissions": [
        "dashboard.view"
      ]
    }, {
      "op_group_id": "c27c4e6f-4560-49a2-b1fa-5c344d1c4698",
      "permissions": [
        "assets.import",
        "assets.create",
        "assets.read"
      ]
    }],
    "settings": []
  },
  "warnings": []
}

In the case that no party is found, a 400 BAD REQUEST will be returned.

This endpoint retrieves login configuration, settings, and permissions for the current logged in user.

The current returned properties:

HTTP Request

GET https://<api-url>/users/me

Error Responses

HTTP Status Error Code Description
400 BAD REQUEST eUserNotFound If the user could not be found. Since it pulls the user id from the current session, this would mean the user record could not be matched or is missing. This may be as a result of the user being deleted since the token was issued.

Type: Asset

This is an asset in the system, containing:

Name Type Allow Null Description
id uuid No Asset ID
name string No The asset name
description string Yes Description for the asset
type_id uuid Yes* The type for the asset. See Asset Type
entity_id uuid Yes Valid entity ID. Must be null on container types
parent_id uuid Yes Valid parent ID, depending on restrictions given by type
phone* string Yes Valid e164 number format
floor_unit* string Yes Max length 150, unit number
year_built* string Yes Max length 50, if building, year built. Will move to custom field.
building_floor* string Yes Max length 50. Will move to custom field.
num_floors_units* string Yes Max length 50. For buildings, number of floors or units. Will move to custom field.
strata* string Yes Max length 50. Strata ID for building. Will move to custom fields
service_ids* uuid[] No Valid service ids. Use empty array for empty.
party_ids* uuid[] No Valid party ids. Use empty array for empty.
contract_ids* uuid[] No Valid contract ids. Use empty array for empty.
address* Address Yes If type permits address, otherwise null
geo* GeoZone Yes If type permits geo, otherwise null
is_hidden boolean True if this asset is hidden on the map No
suspended_at datetime When set to not-null, will override with current datetime Yes

* These entries only show on non-shallow payloads ** Please be aware that not all these fields apply to containers/locations alike. Some will be ignored as we migrate the database

Readonly / Optional / Meta properties

Name Type Can be Null Description
updated_at datetime Yes When the contract was last updated
created_at datetime No When the contract was created

Type: Asset Type

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Asset Type ID
name string No The default type name
config object No Configurations for the type

Type configuration object

Name Type Allow Null Description
require_parent boolean No If true then any asset with this type requires a parent.
allow_parents uuid[] No Only allow parents with these uuids. If none given, then does not permit parents.
can_inherit boolean No If true, an asset with this type will inherit addresses/geo information from it's parents.
permit_address boolean No If true, an asset with this type may have a civic address.
permit_geo boolean No If true, an asset with this type may have a geo location.
geo_update_freq integer Yes If not null, this is the frequency in which the asset can receive updates from the wild.
is_container boolean No If true, this is a container only, and does not contain any sub-objects other than assets.
is_system boolean No If true, this is a system type, and therefore has heavy restrictions around it's updating.

Note, a type could end up in an inconsistent state if require_parent is true and allow_parents is empty. Updating a type to this state will throw an error.

The following are immutable fields provided

Name Type Allow Null Description
created_at datetime No When this type was created
updated_at datetime Yes When this type was last updated
deleted_at datetime Yes If this type is deleted. (Will be generally be omitted.)

Type: Contract

This is an contract in the system, containing:

Name Type Allow Null Description
id uuid No Contract ID
name string No The contract name
description string Yes The contract description, if any
starts_at datetime Yes ISO8601 compliant timestamp, if any
expires_at datetime Yes ISO8601 compliant timestamp, if any
url string Yes Must be a valid url. Max 1000 chars.
entity_ids* uuid[] No Entities assigned to this contract
media_ids* uuid[] No Medias assigned to this contract
owners* PartyAssociation[] No Owners assigned to this contract
contacts* PartyAssociation[] No Contacts assigned to this contract
suspended_at datetime Yes When set to not-null, will override with current datetime

* Not on shallow payloads (ie, only on get one, response from create/updates)

Readonly / Optional / Meta properties

Name Type Can be Null Description
updated_at datetime Yes When the contract was last updated
created_at datetime No When the contract was created

Type: Contract Role

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Role ID
name string No The default role name
type enum No Either contact or owner
description string Yes A description of this role
created_at datetime No When this role was created.

Type: DataZone

This is a datazone in the system, being either at:

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Datazone ID
name string No The datazone name
type enum No DataZone Type
is_dynamic boolean No Default true.
owner_ids uuid[] No Valid party IDs (Can use legacy user ids)
addresses Address[] No Addresses, only valid on type geo. Use empty array [] otherwise. Not included on simplified datazone lists
description string Yes The datazone description
inherit_ids uuid[] No Datazone IDs of groups it inherits from Not included on simplified datazone lists
industry_ids array of uuids No Commercial only Valid Industry IDs Not included on simplified datazone lists
entity_ids array of uuids No Valid Entity IDs Not included on simplified datazone lists
contract_ids array of uuids No Valid Contract IDs Not included on simplified datazone lists
suspended_at datetime Yes When set to not-null, will override with current datetime

Readonly / Optional / Meta properties

Name Type Can be Null Description
stats { type / count }[] No A list of all object types and counts within the datazone
inherits DataZone[] No When expanded, all of the inherited objects.
updated_at datetime Yes When the datazone was last updated
created_at datetime No When the datazone was created

Type: DataZone Type

This is an enumeration of possible datazone types.

Type Description
geo A geo type datazone
commercial A commercial datazone

Type: Entity

This is an entity in the system, containing:

Name Type Allow Null Description
id uuid No Entity ID
name string No The entity name. Max 150 chars
description string Yes The entity description. Max 5000 chars.
type_id uuid No The type ID for this entity. (Current types are retrieved via endpoint)
industry_id uuid Yes The industry this entity is assigned to. (Industries can be pulled via endpoint)
phone string Yes Must be valid e164 format
url string Yes Must be a valid url. Max 1000 chars.
addresses* Address[] No Addresses for the entity
contract_ids* uuid[] No Contracts assigned to this entity
service_ids* uuid[] No Services assigned to this entity
owners* PartyAssociation[] No Owners assigned to this entity
contacts* PartyAssociation[] No Contacts assigned to this entity
suspended_at datetime Yes When set to not-null, will override with current datetime
permissions string[] No When returned, it is a list of all the permissions the current user can perform on this object.

* Not on shallow payloads (ie, only given on get one, responses from create/updates)

Readonly / Optional / Meta properties

Name Type Can be Null Description
stats { type / count }[] No (Supplmentary not part of the main resource object): A list of all object types and counts within the group
updated_at datetime Yes When the entity was last updated
created_at datetime No When the entity was created

Type: Entity Type

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Type ID
name string No The default type name
description string Yes A description of this type
base_type enum No One of the base types given below

Base Types

Name Description
client Client base type
vendor Vendor base type

Type: Entity Role

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Role ID
name string No The default role name
type enum No Either contact or owner
description string Yes A description of this role
created_at datetime No When this role was created.

Type: Feature

This is an feature in the system, containing:

Name Type Allow Null Description
id uuid No Feature ID
name string No The given feature name
permission string No The assigned system permission for this feature set
is_system boolean No If a system feature, then it cannot be edited/removed.

Type: Feature Category

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Category ID
name string No The default category name
sys_name string Yes The system name for this category, if a system field.
parent_id uuid Yes If given, the parent of the category (ie, this is a sub category)

Please note, only categories and sub-categories are supported. Categories beyond 1-level deep are not supported at this time

Type: Group

This is a group in the system, containing a collection of objects ("items") given by the Group Type

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Group ID
name string No The group name
type enum No Group Type
owner_ids uuid[] No Valid party IDs (can also use legacy user ids) Not included on simplified group lists
description string Yes The group description
items uuid[] No Contents of the group, depending on type Not included on simplified group lists
inherit_ids uuid[] No Group IDs of groups it inherits from Not included on simplified group lists
meta object Yes Specific configuration for the type
is_system boolean No Immutable. If group is a system group.
suspended_at datetime Yes If the group has been suspended. null means active.

Expanded / Readonly

As with most resources, there are certain fields that are read only. They are accepted in create/updated, but ignored.

Name Type Can be Null Description
stats { type / count }[] No (Supplmentary not part of the main resource object): A list of all object types and counts within the group
updated_at datetime Yes When the group was last updated
created_at datetime No When the group was created

META object

META: For groups of type user

{
  "email": "someaddress@email.com" 
}

META: For groups of type territory.

{
  "addresses": [{
    "country": "United States"
  }, {
    "country": "Canada",
    "region": "Alberta",
    "locale": "Rocky View County"
  }, {
    "country": "Canada",
    "region": "Alberta",
    "city": "Calgary",
    "street": "1st St NW"
  }, {
    "country": "Canada",
    "postal": "T3A 0Z0"
  }]
}

Depending on the group type, different data options are permitted. The following are supported for the different group types:

Group Type Data Key Description
user email Email relating to this group
territory addresses[] An array of Address[] objects

Type: Group Type

This is an enumeration of possible group types.

Type Description
user A group of parties of type user
territory A group of territories
feature A group of features
operation An operational group

Type: Heatmap

This is a Heatmap configuration in the system, containing:

Name Type Allow Null Description
id uuid No Heatmap Configuration ID
name string No The name of the heatman
description string Yes Description for the heatmap
type enum No Type of Heatmap, one of system, business, or user
owner_ids* uuid[] No Valid party ids. Use empty array for empty.
group_ids* uuid[] No Valid group ids. Use empty array for empty.
metrics Heatmap Metric[] No Valid array of metrics to caculate
suspended_at datetime When set to not-null, will override with current datetime Yes

* These entries only show on non-shallow payloads

Readonly / Optional / Meta properties

Name Type Can be Null Description
updated_at datetime Yes When the contract was last updated
created_at datetime No When the contract was created

Type: Heatmap Metric

This is a metric used to calculate data in the heatmap.

Name Type Description
field_id uuid null
label string A reference/name/label to use for this metric.
ref string Reference for this metric. Used to link back to different visualization metrics.
calc enum One of the possible calculation metrics, accepted: sum, count, avg, min, or max.
ranges integer[] Between 0 and 100. Ranges for use in visualization.

Type: Heatmap Query

This is the result set from a Heatmap executed query.

Top Level

Name Type Description
zoom integer Zoom level of this result 0-16
bound string WKT of the bounding box used for this operation
clusters array[] Array of clusters returned from this query

Clusters

Name Type Description Allow Null
datazone_id uuid If given, this cluster data belongs to a datazone. If null, then it does not. Yes
pins array[] Array of data pins for this cluster

Pins

Name Type Description Allow Null
lat string Valid latitude, range -90 to 90, If field is given, then this is null Yes
long string Valid longitude, range -180 to 180, if field is given, then this is nu;; Yes
field string The field value used for that group. If a group is given, then long and lat are null Yes
count integer Total number of items in a cluster pin. Could be 0 No
metrics array[] Total number of metrics in this cluster No

Metrics

Note, these are different than the Heatmap Metric type

Name Type Description Allow Null
field_id uuid The field ID used to generate this result metric No
ref string Reference field for this result No
percent number Percent value in comparison to the whole dataset. No
total number Raw total according to the metric's heatmap calculation

Type: Industry

This is an industry in the system, containing:

Name Type Allow Null Description
id uuid No Industry ID
name string No The industry name
archived_at datetime Yes When set to not-null, item is archied.

Readonly / Optional / Meta properties

Name Type Can be Null Description
created_at datetime No When the industry was created

Type: Job Title

This is a job title in the system, containing:

Name Type Allow Null Description
id uuid No Job Title ID
name string No The Job Title name
archived_at datetime Yes When set to not-null, item is archied.

Readonly / Optional / Meta properties

Name Type Can be Null Description
created_at datetime No When the industry was created

Type: Party

This is a party in the system, containing:

Name Type Allow Null Description
id uuid No Party ID
type_id uuid Yes The type of party Entity Type
first_name string No Max length 150
last_name string No Max length 150
email string Yes The administrative email for the party
phone string Yes The administrative phone for the party Valid e164 number format
avatar_media_id uuid Yes The avatar for the party (media ID)
avatar_url string Yes URL for the avatar if using a public URL (ie, via Google)
job_title uuid Yes The job title for the party (job title ID)
addresses* Address[] No Addresses for the entity. Use empty array for none.
profile* PartyProfile[] No Profile entries (to be migrated to custom fields) Use empty array for none

* Not on shallow payloads (ie, only given on get one, responses from create/updates)

Readonly / Optional / Meta properties

Name Type Can be Null Description
updated_at datetime Yes When the party was last updated
created_at datetime No When the party was created

Type: Party Association

This is an association between a party and a host object.

As an example, this defines the 'role' that a party has when associated with an entity. (ie, Primary Contact, Account Exec)

The roles are retrieved from the individual resource endpoints that they are for.

Name Type Allow Null Description
id uuid No Party ID
role_id uuid No The role from the appropriate mapping table

Type: Party Type

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Type ID
name string No The default type name
description string Yes A description of this type
base_type enum No One of the base types given below

Base Types

Type Description
user Party is of the type user
contact Party is of the base type contact

Type: Party Identity

These are identities assigned to the party. An identity is a way a user can log into the system.

Currently only the "email" identity type is supported.

The combination of type and identity must be unique across the system for that client. If it is not, then an 400 BAD REQUEST is returned.

Identity

Field Description
type The type of identity. See valid types.
identity The identifing key for this identity type.

Supported Types

Type Description
email Use this email as the user's identity

Type: Party Profile

Profile items are currently given in the key/val format as per Key/Val Object.

The following keys are accepted:

Key Description
title Text, max length 150
dob Text, max length 150
is_operational Text, max length 150

Type: Party Settings

Settings items are currently given in the key/val format as per Key/Val Object.

The following keys are accepted:

Key Description
welcome_template_id UUID (ID from /templates?type=welcome)

Type: Party SkillSet

These are instances of skillsets assigned to the party.

Name Type Allow Null Description
party_id uuid No The party ID
skillset_id uuid No The skillset ID
effective_at datetime Yes The date time this skillset is effective from
expires_at datetime Yes The date time this sillset expires for this party
doc_url string Yes A document link. Max length 5000

Type: Search Result

This is a search result in the system, containing:

Name Type Allow Null Description
id uuid No The ID for the found object
type Search Result Type No The type for this ID
name string The name for this ID/type resource
wkt string If given, the WKT of this object.
lat string If given, the latitude of this object.
long string If given, the longitude of this object.

Type: Search Result Type

The different kind of types that can be searched/retrieved.

Type Is Default Description
asset Yes An asset (address or geo location)
entity Yes An entity (via it's address)
party No Via it's assigned assets, NOT it's own address
service No Via it's assigned assets

Type: Service

This is a service in the system, containing:

Name Type Allow Null Description
id uuid No Service ID
name string No The service name
email string Yes Valid email
phone string Yes Valid e164 phone
description string Yes The service description, if any
type_id uuid No The Service Type uuid
category_id uuid No The Service Category uuid
suspended_at datetime Yes When set to not-null, will override with current datetime

Readonly / Optional / Meta properties

Name Type Can be Null Description
updated_at datetime Yes When the service was last updated
created_at datetime No When the service was created

Type: Service Type

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Service type ID
name string No The service type name
created_at datetime No When this service type was created

Type: Service Category

The following are the attributes given in the REST object.

Name Type Allow Null Description
id uuid No Service Category ID
name string No The service category name
created_at datetime No When this service category was created

Type: Skill Set

This is a skillset in the system, containing:

Name Type Allow Null Description
id uuid No Skill Set ID
name string Max length 150 No
description string Max length 5000 No
suspended_at datetime Yes When set to not-null, will override with current datetime

Readonly / Optional / Meta properties

Name Type Can be Null Description
updated_at datetime Yes When the skillset was last updated
created_at datetime No When the skillset was created

Type: User

This is a party's user in the system, containing:

Name Type Allow Null Description
id uuid No Party ID (User)
allow_sso boolean No If allow login via SSO
allow_otp boolean No If allow login via guest logins (aka OTP)
system_admin boolean No If user is a system admin

user signed into the system. (readonly) identities* | PartyIdentity[] | No | Identities (ie login identifiers). suspended_at | datetime | No | When set to not-null, will override with current datetime

* Not on shallow payloads (ie, only given on get one, responses from create/updates)

Readonly / Optional / Meta properties

Name Type Can be Null Description
first_name string No Max length 150 (readonly)
last_name string No Max length 150 (readonly)
email string Yes The administrative email for the party (readonly)
last_signin datetime Yes Only given on response payload. Last time this
updated_at datetime Yes When the party was last updated
created_at datetime No When the party was created

Type: GeoZone

The following is the geo type object used by territories and locations.

The data has the following constraints:

Attribute Type Restrictions Null allowed
id uuid Unique id No
lat string Valid latitude, range -90 to 90 Yes
long string Valid longitude, range -180 to 180 Yes
radius integer Radius in meters, range >= 0 Yes
wkt string Valid WKT (Well known text) Yes

Type: Address

{
  "valid_addresses": [{
    "name": "Main area",
    "country": "United States"
  }, {
    "name": "Our main catchment area",
    "country": "Canada",
    "region": "Alberta",
    "locale": "Rocky View County"
  }, {
    "name": "Head Office",
    "country": "Canada",
    "region": "Alberta",
    "city": "Calgary",
    "street": "1st St NW",
    "unit": "100",
    "lat": "52.023432",
    "long": "-0.126345"
  }, {
    "name": "Distribution Area",
    "country": "Canada",
    "postal": "T3A 0Z0"
  }]
}

This is an address entry in the system. It is not a first-class citizen, which means, it exists as part of another object, it's meta, or as a consequence. This is due to the non-specific and emphemeral nature of a lot of addresses. The Geo is considered the first-class citizen for geo-related activities.

Address Field Requires
name None
country None
region country
city country, region
locale country, region
street country, region, city
unit country, region, city, street
postal country
lat None
long None

Type: Identity

The following is the identity object used by parties.

Attribute Type Restrictions Null allowed
id email Valid Email No
suspended_at datetime None Yes

Type: Key Value

A common format for key/value data. Value has a max length of 500. If more data is required, consider if this is the best way of holding such data.

Attribute Type Description
key string Key for the data, max 150 length
val string Value of the data, max 500 length

Batch Error Output

For batch update endpoints, errors will be given in the response. An empty array generally means there were no failures.

A batch error output will adopt the following format:

{
  "errors": [{
    "id": "<uuid>", // The ID of the object which caused the error
    "code": "<error-code>", // The error code, ie 'eGroupNotFound'
    "msg": "<message>" // The human readible error message
  }, {
    ... more errors ...
  }]
}

Output

Different endpoints will return a different kind of output format

All list output will adopt the following format:

{
  "data": [{
    ... data for the object ...
  }, {
    ... data for the object ...
  }],
  "pagination": {
    // Pagination
    "page": 0,
    "per_page": 10,
    "total": 200
  },
  "sort": [{
    // Sort is generally an array, to support single
    // sorts and multiple sort.
    "field": "name",
    "direction": "asc" // Either asc or desc
  }],
  "warnings": [
    // Warnings are single strings - mostly just
    // for developer feedback and not for the user.
    "This is a warning"
  ]
}

For GET One, Create (POST), Update (PUT) will follow the format:

{
  "data": {
    ... data for the object ...
  },
  "warnings": [
    // Warnings are single strings - mostly just
    // for developer feedback and not for the user.
    "This is a warning"
  ]
}

Errors

{
  "errors": [{
    "code": "errorCode",
    "message": "errorMessage"
  }]
}

The following HTTP standard error codes are in use with the API:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- You need to authenticate or your token has expired.
403 Forbidden -- The request has is forbidden for the given token or token is invalid
404 Not Found -- The specified URL could not be found.
405 Method Not Allowed -- The method/verb for the given URL is not permitted.
406 Not Acceptable -- You requested a format that isn't json.
410 Gone -- The resource requested has been removed from our servers.
418 I'm a teapot.
429 Too Many Requests -- Too many requests, you're rate limited.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

In most cases, errors will be an array of 1. However, in somecases, it will be possible to give more than one error message per response.

See the individual resources for a list of possible error messages for each endpoint.