Markers - Entity Marker
Using Entity Markers
-
Iterate over the list of project IDs and for each project ID.
-
Execute a GET request on the kahua Marker endpoint for the kahua_Issue.Issue entity definition.
-
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Issue/entitydefs/Issue/markers/from/0
-
If the response is empty continue to the next project ID. This means no issues were recently changed in this project.
-
If the response is not empty, extract the largest Marker ID and the smallest MarkerTime.
Copy{
"markers": [
{
"id": 6913914,
"markerTime": "2020-12-15T00:53:55.573Z",
"entityDefName": "kahua_Issue.Issue",
"entityId": 6185478,
"entityInstanceId": 6185516,
"entityPartitionId": 1952888,
"domainPartitionId": 1952888,
"type": "Update"
},
{
"id": 6913915,
"markerTime": "2020-12-15T00:53:55.527Z",
"entityDefName": "kahua_Issue.Issue",
"entityId": 6185478,
"entityInstanceId": 6185515,
"entityPartitionId": 1952888,
"domainPartitionId": 1952888,
"type": "Update"
}
]
} -
Save the largest Marker ID in your code as the "LargestMarkerId".
-
Use the smallest MarkerTime as your LastModifiedDateTime parameter with the GetIssueRevision endpoint to get data as normal. This will get you issues that have recently changed since that time.
-
Continue to the next project ID and repeat using the original Marker ID in the request (For this example: 0). Compare your next non-empty response's largest Marker ID with the saved LargestMarkerId. If it is bigger then save it as the new LargestMarkerId.
-
-
After time passes and you are ready to make your next data pull from Kahua, use the LargestMarkerId you saved the last time. Use this in place of 0 for the next set of requests. Each time you execute a new set of data pulls from Kahua use the LargestMarkerId from your last data pull. You can use the same marker ID for your three groups of requests: contracts, change orders, and issues. Changes to the items are interpreted as changes to the parent entity, so you should only need to repeat step 1 above for those three entities.
-
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Issue/entitydefs/Issue/markers/from/LargestMarkerId
-
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Contract/entitydefs/Contract/markers/from/LargestMarkerId
-
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_ContractChangeOrder/entitydefs/ContractChangeOrder/markers/from/LargestMarkerId
-
Here is some documentation that describes how to use the Marker endpoint in general. Please test it out in Postman to get familiar with the endpoint.
The format of the call is like this:
GET /v1/domains/{{domain}}/projects/:projectId/apps/:appname/entitydefs/:entitydef/markers/from/:lastmarker
Where you need to supply the appname, entity def, and lastmarker.
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Issue/entitydefs/Issue/markers/from/LargestMarkerId
The last marker would typically be saved from the previous call, and this would return a list of all changes to the given entity since that marker. You can start with a marker of zero.
Markers are only stored for approximately the past 30 days. Sending zero as the last marker will only return those changes made in the last 30 days.
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Contract/entitydefs/Contract/markers/from/0
Result:
{
"markers": []
}
After you add a contract, here is the result for the same call:
Result:
{
"markers": [
{
"id": 6446784,
"markerTime": "2020-10-02T14:14:38.16Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808097,
"entityInstanceId": 5808097,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Add"
},
{
"id": 6446786,
"markerTime": "2020-10-02T14:14:43.53Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808097,
"entityInstanceId": 5808097,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Invalidate"
},
{
"id": 6446787,
"markerTime": "2020-10-02T14:14:43.55Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808097,
"entityInstanceId": 5808097,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Invalidate"
}
]
}
You can then save the last marker in the list, 6446787, to detect changes that happen after that point. If you run it immediately before any activity, you'd still get an empty list:
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Contract/entitydefs/Contract/markers/from/6446787
If you then make more changes, that same call will return changes since the given marker:
{
"markers": [
{
"id": 6446788,
"markerTime": "2020-10-02T14:15:00.443Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808097,
"entityInstanceId": 5808099,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Update"
},
{
"id": 6446791,
"markerTime": "2020-10-02T14:18:35.873Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808102,
"entityInstanceId": 5808102,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Add"
},
{
"id": 6446793,
"markerTime": "2020-10-02T14:18:36.733Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808102,
"entityInstanceId": 5808102,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Invalidate"
},
{
"id": 6446794,
"markerTime": "2020-10-02T14:18:36.747Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808102,
"entityInstanceId": 5808102,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Invalidate"
},
{
"id": 6446795,
"markerTime": "2020-10-02T14:18:46.353Z",
"entityDefName": "kahua_Contract.Contract",
"entityId": 5808102,
"entityInstanceId": 5808104,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Update"
}
]
}
Markers are used across apps/entities, so this same marker can be used to detect changes in multiple different entities. Here's an issue you created after marker x:
GET /v1/domains/{{domain}}/projects/:projectId/apps/kahua_Issue/entitydefs/Issue/markers/from/6446787
{
"markers": [
{
"id": 6446798,
"markerTime": "2020-10-02T14:19:42.837Z",
"entityDefName": "kahua_Issue.Issue",
"entityId": 5808107,
"entityInstanceId": 5808107,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Add"
},
{
"id": 6446803,
"markerTime": "2020-10-02T14:19:45.443Z",
"entityDefName": "kahua_Issue.Issue",
"entityId": 5808107,
"entityInstanceId": 5808107,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Invalidate"
},
{
"id": 6446804,
"markerTime": "2020-10-02T14:19:59.73Z",
"entityDefName": "kahua_Issue.Issue",
"entityId": 5808107,
"entityInstanceId": 5808110,
"entityPartitionId": 0,
"domainPartitionId": 0,
"type": "Update"
}
]
}
To retrieve a list of project entity IDs for data modified on or after a certain date and time, you may use the marked project endpoint. This endpoint requires a since parameter and a list of the entity definitions to use to determine modified projects.
Markers are only guaranteed to be present for the last 30 days from the current date and time.
The since parameter should be in ISO 8601 format. ex: 2026-05-13T16:30:00.000Z
EntityDefs is a JSON array of fully qualified entity definition names, for example { ["kahua_AEC_RFI.RFI", "kahua_Issue.Issue", "kahua_FundingBudget.FundingBudget"] }.
Operation
GET
Endpoint
/v1/domains/{{domain}}/projects/:projectId/markers/markedprojects/?since={{since}}
Request Body
{
["kahua_AEC_RFI.RFI", "kahua_Issue.Issue", "kahua_FundingBudget.FundingBudget"]
}