Content Types
iCL allows you to quickly create powerful check lists to gather information on various things. In many cases you will want to track those "things" as separate data. For example, when doing building inspections, it is advisable to store all the data of a building in a separate table. Then, whenever that building is inspected, you can use its data to pre-fill parts of your checklists.
Buildings, fire fighting equipment, elevator types, customer information, ... in iCL these can be modeled with content types. A content type defines
- the fields that it stores (name, address, building year, ...)
- the relationships to other content types (e.g. an elevator belongs to a building)
- the form to edit its data
- advanced rules regarding how it is synchronized and more.
To understand the structure and contents of a content type definition, please read the content types guide
This API can be used to create, update and delete content types.
Each endpoint requires a permission, which is listed in its section. If the calling user lacks it, the API responds with 403 Forbidden (401 Unauthorized if the request is not authenticated at all).
Invalid requests and content type definitions are rejected with 400 Bad Request and an error message.
1. Querying content types
Gets all content types that are currently defined.
Required permission: ContentTypes.List
Example:
GET https://dev.iclportal.com/api/contenttypes?$inlinecount=allpages&$top=20 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
The response is a JSON object. result.results contains the content types, result.__count the total number of content types:
{
"result": {
"results": [
{
"contentTypeId": "31d1d26b-1475-477e-ab21-13d8fd2dc7ea",
"name": "building",
"canBeInspected": false,
"builtInTypeId": 0,
"filteredSynchronization": false,
"syncConflictResolution": 0,
"creationTime": "2021-06-17T08:27:01.22Z",
"lastModificationTime": "2021-06-17T13:15:40.58Z"
},
...
],
"__count": 117
},
"targetUrl": null,
"success": true,
"error": null,
"unAuthorizedRequest": false,
"__abp": true
}
At most 50 content types are returned per request. If there are more, result.__next contains the relative URL (path and query) of the next page.
2. Retrieving a content type definition
Allows to retrieve the full definition of a content type.
Required permission: ContentTypes.View
Example: to get the definition of the building, call
GET https://dev.iclportal.com/api/contenttypes/building HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
This will return the definition as a json document
{
"name": "building",
"displayName": "Building",
"builtinTypeId": 0,
"canBeInspected": true,
"titleFieldName": "buildingname",
"fields": [
{
"type": "ShortText",
"name": "buildingname",
"displayName": "Objektnummer",
"isRequired": true,
"isIndexed": false
},
{
"type": "ShortText",
"name": "zipcode",
"displayName": "ZIP",
"isRequired": false
},
...
],
...
}
The syncRules of the returned definition also contain the built-in parent rule if it applies to the content type, even if the stored definition does not list it.
If no content type with the given name exists, the API responds with 404 Not Found.
To understand the structure and contents of a content type definition, please read the content types guide
3. Downloading a content type definition
This endpoint returns essentially the same information as Retrieving a content type definition However, it returns those as a download file response:
Required permission: ContentTypes.View
GET https://dev.iclportal.com/api/contenttypes/building/download HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
This will return the definition as a json document, but attach the following response headers, so that browsers interpret the response as file download. The file is named after the content type (<name>.json):
"cache-control": "no-store, must-revalidate, no-cache, max-age=0",
"content-disposition": "attachment; filename=building.json",
"content-encoding": "gzip",
"content-length": "871",
"content-type": "application/json",
"date": "Fri, 03 Feb 2023 09:17:20 GMT",
"server": "Microsoft-IIS/10.0",
"x-aspnet-version": "4.0.30319",
"x-powered-by": "ASP.NET"
If no content type with the given name exists, the API responds with 404 Not Found.
4. Creating a content type
Allows to create a new content type.
Required permission: ContentTypes.Create
A content type must always have a unique id. While content type names must be unique, this requirement is to ensure that no name-clashes happen without anyone noticing. E.g. two users create a content type named "building" but with totally different fields and configuration. In the worst case, this could cause data loss. To get a unique id for your content type get a GUID from here
The content type name in the URL must match the name in the request body (case-insensitive).
Names are stored in lowercase: the portal converts the name of the content type, its titleFieldName, the names of its fields and the foreign key fields of its relationships to lowercase.
Example
POST https://dev.iclportal.com/api/contenttypes/elevator HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
{
"id": "fee7bb0d-7f53-4a86-8696-c9cf683680a9",
"name": "elevator",
"displayName": "Elevator",
"builtinTypeId": 0,
"canBeInspected": true,
"titleFieldName": "elevator_name",
"fields": [
{
"type": "ShortText",
"name": "elevator_name",
"displayName": "Aufzugsname",
"isRequired": true,
"isIndexed": false
},
{
"type": "ShortText",
"name": "zipcode",
"displayName": "ZIP",
"isRequired": false
}
]
}
On success, the API responds with 200 OK and an empty body.
It responds with 400 Bad Request if
- the request body is empty or has no
id - the name in the URL and the
namein the body do not match - a content type with the same
idalready exists (use the update endpoint instead) - another content type with the same name already exists
- the definition is invalid (e.g. invalid fields, relationships or sync rules)
5. Updating a content type
The update method will alter titles of a content type as well as add new columns - so basically the same, what a normal drag&drop upload on the portal will do. Only non breaking changes are allowed:
- adding a new field to a content type
- changing the display name of some field or content type
- changing some field to be
required - etc.
Required permission: ContentTypes.Edit
If no content type with the given id exists yet, it is created. So this endpoint can also be used to create or update a content type in one step.
As when creating a content type, the name in the URL must match the name in the body. The name of an existing content type cannot be changed.
In the following example, we change the displayName of the field elevator_name to English, which is a non-breaking change:
Example
PUT https://dev.iclportal.com/api/contenttypes/elevator HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
{
"id": "fee7bb0d-7f53-4a86-8696-c9cf683680a9",
"name": "elevator",
"displayName": "Elevator",
"builtinTypeId": 0,
"canBeInspected": true,
"titleFieldName": "elevator_name",
"fields": [
{
"type": "ShortText",
"name": "elevator_name",
"displayName": "Elevator name",
"isRequired": true,
"isIndexed": false
},
{
"type": "ShortText",
"name": "zipcode",
"displayName": "ZIP",
"isRequired": false
}
]
}
On success, the API responds with 200 OK and an empty body. Breaking changes and invalid definitions are rejected with 400 Bad Request.
When updating a content type, any items of that type will not be changed at all. Rather, the new content type definition is used by the system to know how to load and save an existing content item. That said: Whenever you add a field to a content type, this field will not automatically be added to each item. Rather, the next time the item is saved this field will also be stored. This approach is based on a design decision to reduce synchronization conflicts. If all items would be changed instantly, any changes performed by disconnected apps would cause a merge conflict.
6. Update of a content type with breaking changes
A forced update will be able to overwrite the existing content types structure by changing titles, field names, datatypes and even by removing entire fields.
This action allows to perform breaking changes and may lead to data loss.
Required permission: ContentTypes.Edit
Such breaking changes include:
- changing the name of a content types field
- changing the type of a content type field
- removing a field from a content type
The name of a content type cannot be changed, not even with a forced update. Such a request is rejected with 400 Bad Request.
Sync rules are validated in any case: a forced update with invalid sync rules is rejected as well.
Because breaking changes can lead to serious issues, we strongly discourage you to ever introduce them in your production system. If you are still working in some development or test environment, though, where you are safe to break things, you can use the following approach to update a content type
The following example changes the type of the zip-code field from ShortText to Number, thereby introducing a breaking change
PUT https://dev.iclportal.com/api/contenttypes/elevator/force HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
{
"id": "fee7bb0d-7f53-4a86-8696-c9cf683680a9",
"name": "elevator",
"displayName": "Elevator",
"builtinTypeId": 0,
"canBeInspected": true,
"titleFieldName": "elevator_name",
"fields": [
{
"type": "ShortText",
"name": "elevator_name",
"displayName": "Elevator name",
"isRequired": true,
"isIndexed": false
},
{
"type": "Number",
"name": "zipcode",
"displayName": "ZIP",
"isRequired": false
}
]
}
When updating a content type, any items of that type will not be changed at all. Rather, the new content type definition is used by the system to know how to load and save an existing content item.
For example, if you change the type of a field from ShortText to Number, all existing items will still keep their field stored as ShortText.
The next time, however, that such an item is loaded, the iCL system tries to automatically convert the stored value to the new type. If it fails to do so, it will clear the field.
But only if the system then stores this loaded content item with the converted field, the old field value will effectively be overwritten.
This means: In case you errornously change the type of a field, the existing data is not instantly lost. So you can still revert your changes (by changing back the field type) and any item that has not been saved using the invalid type definition will still have the original field value.
This approach is based on a design decision to reduce synchronization conflicts. If all items would be changed instantly, any changes performed by disconnected apps would cause a merge conflict.
7. Deleting a content type
A content type can only be deleted with this endpoint if no other content type has a relationship to it and no workbook on the portal uses it. Otherwise, the API responds with 400 Bad Request and lists the referring content types or workbooks.
Relationships of the deleted content type itself to other content types do not prevent the deletion.
Required permission: ContentTypes.Delete
All items of that content type will be deleted as well.
Example
DELETE https://dev.iclportal.com/api/contenttypes/building HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
On success, the API responds with 200 OK and an empty body. If no content type with the given name exists, it responds with 404 Not Found.
8. Deleting a used content type
In case a content type is already
- referenced by some workbook
- having other content types relating to it (relationship) deleting it would introduce a breaking change. If you are sure of what you do and you still need to delete it, use this endpoint. It skips these checks.
Required permission: ContentTypes.Delete
All items of that content type will be deleted
Because breaking changes can lead to serious issues, we strongly discourage you to ever introduce them in your production system. If you are still working in some development or test environment, though, where you are safe to break things, you can use the following approach to delete a content type
DELETE https://dev.iclportal.com/api/contenttypes/building/force HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
On success, the API responds with 200 OK and an empty body. If no content type with the given name exists, it responds with 404 Not Found.
9. Resetting the sync filters of all content types
When sync rules are evaluated per item, they are valid until midnight of the next day. This is stored in the column ExpirationDate;
This means, that if a sync rule determines that some item "building A" should be synchronized, this remains in effect until the next day.
Only thereafter they will be evaluated again in order to determine, whether some items should actually not be synchronized anymore but deleted from the users devices.
So even if the next incremental evaluation determines that "building A" should not be synchronized anymore, it will remain on the device until the ExpirationDate is reached.
This behavior only delays the removal of items from remote devices. If a new item should be synchronized, this will take effect immediately.
This endpoint lets the sync filters of all content types expire that were set by an active sync rule and would otherwise expire at the next midnight. Filters that have already expired or that expire later are not changed. It then starts the re-evaluation process, which usually only runs every night, as a background job.
Required permission: ContentTypes.Edit
POST https://dev.iclportal.com/api/contenttypes/syncfilters/reset HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
The response contains the number of sync filters that were reset:
{
"numberOfResetSyncFilters": 42
}
Re-calculating sync filters may take some time and can impact the performance of the database. So use this endpoint with caution.
10. Downloading an Excel import template
Returns an Excel file (.xlsx) that can be filled in to import content items of one or more content types.
It contains one worksheet per content type, named after the content type. The first row of each worksheet contains the column headers Id and ExternalId, followed by the names of the content type's fields.
Required permission: ContentTypes.View
Pass the names of the content types in the query parameter contentTypeNames, once per content type. Names that do not match an existing content type are ignored.
GET https://dev.iclportal.com/api/contenttypes/download/excel?contentTypeNames=building&contentTypeNames=elevator HTTP/1.1
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
The file is returned as a download (Content-Disposition: attachment) named <tenant id>_ContentTypes_template.xlsx.
To download the template of a single content type, you can also use the Content Items API.