Worklog REST APIs for Jira Cloud

Abstract

Worklog REST APIs to migrate Tempo data from Jira Server / Data Center to Jira Cloud

Note

The code examples provided below are for curl and you will need to adapt them to your preferred means of dealing with REST APIs. All information provided in curly brackets “{}” need to be replaced with the variables from your instance.

Worklogs

The https://api.tempo.io/core/3/worklogs endpoint should be used to get worklogs in bulk. It supports different parameters to filter on Jira projects (“project”) a list of Jira issues (“issue”) a date period (“from”,”to”). Alternatively you can use the “updatedFrom” parameter to get worklogs that have been added or amended since the last import/check. That means that the  “from” and ”to” parameters refer to the date of the worklog itself (worklog date) and the “updatedFrom” parameter refers to the date when the worklog was actually entered or amended (system timestamp). 

The response of this endpoint is paginated. You can set the amount of worklogs per page with the “limit” parameter but the maximum number is restricted to 1,000. When calling the next page of returned worklogs you need to add the “offset” parameter.

As an example, a call would look like this:

curl --location --request GET 'https://api.tempo.io/core/3/worklogs?offset=0&limit=100&project=MOBIS&project=TO&from=2020-01-01&to=2020-03-31' \
--header 'Authorization: Bearer {YourTempoAccessToken}'

Please note that the “updatedFrom” parameter does not work in conjunction with other parameters. This means that you should not use the “updatedFrom” with other parameters!

curl --location --request GET 'https://api.tempo.io/core/3/worklogs?updatedFrom=2019-06-30&offset=0&limit=100' \
--header 'Authorization: Bearer {YourTempoAccessToken}'

The response always consists of three parts:

  1. self”: this is a string to the endpoint url that has been called

  2. metadata”:  here you will see the total number of worklogs (“count”) if the “limit” parameter is greater than the amount of worklogs to be returned in the call. When the “limit” parameter is smaller than the amount of worklogs (in that case the “limit” parameter will be the same as “count”) you will get a “next” section that includes the url to be called for the next page of results (“offset” parameter is already been set).

  3. results”:  this will return all worklog objects. You will need to iterate through all the returned worklogs.

Deleted worklogs

To retrieve deleted worklogs you will need to call the https://api.tempo.io/audit/1/events/deleted/types/worklog endpoint. This endpoint only includes the basic information about the deleted worklogs (worklog IDs in Tempo and Jira and the deletion date). The pagination works in the same way as above.

A typical call would look like the following:

curl --location --request GET 'https://api.tempo.io/audit/1/events/deleted/types/worklog?updatedFrom=2019-06-30T00:00&offset=0&limit=100' \
--header 'Authorization: Bearer {YourTempoAccessToken}'

All our worklog endpoints are documented in our developer section but you will also need additional endpoints to check on deleted worklogs.

Worklog attributes

Worklog attributes need to be created manually through the UI. But you will need the IDs behind each attribute so you can update the Tempo worklogs with your worklog attributes.

All the worklog attributes are available from a REST API endpoint. You need to call the endpoint to get the key of the worklog attribute to update the worklog.

curl -X GET \
  https://api.tempo.io/core/3/work-attributes \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Bearer {TempoAuthorizationToken}' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Host: api.tempo.io'curl -X GET \

You will get a response similar to:

{
    "self": "https://api.tempo.io/core/3/work-attributes",
    "metadata": {
        "count": 3
    },
    "results": [
        {
            "self": "https://api.tempo.io/core/3/work-attributes/_Account_",
            "key": "_Account_",
            "name": "Account",
            "type": "ACCOUNT",
            "required": false
        },
        {
            "self": "https://api.tempo.io/core/3/work-attributes/_Overtime_",
            "key": "_Overtime_",
            "name": "Overtime",
            "type": "INPUT_FIELD",
            "required": false
        },
        {
            "self": "https://api.tempo.io/core/3/work-attributes/_Workcategory_",
            "key": "_Workcategory_",
            "name": "Work category",
            "type": "STATIC_LIST",
            "required": false,
            "values": [
                "External",
                "Internal"
            ]
        }
    ]
}

Updating worklogs

All worklogs need to be updated with the missing information from Tempo (worklog attributes and billed hours). 

Billed hours get by default the same value (time in seconds) as logged hours. In those cases where you have set different values for billed hours you will need to update the billed hours value in your Cloud instance accordingly.

Before you can update the Tempo worklogs you will need to get the Tempo worklog ID for each Jira worklog as the IDs do not match. The Tempo worklog table in Jira Cloud keeps both the Jira worklog ID (which is the original worklog ID from the Jira Server instance).

To retrieve the Tempo worklog ID call:

