Skip to main content

Content Items

Once you have defined a content type, you can add items of that type - the so called content items.

1. Querying content items

Gets all content items regardless of their type.

Example:

GET https://dev.iclportal.com/api/content?$inlinecount=allpages&$top=20 HTTP1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

The response is a JSON array of content items:

{
"result": {
"__count": 2932,
"results": [
{
"bezeichnung": "Wien, Hansonstrasse 23",
"adresse": "Hansonstrasse 23",
"ort": "Wien",
"nummer": "GB-00012",
"plz": "1100",
"contentItemId": "18c7a93c-0865-4922-af34-31d112e4d2ac",
"externalId": "OPTI-Q1",
"lastModificationTime": "2020-10-09T13:19:29.673Z",
"isDeleted": false,
"creatorUserId": null,
"creatorUser": null,
"lastModifierUserId": 2,
"lastModifierUser": "Antoine Gadget",
"title": "Wien, Hansonstrasse 23"
},
...
]
},
"targetUrl": null,
"success": true,
"error": null,
"unAuthorizedRequest": false,
"__abp": true
}

You can query the API using OData v3 query syntax, however, as this endpoint delivers items of all types, only the common fields can be used to be filtered. These are: contentItemId, title, externalId Any custom fields, while being returned by the endpoint, cannot be used to filter.

Example:

GET https://dev.iclportal.com/api/content?$filter=substringof('hansonstrasse',tolower(Title))&$inlinecount=allpages&$top=20 HTTP1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
Uppercased attribute names

Note that the property Title is uppercased in the query string. This is an OData v3 requirement.

The response is a JSON array of content items:

{
"result": {
"__count": 1,
"results": [
{
"bezeichnung": "Wien, Hansonstrasse 23",
"adresse": "Hansonstrasse 23",
"ort": "Wien",
"nummer": "GB-00012",
"plz": "1100",
"contentItemId": "18c7a93c-0865-4922-af34-31d112e4d2ac",
"externalId": "OPTI-Q1",
"lastModificationTime": "2020-10-09T13:19:29.673Z",
"isDeleted": false,
"creatorUserId": null,
"creatorUser": null,
"lastModifierUserId": 2,
"lastModifierUser": "Antoine Gadget",
"title": "Wien, Hansonstrasse 23"
}
]
},
"targetUrl": null,
"success": true,
"error": null,
"unAuthorizedRequest": false,
"__abp": true
}

1. Querying content items of a specific type

Gets all content items of a specific type.

Example:

GET https://dev.iclportal.com/api/content/building?$inlinecount=allpages&$top=20 HTTP1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

The response is a JSON array of content items:

{
"result": {
"__count": 2932,
"results": [
{
"bezeichnung": "Wien, Hansonstrasse 23",
"adresse": "Hansonstrasse 23",
"ort": "Wien",
"nummer": "GB-00012",
"plz": "1100",
"contentItemId": "18c7a93c-0865-4922-af34-31d112e4d2ac",
"externalId": "OPTI-Q1",
"lastModificationTime": "2020-10-09T13:19:29.673Z",
"isDeleted": false,
"creatorUserId": null,
"creatorUser": null,
"lastModifierUserId": 2,
"lastModifierUser": "Antoine Gadget",
"title": "Wien, Hansonstrasse 23"
},
...
]
},
"targetUrl": null,
"success": true,
"error": null,
"unAuthorizedRequest": false,
"__abp": true
}

You can query the API using OData v3 query syntax. Any custom or internal (title, externalid, contentItemId) field can be used.

Example:

GET https://dev.iclportal.com/api/content/building?$filter=substringof('hansonstrasse',tolower(Adresse))&$inlinecount=allpages&$top=20 HTTP1.1
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...
Uppercased attribute names

Note that the property Adresse is uppercased in the query string even though it must be defined lowercased in the content type. This is an OData v3 requirement.

The response is a JSON array of content items:

