Skip to main content

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.
technical guide on content types

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.

technical guide on content types

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

content types with unique IDs

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 name in the body do not match
  • a content type with the same id already 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.

updates

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.

Read the guide on merge conflicts for further information

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
note

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.

breaking changes

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
}
]
}
reverting invalid changes

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.

Read the guide on merge conflicts for further information

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

note

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

note

All items of that content type will be deleted

breaking changes

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.

note

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
}
performance impact

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.

tip

To download the template of a single content type, you can also use the Content Items API.