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:
- Calculations, such as a count of inherited objects
- The permissions (
__permissions__) array, the system admin (__system_admin__) flag on parties.
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:
- You are a systems administrator, and the permission check bypassed.
- It is an object that has no permission control in the system
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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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:
- Theme
- Vocabulary (ie, name changes)
- Base permissions for current users
- Phases, messages, etc
- Tab and configurations
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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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)
- Geo
- Commercial
A geo datazone is a zone described by various geo parameters. These include
- Longitude & Latitude, as a single point (via the Geo object)
- Longitude & Latitude, as a radius (via the Geo object)
- WKT (Well-known-text) a geometric polygon shape (via the Geo object)
- Locations via addresses (See Address)
The geo datazone an also have the following properties:
- Specific addresses
- Specific geo data/zones
- Specific entities
- Specific contracts
A commercial datazone can have the following propreties:
- Specified industries that is applies to
- Specific entities
- Specific contracts
The following hard rules are applied:
- A Commercial datazone cannot contain any geo information, addresses.
- 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:
owner_idsaddresses
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
geoobject 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
countswill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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
datacontaining an array of all geozones for that datazone. A valid response will be a200 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 REQUESTwill 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 REQUESTwill 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:
- The SUBJECT (the main object this relates to)
- The OBJECT (the other object whence this subject has a relationship with)
Subjects
Currently, the following subjects are supported:
- Assets
Objects
The following objects are supported:
- Assets
- Contracts
- Services
- (None)
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:
- field
- contractExpiry (contract/accounts only)
- skillsets (parties only)
- summary
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:
- Ensure that only relavent item types can be selected for the current subject/object type
- If an invalid type is received, ignore it, and log an error.
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.

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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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, a400 BAD REQUESTwill 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, a400 BAD REQUESTwill 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 REQUESTwill 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)
- User
- Territory
- Feature
- Operational
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:
- 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.
- Only operational groups may inherit from operational groups3. The data array is context specific to the base group type
- Groups without supplementary data may have their
metaattribute set tonull, if they do not have any additional data.
How groups are structured

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:
itemsowner_idsinherit_ids
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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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, a400 BAD REQUESTwill 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, a400 BAD REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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
clusterregioncountrycity
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.
- When we reach stablility, I will remove these query params and make these fields the default.
- If there are any we want to keep, for customer configuration etc, we will then adjust so they remain a query parameter.
- Please avoid changing
node_sizeif 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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:
- User
- Contact
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:
- Work SSO Email
- Personal Email
- Mobile Phone Number
- Username
- 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 |
| 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 REQUESTwill 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 REQUESTwill 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 |
| 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 REQUESTwill 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 |
| 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 REQUESTwill 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 REQUESTwill 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
heatmapentity
Supported types
pinfavorite
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 REQUESTwill 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 |
| 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 REQUESTwill 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 REQUESTwill be returned.
Will update the user for the given party ID. If the party does not have a user, then one is created.
IDcan be given in the payload but is ignored.first_name,last_name,emailare from the party. They will be ignored, and can be omitted.last_signinthis is a read only field. It can be omitted. If given, will be ignored.allow_otpthese are One-Time-Passwords aka Guest Logins.
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 REQUESTwill 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 REQUESTwill 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
- Make the return schema minimally descriptive
- Make the schema relevant to all returned resources
- 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.
LOCATIONS Search
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
- All words given are performed in an AND fashion
- You can use keywords:
AND,OR, andNOT - You can use brackets to make the order of presidence explict
- 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 REQUESTwill 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 REQUESTwill 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 |
| 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 REQUESTwill 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 |
| 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill 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 REQUESTwill be returned.
This endpoint retrieves login configuration, settings, and permissions for the current logged in user.
The current returned properties:
party_idThe current party ID of the logged in user (not the user ID)permissionsA list of permissions grouped by the operational group that issues them. If the group isnullthen the permissions are directly applied to a user group and not derived from an operational group.settingsA list of all the custom settings for this user in the context on the current tentant.
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:
- Geo DataZone
- Commercial DataZone
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 |
| 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 |
| 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) |
| 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:
- If WKT (Well-Known Text) is given, then
long,lat, andradiusMUST benull - If WKT is
null, then long/lat will be required
| 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 | 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.