{
"result": {
"__count": 1,
"results": [
{
"bezeichnung": "Wien, Hansonstrasse 23",
"adresse": "Hansonstrasse 23",
"ort": "Wien",
"nummer": "GB-00012",
"plz": "1100",
"contentItemId": "18c7a93c-0865-4922-af34-31d112e4d2ac",
"externalId": "OPTI-Q1",
"lastModificationTime": "2020-10-09T13:19:29.673Z",
"isDeleted": false,
"creatorUserId": null,
"creatorUser": null,
"lastModifierUserId": 2,
"lastModifierUser": "Antoine Gadget",
"title": "Wien, Hansonstrasse 23"
}
]
},
"targetUrl": null,
"success": true,
"error": null,
"unAuthorizedRequest": false,
"__abp": true
}
use Portal UI to create query

To create the query, you can simply use the iCL Portal data grid of the given content type and specify the sorts and filters there. Then, use your browsers development tools to look at the created request in the network tab:

3. Creating a content item

Creates a new content item. Note that only required fields need to be specified. If you create an item that references another one using a content field of type ContentItem (e.g. you create a building that belongs to some site), you can specify that site either by its contentItemId or externalId.

Example

POST https://dev.iclportal.com/api/content/building
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

{
"externalId":"HG",
"buildingname":"HG10223",
"strasse":"Hansongasse 23",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien"
}

The response is the completed json object - including all internal fields.

{
"buildingname":"HG10223",
"strasse":"Hansongasse 23",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien",
"contentItemId":"39d83715-b7d0-4a1e-88a7-bed24d5ab8a0",
"_id":"a8218840-e764-46b7-a289-9e52b65cff66",
"externalId":"HG",
"lastModificationTime":"2023-03-14T12:42:41.1951367Z",
"isDeleted":false,
"creatorUserId":2,
"creatorUser":"Antoine Gadget",
"lastModifierUserId":null,
"lastModifierUser":null
}

4. Getting a content item

By specifying the items internal _id, contentItemId or externalId, you can retrieve an item.

The following requests all return the same result:

Example: using the internal _id

Get https://dev.iclportal.com/api/content/building/a8218840-e764-46b7-a289-9e52b65cff66
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

Example: using the contentItemId

Get https://dev.iclportal.com/api/content/building/39d83715-b7d0-4a1e-88a7-bed24d5ab8a0
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

Example: using the externalId

Get https://dev.iclportal.com/api/content/building/HG
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

Return:

{
"buildingname":"HG10223",
"strasse":"Hansongasse 23",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien",
"contentItemId":"39d83715-b7d0-4a1e-88a7-bed24d5ab8a0",
"_id":"a8218840-e764-46b7-a289-9e52b65cff66",
"externalId":"HG",
"lastModificationTime":"2023-03-14T12:42:41.1951367Z",
"isDeleted":false,
"creatorUserId":2,
"creatorUser":"Antoine Gadget",
"lastModifierUserId":null,
"lastModifierUser":null
}

5. Updating a content item

Updates an existing content item. If you create an item that references another one using a content field of type ContentItem (e.g. you create a building that belongs to some site), you can specify that site either by its contentItemId or externalId. You can use the items internal _id, contentItemId or externalId to identify an item.

PUT replaces all data

This method is not a PATCH, but a PUT operation. Any attributes that are not included in the request will be deleted from the item!

Example - using externalId but omitting the field strasse

PUT https://dev.iclportal.com/api/content/building/HG
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

{
"externalId":"HG",
"buildingname":"HG10223",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien"
}

The response is the completed json object - including all internal fields. Note that the field strasse was omitted in the request and therefore is removed from the item.

{
"buildingname":"HG10223",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien",
"contentItemId":"39d83715-b7d0-4a1e-88a7-bed24d5ab8a0",
"_id":"a8218840-e764-46b7-a289-9e52b65cff66",
"externalId":"HG",
"lastModificationTime":"2023-03-14T12:42:41.1951367Z",
"isDeleted":false,
"creatorUserId":2,
"creatorUser":"Antoine Gadget",
"lastModifierUserId":null,
"lastModifierUser":null
}

6. Deleting a content item

Deletes an existing content item. You can use the items internal _id, contentItemId or externalId to identify an item.

This is a soft delete

Content items are never actually deleted from the database to prevent data loss. Instead, their column IsDeleted is set to true and they are filtered from any future requests.

Example - using externalId

DELETE https://dev.iclportal.com/api/content/building/HG
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

The response will be empty and contain the corresponding status code:

  • 200 OK for success,
  • 400 Bad request in case you did something wrong
  • 404 Not found in case the item does not exist or was previously deleted