curl -X GET https://api.tempo.io/core/3/worklogs/jira/{worklogID} -H 'Authorization: Bearer {machine-to-machineAccessToken}'
  -H 'Content-Type: application/json'
  
-H 'Host: api.tempo.io' 

You will get the following response:

{
    "self": "https://api.tempo.io/core/3/worklogs/3920",
    "tempoWorklogId": 3920,
    "jiraWorklogId": 14020,
    "issue": {
        "self": "https://tempo-sales.atlassian.net/rest/api/2/issue/CTP-1",
        "key": "CTP-1",
        "id": 10991
    },
    "timeSpentSeconds": 3600,
    "billableSeconds": 3600,
    "startDate": "2019-11-27",
    "startTime": "16:11:15",
    "description": "asdf",
    "createdAt": "2019-11-27T16:11:23Z",
    "updatedAt": "2019-11-27T16:11:23Z",
    "author": {
        "self": "https://tempo-sales.atlassian.net/rest/api/2/user?accountId=557058:3322bc29-17c6-493f-b4f5-1945319acf06",
        "accountId": "557058:3322bc29-17c6-493f-b4f5-1945319acf06",
        "displayName": "Taylor"
    },
    "attributes": {
        "self": "https://api.tempo.io/core/3/worklogs/3920/work-attribute-values",
        "values": []
    }
}

Now that we have the Tempo worklog ID we can prepare the information that we need to update and finally call the REST API update command. The values that we need to update are the worklog attributes and the billed seconds.

We are going to use the https://api.tempo.io/core/3/worklogs/{tempoWorklogID}  endpoint as a PUT request. Replace the Tempo worklog ID with the “tempoWorklogId” received from the call above. 

The payload we send with the request should look similar to the example below. If you have the Tempo Account field specified as a worklog attribute you will need to specify the Account Key in the payload.

{
  "issueKey": "CTP-1",
  "timeSpentSeconds": 3600,
  "billableSeconds": 7200,
  "startDate": "2019-11-27",
  "startTime": "16:11:15",
  "authorAccountId": "557058:3322bc29-17c6-493f-b4f5-1945319acf06",
  "attributes":[
    {
      "key": "_Workcategory_",
      "value": "External"    },
    {
      "key": "_Overtime_",
      "value": "Nothing here"
    },
    {
      "key": "_Account_",
      "value": "Spring_support"
    }
      ]
}

You will need to do the update for each single worklog to populate the worklog attributes and the billed seconds (billed hours).

With cUrl:

curl -X PUT \
  https://api.tempo.io/core/3/worklogs/3920 \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Bearer {yourTempoAuthenticationToken}' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 441' \
  -H 'Content-Type: application/json' \
  -H 'Host: api.tempo.io' \
  -d '{
  "issueKey": "CTP-1",
  "timeSpentSeconds": 3600,
  "billableSeconds": 7200,
  "startDate": "2019-11-27",
  "startTime": "16:11:15",
  "authorAccountId": "557058:3322bc29-17c6-493f-b4f5-1945319acf06",
  "attributes":[
    {
      "key": "_Workcategory_",
      "value": "External"
    },
    {
      "key": "_Overtime_",
      "value": "Nothing here"
    },
    {
      "key": "_Account_",
      "value": "Spring_support"
    }
      ]
}'

If the update command is not successful you will receive an error message with a hint to the probable problem. You might also want to check the troubleshooting page when updates are not successful.

A successful update will return a response including all of the information in the worklog.

Worklog account information

Retrieving the account information can only be done for a single Tempo Account. In order to retrieve all Tempo Accounts you will need to loop through all your accounts.

curl --location --request GET 'https://api.tempo.io/core/3/worklogs/account/{TempoAccountKey}?from={periodStartdate}&to={periodEnddate}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {TempoAuthorisationToken}'

Warning

The endpoint only accepts the Account key (not Tempo account ID or the Tempo Account name).

Worklog approval information

Retrieving the approval information can only be done by checking the timesheet approval status for the user who has tracked the time for the worklog date. In order to retrieve all approved worklogs for a user you will need to call:

curl --location --request GET 'https://api.tempo.io/core/3/timesheet-approvals/user/{AtlassianAccountId}?from={periodStartdate}&to={periodEnddate}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {TempoAuthorisationToken}'

Warning

You must follow these steps for every single user whose approval status you need to check.

You can also do this on a team by team basis, like this:

curl --location --request GET 'https://api.tempo.io/core/3/timesheet-approvals/team/{TeamId}?from={periodStartdate}&to={periodEnddate}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {TempoAuthorisationToken}' 

The response will include the approval status for each team member. Each approval status object also includes a URI to retrieve all worklogs within the requested approval period. This enables you to programmatically retrieve all worklogs for the approval period in question.