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...
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...
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
}
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.
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.
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.
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.
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.
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.
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...
0
for the changeToken
in swaggerUnfortunately, 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
.
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.
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.
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...
0
for the changeToken
in swaggerUnfortunately, 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
.
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.
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
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.
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!