7. Adding/updating multiple content items at once

This endpoint allows you to add or update multiple content items in one batch. The items are identified by their externalId. In case an item is found, it is updated. If not, a new item is create.

an update replaces all data

In case an existing item is found, the update acts like a PUT operation. Any attributes that are not included in the request will be deleted from the item!

If any item has validation errors, the whole batch is rolled back. If an item references another one using a content field of type ContentItem (e.g. you create a building that belongs to some site), you can specify that site either by its contentItemId or externalId.

Example

PUT https://dev.iclportal.com/api/content/building/batch
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

[
{
"externalId":"HG",
"buildingname":"HG10223",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien"
},
{
"externalId":"LHS101",
"buildingname":"LANHS101",
"stiege":"10",
"strasse":"Landstraßer Hauptstraße",
"stock":1,
"topnr":"GO11",
"plz":"1030",
"ort":"Wien"
}
}

The response is a summary of all the succeeded or errored adds or updates:

{
"errored": [
{
"externalId": "HG",
"error": "The field 'strasse' is required"
}
],
"succeeded": [
{
"externalId": "LHS101",
"id": "65942320-d1c4-420d-b768-b0ca1ca35fba" // the contentitemid of the created item
}
]
}

8. Adding/updating multiple content items at once - ignoring errors

This endpoint allows you to add or update multiple content items in one batch. The items are identified by their externalId. In case an item is found, it is updated. If not, a new item is create.

an update replaces all data

In case an existing item is found, the update acts like a PUT operation. Any attributes that are not included in the request will be deleted from the item!

In case of an error, the operation is continued. All valid items will be stored. No rollback is happening.

For integration scenarios

This endpoint is intended for integration scenarios with tools such as SSIS or Azure Data Factory. In case of an error, you can return those e.g. per e-mail to the user in the source system, so (s)he can fix the issues of the failed items

If an item references another one using a content field of type ContentItem (e.g. you create a building that belongs to some site), you can specify that site either by its contentItemId or externalId.

Example

PUT https://dev.iclportal.com/api/content/building/batch
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

[
{
"externalId":"HG",
"buildingname":"HG10223",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien"
},
{
"externalId":"LHS101",
"buildingname":"LANHS101",
"stiege":"10",
"strasse":"Landstraßer Hauptstraße",
"stock":1,
"topnr":"GO11",
"plz":"1030",
"ort":"Wien"
}
}

The response is a summary of all the succeeded or errored adds or updates:

{
"errored": [
{
"externalId": "HG",
"error": "The field 'strasse' is required"
}
],
"succeeded": [
{
"externalId": "LHS101",
"id": "65942320-d1c4-420d-b768-b0ca1ca35fba" // the contentitemid of the created item
}
]
}

9. Get changes of items of all types

This endpoint returns all Content items regardless of their type that changed since a specific point in time. This point in time is denoted as changeToken and provided as query argument. If you omit this changeToken you essentially get all content items.

use this for incremental data synchronization

This endpoint is intended to be used in integration scenarios, where you need to synchronize content items from iCL Portal to some external system of your choice. To be as efficient as possible, it allows you to get incremental changes, so that you do not have to go through an evergrowing list of items until you run into timeouts.

The following sample shows the first request (omitting the cangeToken)

GET https://dev.iclportal.com/api/content/getchanges
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

use 0 for the changeToken in swagger

Unfortunately, swagger does not understand, that chagneToken is an optional parameter. To be able to play with this endpoint in swagger UI, use the value 0. The endpoint will simply ignore this magic value

The response will include any items that changed since that point in time and will include a NextChangeToken which can be used to get the next page of chagnes. Alternatively you can use the NextLink.

limited to 500 results

Note that the result set is limited to 500 items. You need to page through the data if you have more than 500 items/changes.

