Runbook: Bulk Delete Worklogs

Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.

Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Goal

This page aims to share script to Bulk delete worklogs that are no longer necessary on your Jira Cloud instance.

Documentation

Get Issue Worklogs API

Bulk Delete Issue Worklogs API

Get Data

Fetch the worklog IDs you plan to delete using Get Issue Worklogs API

  • use startedAfter and startedBefore parameters to narrow the timeframe (timestamps in milliseconds)

Example script in Python 3

1 2 3 4 5 6 7 8 9 def get_worklog_ids(issue_key, after=None, before=None): url = f"{SITENAME}/rest/api/3/issue/{issue_key}/worklog?" \ f"maxResults=5000&" \ f"startedAfter={get_timestamp_in_milliseconds(after)}&" \ f"startedBefore={get_timestamp_in_milliseconds(before)}" response = requests.get(url, auth=(USER, PWD), timeout=30) return [worklog['id'] for worklog in response.json()['worklogs']]

Get Data by author

To delete worklogs authored by a specific user, custom filtering of results must be done, as the Get Issue Worklogs APIdoes not accept a user parameter.

Example script in Python 3 (by email address)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 def get_worklog_ids_by_emails(issue_key, emails, after=None, before=None):     url = f"{SITENAME}/rest/api/3/issue/{issue_key}/worklog?" \           f"maxResults=5000&" \           f"startedAfter={get_timestamp_in_milliseconds(after)}&" \           f"startedBefore={get_timestamp_in_milliseconds(before)}"     response = requests.get(url,                             auth=(USER, PWD),                             timeout=30)     worklog_ids = []     for worklog in response.json()['worklogs']:         if 'emailAddress' in worklog['author'] and worklog['author']['emailAddress'] in emails:             worklog_ids.append(worklog['id'])     return worklog_ids

Delete Data

Delete the worklogs by calling Bulk Delete Issue Worklogs API with IDs received from the previous call

You can specify either auto or leave option for the adjustEstimateAPI parameter

  • leave Leaves the estimate unchanged.

  • auto Reduces the estimate by the value of timeSpent in the worklogs.

Example script in Python 3

1 2 3 4 5 def bulk_remove_worklogs(issue_key, worklog_ids, adjust_estimate="auto"): url = f"{SITENAME}/rest/api/3/issue/{issue_key}/worklog?adjustEstimate={adjust_estimate}" body = {"ids": worklog_ids} response = requests.delete(url, json=body, auth=(USER, PWD), timeout=30) return response.status_code, response.text

Full script

The script will delete all worklogs on issue ISSUE_KEY started after STARTED_AFTER and before STARTED_BEFORE

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import json from datetime import datetime import requests USER = 'admin@yahoo.com' PWD = 'prod_token' SITENAME = "the instance address" ISSUE_KEY = 'TEST-1' # Adjust if you'd prefer to use a different format DATE_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S%z' # Can be set to None STARTED_AFTER = '2023-01-01T11:00:00+1100' STARTED_BEFORE = '2024-01-01T11:00:00+1100' def get_worklog_ids(issue_key, after=None, before=None): url = f"{SITENAME}/rest/api/3/issue/{issue_key}/worklog?" \ f"maxResults=5000&" \ f"startedAfter={get_timestamp_in_milliseconds(after)}&" \ f"startedBefore={get_timestamp_in_milliseconds(before)}" response = requests.get(url, auth=(USER, PWD), timeout=30) return [worklog['id'] for worklog in response.json()['worklogs']] def get_worklog_ids_by_emails(issue_key, emails, after=None, before=None): url = f"{SITENAME}/rest/api/3/issue/{issue_key}/worklog?" \ f"maxResults=5000&" \ f"startedAfter={get_timestamp_in_milliseconds(after)}&" \ f"startedBefore={get_timestamp_in_milliseconds(before)}" response = requests.get(url, auth=(USER, PWD), timeout=30) worklog_ids = [] for worklog in response.json()['worklogs']: if 'emailAddress' in worklog['author'] and worklog['author']['emailAddress'] in emails: worklog_ids.append(worklog['id']) return worklog_ids def get_timestamp_in_milliseconds(date): if not date: return '' return 1000 * int(datetime.strptime(date, DATE_TIME_FORMAT).timestamp()) def bulk_remove_worklogs(issue_key, worklog_ids, adjust_estimate="auto"): url = f"{SITENAME}/rest/api/3/issue/{issue_key}/worklog?adjustEstimate={adjust_estimate}" body = {"ids": worklog_ids} response = requests.delete(url, json=body, auth=(USER, PWD), timeout=30) return response.status_code, response.text while True: worklog_ids = get_worklog_ids(ISSUE_KEY, STARTED_AFTER, STARTED_BEFORE) if len(worklog_ids) == 0: print("No more worklogs to delete") break status, body = bulk_remove_worklogs(ISSUE_KEY, worklog_ids) if status == 200: print(f"Successfully deleted *some* worklogs, response \n\"{body}\"") elif status == 204: print(f"Successfully deleted {len(worklog_ids)} worklogs on issue {ISSUE_ID}") else: print(f"Received different status than HTTP 200/204 from the Bulk Delete endpoint, status {status}, response body \n\"{body}\"") break

FAQ

Q. How many worklogs, at max, can be deleted at a time?

A. The limit, as described in the API docs, is 5000 worklogs.

Q. What are the various criteria that can be used to identify the worklogs to delete?

A. The Bulk Delete API can only accept worklog IDs. Those IDs must be fetched using one of the available APIs, e.g. the Get Issue Worklogs API

Q. What is the maximum time range to get worklog IDs?

A. The Get Issue Worklogs API does not limit the time range, as long as the timestamps are valid.

Q. Are worklogs deleted from a single issue at a time?

A. The worklog must be from a single issue, specified in the {issueIDOrKey} API parameter.

Q. What if I delete worklogs by mistake? Can i restore them back?

A. The worklogs cannot be restored so the delete operations must be performed cautiously.

Q. Does the Bulk Delete API update issue change history?

A. Yes, issue change history will be updated.

Updated on April 8, 2025

Still need help?

The Atlassian Community is here for you.