Python Atlassian REST API Wrapper providing comprehensive access to Jira, Confluence, Bitbucket, and other Atlassian products
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive Jira REST API client providing access to all Jira functionality including issues, projects, users, workflows, and administration. Supports both Jira Cloud and Server/Data Center platforms with 353 public methods covering the complete Jira API surface.
class Jira(AtlassianRestAPI):
def __init__(self, url: str, username: str = None, password: str = None,
token: str = None, cloud: bool = None, api_version: str = "2",
**kwargs):
"""
Initialize Jira client.
Parameters:
- url (str): Base URL of Jira instance
- username (str, optional): Username for authentication
- password (str, optional): Password or API token
- token (str, optional): Bearer token for authentication
- cloud (bool, optional): True for Cloud, False for Server/DC
- api_version (str): API version, defaults to "2"
"""Core functionality for creating, reading, updating, and deleting Jira issues with comprehensive field and metadata support.
def get_issue(self, issue_id_or_key: T_id, fields: Optional[str] = None,
properties: Optional[str] = None, update_history: bool = True,
expand: Optional[str] = None) -> T_resp_json:
"""
Get issue details with optional field filtering.
Parameters:
- issue_id_or_key: Issue key (e.g., "PROJ-123") or numeric ID
- fields: Comma-separated field names or "*all"
- properties: Comma-separated property keys
- update_history: Include change history
- expand: Additional data to expand
Returns:
dict: Issue data with fields, transitions, changelog
"""
def issue(self, key: str, fields: str = "*all", expand: Optional[str] = None) -> T_resp_json:
"""
Simplified issue retrieval.
Parameters:
- key: Issue key (e.g., "PROJ-123")
- fields: Field specification or "*all"
- expand: Additional data to expand
Returns:
dict: Issue data
"""
def create_issue(self, fields: dict, update_history: bool = False,
update: Optional[dict] = None) -> T_resp_json:
"""
Create new issue.
Parameters:
- fields: Issue field data (project, summary, issuetype, etc.)
- update_history: Include creation in change history
- update: Additional update operations
Returns:
dict: Created issue with key and URL
"""
def create_issues(self, list_of_issues_data: List[dict]) -> T_resp_json:
"""
Bulk create multiple issues.
Parameters:
- list_of_issues_data: List of issue field dictionaries
Returns:
dict: Creation results with successes and errors
"""
def update_issue_field(self, key: str, fields: dict,
notify_users: bool = True) -> T_resp_json:
"""
Update issue fields.
Parameters:
- key: Issue key
- fields: Field updates to apply
- notify_users: Send notifications
Returns:
dict: Update confirmation
"""
def delete_issue(self, issue_id_or_key: T_id, delete_subtasks: bool = True) -> bool:
"""
Delete issue.
Parameters:
- issue_id_or_key: Issue identifier
- delete_subtasks: Also delete subtasks
Returns:
bool: True if deletion successful
"""
def issue_exists(self, issue_key: str) -> bool:
"""
Check if issue exists.
Parameters:
- issue_key: Issue key to check
Returns:
bool: True if issue exists
"""def get_issue_transitions(self, issue_key: str) -> T_resp_json:
"""
Get available transitions for issue.
Parameters:
- issue_key: Issue key
Returns:
dict: Available transitions with IDs and names
"""
def set_issue_status(self, issue_key: str, status_name: str,
fields: Optional[dict] = None,
update: Optional[dict] = None) -> T_resp_json:
"""
Transition issue to new status.
Parameters:
- issue_key: Issue key
- status_name: Target status name
- fields: Additional field updates
- update: Update operations to perform
Returns:
dict: Transition result
"""
def get_issue_status(self, issue_key: str) -> T_resp_json:
"""
Get current issue status.
Parameters:
- issue_key: Issue key
Returns:
dict: Status information
"""def jql(self, jql: str, fields: str = "*all", start: int = 0,
limit: Optional[int] = None, expand: Optional[str] = None,
validate_query: Optional[bool] = None) -> T_resp_json:
"""
Execute JQL query.
Parameters:
- jql: JQL query string
- fields: Fields to retrieve
- start: Starting index for pagination
- limit: Maximum results to return
- expand: Additional data to expand
- validate_query: Validate JQL syntax
Returns:
dict: Search results with issues array
"""
def enhanced_jql(self, jql: str, fields: str = "*all",
nextPageToken: Optional[str] = None,
limit: Optional[int] = None,
expand: Optional[str] = None) -> T_resp_json:
"""
Enhanced JQL with token-based pagination (Cloud only).
Parameters:
- jql: JQL query string
- fields: Fields to retrieve
- nextPageToken: Pagination token
- limit: Maximum results per page
- expand: Additional data to expand
Returns:
dict: Enhanced search results with nextPageToken
"""
def jql_get_list_of_tickets(self, jql: str, fields: str = "*all",
expand: Optional[str] = None) -> List[dict]:
"""
Get all issues matching JQL query.
Parameters:
- jql: JQL query string
- fields: Fields to retrieve
- expand: Additional data to expand
Returns:
List[dict]: All matching issues
"""def issue_get_comments(self, issue_id: T_id) -> T_resp_json:
"""
Get issue comments.
Parameters:
- issue_id: Issue key or ID
Returns:
dict: Comments data with pagination
"""
def issue_add_comment(self, issue_key: str, comment: str,
visibility: Optional[dict] = None) -> T_resp_json:
"""
Add comment to issue.
Parameters:
- issue_key: Issue key
- comment: Comment text (wiki markup or plain text)
- visibility: Visibility restrictions (role/group)
Returns:
dict: Created comment data
"""
def issue_add_worklog(self, key: str, started: str, time_sec: int,
comment: Optional[str] = None) -> T_resp_json:
"""
Add worklog to issue.
Parameters:
- key: Issue key
- started: Start date/time (ISO format)
- time_sec: Time spent in seconds
- comment: Optional worklog comment
Returns:
dict: Created worklog data
"""
def issue_get_worklog(self, issue_id_or_key: T_id) -> T_resp_json:
"""
Get issue worklogs.
Parameters:
- issue_id_or_key: Issue identifier
Returns:
dict: Worklog data with totals
"""def add_attachment(self, issue_key: str, filename: str) -> T_resp_json:
"""
Add attachment from file.
Parameters:
- issue_key: Issue key
- filename: Path to file to attach
Returns:
dict: Attachment metadata
"""
def get_attachment(self, attachment_id: str) -> T_resp_json:
"""
Get attachment metadata.
Parameters:
- attachment_id: Attachment ID
Returns:
dict: Attachment details (filename, size, author, etc.)
"""
def get_attachment_content(self, attachment_id: str) -> bytes:
"""
Download attachment content.
Parameters:
- attachment_id: Attachment ID
Returns:
bytes: File content
"""
def remove_attachment(self, attachment_id: str) -> bool:
"""
Delete attachment.
Parameters:
- attachment_id: Attachment ID
Returns:
bool: True if deletion successful
"""def user(self, username: Optional[str] = None, key: Optional[str] = None,
account_id: Optional[str] = None, expand: Optional[str] = None) -> T_resp_json:
"""
Get user details.
Parameters:
- username: Username (Server/DC)
- key: User key (Server/DC)
- account_id: Account ID (Cloud)
- expand: Additional data to expand
Returns:
dict: User information
"""
def myself(self) -> T_resp_json:
"""
Get current user information.
Returns:
dict: Current user details
"""
def user_find_by_user_string(self, username: Optional[str] = None,
query: Optional[str] = None,
account_id: Optional[str] = None,
start: int = 0, limit: int = 50) -> List[dict]:
"""
Search users.
Parameters:
- username: Exact username match
- query: Search query string
- account_id: Account ID to find
- start: Starting index
- limit: Maximum results
Returns:
List[dict]: Matching users
"""
def user_create(self, username: str, email: str, display_name: str,
password: Optional[str] = None,
notification: Optional[bool] = None) -> T_resp_json:
"""
Create user (Server/DC only).
Parameters:
- username: Unique username
- email: Email address
- display_name: Display name
- password: Initial password
- notification: Send notification email
Returns:
dict: Created user data
"""def projects(self, included_archived: Optional[bool] = None,
expand: Optional[str] = None) -> List[dict]:
"""
Get all projects.
Parameters:
- included_archived: Include archived projects
- expand: Additional data to expand
Returns:
List[dict]: Project list with metadata
"""
def get_project(self, key: str, expand: Optional[str] = None) -> T_resp_json:
"""
Get project details.
Parameters:
- key: Project key
- expand: Additional data to expand
Returns:
dict: Project information with components, versions, roles
"""
def get_project_components(self, key: str) -> List[dict]:
"""
Get project components.
Parameters:
- key: Project key
Returns:
List[dict]: Component list
"""
def get_project_versions(self, key: str,
expand: Optional[str] = None) -> List[dict]:
"""
Get project versions.
Parameters:
- key: Project key
- expand: Additional data to expand
Returns:
List[dict]: Version list
"""
def get_all_project_issues(self, project: str, fields: str = "*all",
start: int = 0, limit: Optional[int] = None) -> List[dict]:
"""
Get all issues in project.
Parameters:
- project: Project key
- fields: Fields to retrieve
- start: Starting index
- limit: Maximum results
Returns:
List[dict]: Project issues
"""def get_groups(self, query: Optional[str] = None,
exclude: Optional[str] = None, limit: int = 20) -> List[dict]:
"""
Search groups.
Parameters:
- query: Search query
- exclude: Groups to exclude
- limit: Maximum results
Returns:
List[dict]: Matching groups
"""
def create_group(self, name: str) -> T_resp_json:
"""
Create group.
Parameters:
- name: Group name
Returns:
dict: Created group data
"""
def add_user_to_group(self, username: Optional[str] = None,
group_name: Optional[str] = None,
account_id: Optional[str] = None) -> T_resp_json:
"""
Add user to group.
Parameters:
- username: Username (Server/DC)
- group_name: Group name
- account_id: Account ID (Cloud)
Returns:
dict: Operation result
"""
def get_all_users_from_group(self, group: str,
include_inactive_users: bool = False,
start: int = 0, limit: int = 50) -> List[dict]:
"""
Get group members.
Parameters:
- group: Group name
- include_inactive_users: Include inactive users
- start: Starting index
- limit: Maximum results
Returns:
List[dict]: Group member list
"""def create_filter(self, name: str, jql: str,
description: Optional[str] = None,
favourite: bool = False) -> T_resp_json:
"""
Create saved filter.
Parameters:
- name: Filter name
- jql: JQL query
- description: Filter description
- favourite: Mark as favourite
Returns:
dict: Created filter data
"""
def get_filter(self, filter_id: T_id) -> T_resp_json:
"""
Get filter details.
Parameters:
- filter_id: Filter ID
Returns:
dict: Filter information including JQL and sharing
"""
def update_filter(self, filter_id: T_id, jql: str, **kwargs) -> T_resp_json:
"""
Update filter.
Parameters:
- filter_id: Filter ID
- jql: New JQL query
- **kwargs: Additional properties (name, description, favourite)
Returns:
dict: Updated filter data
"""def get_all_agile_boards(self, board_name: Optional[str] = None,
project_key: Optional[str] = None,
board_type: Optional[str] = None,
start: int = 0, limit: int = 50) -> T_resp_json:
"""
Get agile boards.
Parameters:
- board_name: Filter by board name
- project_key: Filter by project
- board_type: Board type (scrum, kanban)
- start: Starting index
- limit: Maximum results
Returns:
dict: Board list with pagination
"""
def create_agile_board(self, name: str, type: str, filter_id: T_id,
location: Optional[dict] = None) -> T_resp_json:
"""
Create agile board.
Parameters:
- name: Board name
- type: Board type (scrum, kanban)
- filter_id: Saved filter ID for board query
- location: Board location configuration
Returns:
dict: Created board data
"""
def create_sprint(self, name: str, board_id: T_id,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
goal: Optional[str] = None) -> T_resp_json:
"""
Create sprint.
Parameters:
- name: Sprint name
- board_id: Board ID
- start_date: Start date (ISO format)
- end_date: End date (ISO format)
- goal: Sprint goal
Returns:
dict: Created sprint data
"""
def add_issues_to_sprint(self, sprint_id: T_id, issues: List[str]) -> T_resp_json:
"""
Add issues to sprint.
Parameters:
- sprint_id: Sprint ID
- issues: List of issue keys
Returns:
dict: Operation result
"""
def get_all_sprints_from_board(self, board_id: T_id) -> T_resp_json:
"""
Get all sprints from board.
Parameters:
- board_id: Board ID
Returns:
dict: Sprints list with status and dates
"""
def get_sprint_issues(self, sprint_id: T_id, start: int = 0,
limit: int = 50) -> T_resp_json:
"""
Get issues in sprint.
Parameters:
- sprint_id: Sprint ID
- start: Starting index
- limit: Maximum results
Returns:
dict: Sprint issues with status
"""
def move_issues_to_backlog(self, issue_keys: List[str]) -> T_resp_json:
"""
Move issues to backlog.
Parameters:
- issue_keys: List of issue keys to move
Returns:
dict: Operation result
"""
def get_epics(self, board_id: T_id, start: int = 0,
limit: int = 50) -> T_resp_json:
"""
Get epics from board.
Parameters:
- board_id: Board ID
- start: Starting index
- limit: Maximum results
Returns:
dict: Epics list
"""
def epic_issues(self, epic: str, fields: str = "*all",
expand: Optional[str] = None) -> T_resp_json:
"""
Get issues in epic.
Parameters:
- epic: Epic key
- fields: Fields to retrieve
- expand: Additional data to expand
Returns:
dict: Epic issues
"""Comprehensive Tempo time tracking, team management, and account administration for advanced project management and resource planning.
def tempo_timesheets_get_worklogs(self, from_date: str, to_date: str,
username: Optional[str] = None,
project_key: Optional[str] = None) -> T_resp_json:
"""
Get worklogs from Tempo.
Parameters:
- from_date: Start date (YYYY-MM-DD format)
- to_date: End date (YYYY-MM-DD format)
- username: Filter by username
- project_key: Filter by project
Returns:
dict: Worklog entries with time tracking data
"""
def tempo_timesheets_write_worklog(self, issue: str, time_sec: int,
start_date: str, username: str,
comment: Optional[str] = None) -> T_resp_json:
"""
Create Tempo worklog entry.
Parameters:
- issue: Issue key
- time_sec: Time spent in seconds
- start_date: Work date (YYYY-MM-DD format)
- username: Username for worklog
- comment: Optional comment
Returns:
dict: Created worklog data
"""
def tempo_teams_get_all_teams(self, expand: Optional[str] = None) -> T_resp_json:
"""
Get all Tempo teams.
Parameters:
- expand: Additional data to expand
Returns:
dict: Teams list with members and configuration
"""
def tempo_teams_add_member(self, team_id: T_id, member_key: str) -> T_resp_json:
"""
Add member to Tempo team.
Parameters:
- team_id: Team ID
- member_key: User key to add
Returns:
dict: Updated team membership
"""
def tempo_account_get_accounts(self, skip: int = 0, limit: int = 50) -> T_resp_json:
"""
Get Tempo accounts for billing/project tracking.
Parameters:
- skip: Number of results to skip
- limit: Maximum results to return
Returns:
dict: Accounts list with billing information
"""
def tempo_account_add_account(self, data: dict) -> T_resp_json:
"""
Create Tempo account.
Parameters:
- data: Account data (key, name, customer_id, etc.)
Returns:
dict: Created account data
"""
def tempo_holiday_get_schemes(self) -> T_resp_json:
"""
Get holiday schemes for time tracking.
Returns:
dict: Holiday schemes with dates and rules
"""
def tempo_timesheets_get_team_utilization(self, team_id: T_id,
from_date: str, to_date: str) -> T_resp_json:
"""
Get team utilization metrics.
Parameters:
- team_id: Team ID
- from_date: Start date
- to_date: End date
Returns:
dict: Team utilization statistics and capacity data
"""def get_server_info(self, do_health_check: bool = False) -> T_resp_json:
"""
Get server information.
Parameters:
- do_health_check: Include health check data
Returns:
dict: Server version, build info, health status
"""
def health_check(self) -> T_resp_json:
"""
Perform health check.
Returns:
dict: System health status
"""
def reindex(self, comments: bool = True, change_history: bool = True,
worklogs: bool = True,
indexing_type: str = "BACKGROUND_PREFERRED") -> T_resp_json:
"""
Reindex Jira.
Parameters:
- comments: Reindex comments
- change_history: Reindex change history
- worklogs: Reindex worklogs
- indexing_type: Indexing strategy
Returns:
dict: Reindex status
"""
def get_all_fields(self) -> List[dict]:
"""
Get all fields (system and custom).
Returns:
List[dict]: Field definitions with types and options
"""
def create_custom_field(self, name: str, type: str,
search_key: Optional[str] = None,
description: Optional[str] = None) -> T_resp_json:
"""
Create custom field.
Parameters:
- name: Field name
- type: Field type (text, number, select, etc.)
- search_key: Searcher key
- description: Field description
Returns:
dict: Created field data
"""from atlassian import Jira
jira = Jira(
url="https://your-domain.atlassian.net",
username="email@example.com",
password="api-token"
)
# Create issue
issue_data = {
"project": {"key": "PROJ"},
"summary": "New feature request",
"description": "Detailed description of the feature",
"issuetype": {"name": "Story"},
}
new_issue = jira.create_issue(fields=issue_data)
# Get issue
issue = jira.get_issue("PROJ-123", fields="summary,status,assignee")
# Update issue
jira.update_issue_field("PROJ-123", {
"summary": "Updated summary",
"description": "Updated description"
})
# Transition issue
jira.set_issue_status("PROJ-123", "In Progress")# JQL search
results = jira.jql("project = PROJ AND status = 'To Do'", limit=50)
issues = results["issues"]
# Get all issues (handles pagination)
all_issues = jira.jql_get_list_of_tickets(
"project = PROJ ORDER BY created DESC"
)
# Export to CSV
csv_content = jira.csv(
"project = PROJ AND status = Done",
limit=1000,
all_fields=True
)# User operations
user = jira.user(account_id="account-id-123")
users = jira.user_find_by_user_string(query="john@example.com")
# Project operations
projects = jira.projects()
project = jira.get_project("PROJ", expand="description,lead,components")
components = jira.get_project_components("PROJ")# Bulk operations
issues_to_create = [
{"project": {"key": "PROJ"}, "summary": "Task 1", "issuetype": {"name": "Task"}},
{"project": {"key": "PROJ"}, "summary": "Task 2", "issuetype": {"name": "Task"}},
]
bulk_result = jira.create_issues(issues_to_create)
# Agile operations
boards = jira.get_all_agile_boards(project_key="PROJ")
sprint = jira.create_sprint("Sprint 1", board_id=123)
jira.add_issues_to_sprint(sprint["id"], ["PROJ-1", "PROJ-2"])
# Filter management
filter_data = jira.create_filter(
"My Issues",
"assignee = currentUser() AND resolution = Unresolved"
)from atlassian.errors import ApiNotFoundError, ApiPermissionError
try:
issue = jira.get_issue("INVALID-123")
except ApiNotFoundError:
print("Issue not found")
except ApiPermissionError:
print("Permission denied")from atlassian.typehints import T_id, T_resp_json
from typing import List, Dict, Optional, Union
# Common parameter types
IssueKey = str
ProjectKey = str
JQLQuery = str
IssueFields = Dict[str, Any]
UserIdentifier = Union[str, dict] # username/account_id or user object
IssueUpdate = Dict[str, List[dict]] # Update operationsInstall with Tessl CLI
npx tessl i tessl/pypi-atlassian-python-api