{
"Results": [
{
"bezeichnung": "LSHS101-1030",
"adresse": "Landstraßer Hauptstraße 101",
"ort": "Wien",
"nummer": "101",
"contentItemId": "683a34a9-b832-490a-8ab1-5d98aafc7d7f",
"externalId": "LSHS101-1030",
"lastModificationTime": "2018-11-20T15:21:43.767Z",
"isDeleted": true,
"$type": "gebaude"
},
{
"beschreibung": "Der DHL Bote findet den Eingang zu Opti-Q (Altstiege 2) nie",
"objektid": "683a34a9-b832-490a-8ab1-5d98aafc7d7f",
"gewerk": "Paketdienst",
"status": 0,
"frist": "2018-11-29T23:00:00Z",
"contentItemId": "f66ba90c-819d-40c4-acdc-984220ba04b0",
"externalId": null,
"lastModificationTime": "2018-12-11T15:55:05.963Z",
"isDeleted": true,
"$type": "mangel"
},
...
],
"NextChangeToken": "AAAAAAADRF8",
"NextLink": "https://testportal.opti-q.com/api/content/getchanges?changeToken=AAAAAAADRF8"
}

Since the content type is not specified, every result will contain a $type attribute to indicate the items content type. Once you reached the last page, the Results array will be empty and the NextChageToken will not change anymore.

this endpoint also returns deleted items

Since this endpoint is intended to be used for synchronization scenarios, it will also return deleted items. In that case, their isDeleted attribute will be true

10. Get changes of items of a specific type

This endpoint returns all Content items regardless of their type that changed since a specific point in time. This point in time is denoted as changeToken and provided as query argument. If you omit this changeToken you essentially get all content items.

use this for incremental data synchronization

This endpoint is intended to be used in integration scenarios, where you need to synchronize content items from iCL Portal to some external system of your choice. To be as efficient as possible, it allows you to get incremental changes, so that you do not have to go through an evergrowing list of items until you run into timeouts.

The following sample shows the first request (omitting the cangeToken)

GET https://dev.iclportal.com/api/content/building/getchanges
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
Authorization: Bearer ..the auth_token...

use 0 for the changeToken in swagger

Unfortunately, swagger does not understand, that chagneToken is an optional parameter. To be able to play with this endpoint in swagger UI, use the value 0. The endpoint will simply ignore this magic value

The response will include any items that changed since that point in time and will include a NextChangeToken which can be used to get the next page of chagnes. Alternatively you can use the NextLink.

limited to 500 results

Note that the result set is limited to 500 items. You need to page through the data if you have more than 500 items/changes.

{
"Results": [
{
"bezeichnung": "LSHS101-1030",
"strasse": "Landstraßer Hauptstraße 101",
"ort": "Wien",
"topnr": "101",
"contentItemId": "683a34a9-b832-490a-8ab1-5d98aafc7d7f",
"externalId": "LSHS101-1030",
"lastModificationTime": "2018-11-20T15:21:43.767Z",
"isDeleted": true
},
{
"buildingname":"HG10223",
"strasse":"Hansongasse 23",
"stiege":"1",
"stock":4,
"topnr":"43",
"plz":"1010",
"ort":"Wien",
"contentItemId":"39d83715-b7d0-4a1e-88a7-bed24d5ab8a0",
"externalId":"HG",
"lastModificationTime":"2023-03-14T12:42:41.1951367Z",
"isDeleted":false
},
...
],
"NextChangeToken": "AAAAAAADRF8",
"NextLink": "https://testportal.opti-q.com/api/content/getchanges?changeToken=AAAAAAADRF8"
}

Since the content type is specified explicitly, the items do not contain the $type attribute. Once you reached the last page, the Results array will be empty and the NextChageToken will not change anymore.

this endpoint also returns deleted items

Since this endpoint is intended to be used for synchronization scenarios, it will also return deleted items. In that case, their isDeleted attribute will be true

Directly get to the last page

As there are no more changes, the system simply returns the latest change available, which is usually the very same change token we just used in the request.

However, you can use this mechanism to get straight to the last page of changed content items by using the highest possible change token __________8 This comes in handy, if you only want to start for getting changes from now on and do not wish to go through all the historical changes.

11. Downloading an Excel template

This endpoint allows you to download an excel workbook which can be used to import content items to iCL Portal. For this, fill in the workbook and drag-and-drop it into any conten item datagrid.

keeps non specified columns

In case one of the imported items already exists, the items properties will be updated with the values coming from the import file. In case a column is not specified, the field will not be deleted from the item, but simply not touched. This allows you to update only specific fields of a conten item without deleting anything else that is not specified!

Note that the column ExternalId is required in this case. This is to ensure, that users do not accidentally upload the same Excel workbook multiple times and end up with duplicated data!