or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

administration.mdasset-management.mdbitbucket.mdconfluence.mddevelopment-tools.mdindex.mdjira.mdservice-management.mdstatuspage.md

jira.mddocs/

0

# Jira API

1

2

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.

3

4

## Initialization

5

6

```python { .api }

7

class Jira(AtlassianRestAPI):

8

def __init__(self, url: str, username: str = None, password: str = None,

9

token: str = None, cloud: bool = None, api_version: str = "2",

10

**kwargs):

11

"""

12

Initialize Jira client.

13

14

Parameters:

15

- url (str): Base URL of Jira instance

16

- username (str, optional): Username for authentication

17

- password (str, optional): Password or API token

18

- token (str, optional): Bearer token for authentication

19

- cloud (bool, optional): True for Cloud, False for Server/DC

20

- api_version (str): API version, defaults to "2"

21

"""

22

```

23

24

## Capabilities

25

26

### Issue Management

27

28

Core functionality for creating, reading, updating, and deleting Jira issues with comprehensive field and metadata support.

29

30

```python { .api }

31

def get_issue(self, issue_id_or_key: T_id, fields: Optional[str] = None,

32

properties: Optional[str] = None, update_history: bool = True,

33

expand: Optional[str] = None) -> T_resp_json:

34

"""

35

Get issue details with optional field filtering.

36

37

Parameters:

38

- issue_id_or_key: Issue key (e.g., "PROJ-123") or numeric ID

39

- fields: Comma-separated field names or "*all"

40

- properties: Comma-separated property keys

41

- update_history: Include change history

42

- expand: Additional data to expand

43

44

Returns:

45

dict: Issue data with fields, transitions, changelog

46

"""

47

48

def issue(self, key: str, fields: str = "*all", expand: Optional[str] = None) -> T_resp_json:

49

"""

50

Simplified issue retrieval.

51

52

Parameters:

53

- key: Issue key (e.g., "PROJ-123")

54

- fields: Field specification or "*all"

55

- expand: Additional data to expand

56

57

Returns:

58

dict: Issue data

59

"""

60

61

def create_issue(self, fields: dict, update_history: bool = False,

62

update: Optional[dict] = None) -> T_resp_json:

63

"""

64

Create new issue.

65

66

Parameters:

67

- fields: Issue field data (project, summary, issuetype, etc.)

68

- update_history: Include creation in change history

69

- update: Additional update operations

70

71

Returns:

72

dict: Created issue with key and URL

73

"""

74

75

def create_issues(self, list_of_issues_data: List[dict]) -> T_resp_json:

76

"""

77

Bulk create multiple issues.

78

79

Parameters:

80

- list_of_issues_data: List of issue field dictionaries

81

82

Returns:

83

dict: Creation results with successes and errors

84

"""

85

86

def update_issue_field(self, key: str, fields: dict,

87

notify_users: bool = True) -> T_resp_json:

88

"""

89

Update issue fields.

90

91

Parameters:

92

- key: Issue key

93

- fields: Field updates to apply

94

- notify_users: Send notifications

95

96

Returns:

97

dict: Update confirmation

98

"""

99

100

def delete_issue(self, issue_id_or_key: T_id, delete_subtasks: bool = True) -> bool:

101

"""

102

Delete issue.

103

104

Parameters:

105

- issue_id_or_key: Issue identifier

106

- delete_subtasks: Also delete subtasks

107

108

Returns:

109

bool: True if deletion successful

110

"""

111

112

def issue_exists(self, issue_key: str) -> bool:

113

"""

114

Check if issue exists.

115

116

Parameters:

117

- issue_key: Issue key to check

118

119

Returns:

120

bool: True if issue exists

121

"""

122

```

123

124

### Issue Transitions and Status

125

126

```python { .api }

127

def get_issue_transitions(self, issue_key: str) -> T_resp_json:

128

"""

129

Get available transitions for issue.

130

131

Parameters:

132

- issue_key: Issue key

133

134

Returns:

135

dict: Available transitions with IDs and names

136

"""

137

138

def set_issue_status(self, issue_key: str, status_name: str,

139

fields: Optional[dict] = None,

140

update: Optional[dict] = None) -> T_resp_json:

141

"""

142

Transition issue to new status.

143

144

Parameters:

145

- issue_key: Issue key

146

- status_name: Target status name

147

- fields: Additional field updates

148

- update: Update operations to perform

149

150

Returns:

151

dict: Transition result

152

"""

153

154

def get_issue_status(self, issue_key: str) -> T_resp_json:

155

"""

156

Get current issue status.

157

158

Parameters:

159

- issue_key: Issue key

160

161

Returns:

162

dict: Status information

163

"""

164

```

165

166

### Issue Search and JQL

167

168

```python { .api }

169

def jql(self, jql: str, fields: str = "*all", start: int = 0,

170

limit: Optional[int] = None, expand: Optional[str] = None,

171

validate_query: Optional[bool] = None) -> T_resp_json:

172

"""

173

Execute JQL query.

174

175

Parameters:

176

- jql: JQL query string

177

- fields: Fields to retrieve

178

- start: Starting index for pagination

179

- limit: Maximum results to return

180

- expand: Additional data to expand

181

- validate_query: Validate JQL syntax

182

183

Returns:

184

dict: Search results with issues array

185

"""

186

187

def enhanced_jql(self, jql: str, fields: str = "*all",

188

nextPageToken: Optional[str] = None,

189

limit: Optional[int] = None,

190

expand: Optional[str] = None) -> T_resp_json:

191

"""

192

Enhanced JQL with token-based pagination (Cloud only).

193

194

Parameters:

195

- jql: JQL query string

196

- fields: Fields to retrieve

197

- nextPageToken: Pagination token

198

- limit: Maximum results per page

199

- expand: Additional data to expand

200

201

Returns:

202

dict: Enhanced search results with nextPageToken

203

"""

204

205

def jql_get_list_of_tickets(self, jql: str, fields: str = "*all",

206

expand: Optional[str] = None) -> List[dict]:

207

"""

208

Get all issues matching JQL query.

209

210

Parameters:

211

- jql: JQL query string

212

- fields: Fields to retrieve

213

- expand: Additional data to expand

214

215

Returns:

216

List[dict]: All matching issues

217

"""

218

```

219

220

### Comments and Worklogs

221

222

```python { .api }

223

def issue_get_comments(self, issue_id: T_id) -> T_resp_json:

224

"""

225

Get issue comments.

226

227

Parameters:

228

- issue_id: Issue key or ID

229

230

Returns:

231

dict: Comments data with pagination

232

"""

233

234

def issue_add_comment(self, issue_key: str, comment: str,

235

visibility: Optional[dict] = None) -> T_resp_json:

236

"""

237

Add comment to issue.

238

239

Parameters:

240

- issue_key: Issue key

241

- comment: Comment text (wiki markup or plain text)

242

- visibility: Visibility restrictions (role/group)

243

244

Returns:

245

dict: Created comment data

246

"""

247

248

def issue_add_worklog(self, key: str, started: str, time_sec: int,

249

comment: Optional[str] = None) -> T_resp_json:

250

"""

251

Add worklog to issue.

252

253

Parameters:

254

- key: Issue key

255

- started: Start date/time (ISO format)

256

- time_sec: Time spent in seconds

257

- comment: Optional worklog comment

258

259

Returns:

260

dict: Created worklog data

261

"""

262

263

def issue_get_worklog(self, issue_id_or_key: T_id) -> T_resp_json:

264

"""

265

Get issue worklogs.

266

267

Parameters:

268

- issue_id_or_key: Issue identifier

269

270

Returns:

271

dict: Worklog data with totals

272

"""

273

```

274

275

### Attachments

276

277

```python { .api }

278

def add_attachment(self, issue_key: str, filename: str) -> T_resp_json:

279

"""

280

Add attachment from file.

281

282

Parameters:

283

- issue_key: Issue key

284

- filename: Path to file to attach

285

286

Returns:

287

dict: Attachment metadata

288

"""

289

290

def get_attachment(self, attachment_id: str) -> T_resp_json:

291

"""

292

Get attachment metadata.

293

294

Parameters:

295

- attachment_id: Attachment ID

296

297

Returns:

298

dict: Attachment details (filename, size, author, etc.)

299

"""

300

301

def get_attachment_content(self, attachment_id: str) -> bytes:

302

"""

303

Download attachment content.

304

305

Parameters:

306

- attachment_id: Attachment ID

307

308

Returns:

309

bytes: File content

310

"""

311

312

def remove_attachment(self, attachment_id: str) -> bool:

313

"""

314

Delete attachment.

315

316

Parameters:

317

- attachment_id: Attachment ID

318

319

Returns:

320

bool: True if deletion successful

321

"""

322

```

323

324

### User Management

325

326

```python { .api }

327

def user(self, username: Optional[str] = None, key: Optional[str] = None,

328

account_id: Optional[str] = None, expand: Optional[str] = None) -> T_resp_json:

329

"""

330

Get user details.

331

332

Parameters:

333

- username: Username (Server/DC)

334

- key: User key (Server/DC)

335

- account_id: Account ID (Cloud)

336

- expand: Additional data to expand

337

338

Returns:

339

dict: User information

340

"""

341

342

def myself(self) -> T_resp_json:

343

"""

344

Get current user information.

345

346

Returns:

347

dict: Current user details

348

"""

349

350

def user_find_by_user_string(self, username: Optional[str] = None,

351

query: Optional[str] = None,

352

account_id: Optional[str] = None,

353

start: int = 0, limit: int = 50) -> List[dict]:

354

"""

355

Search users.

356

357

Parameters:

358

- username: Exact username match

359

- query: Search query string

360

- account_id: Account ID to find

361

- start: Starting index

362

- limit: Maximum results

363

364

Returns:

365

List[dict]: Matching users

366

"""

367

368

def user_create(self, username: str, email: str, display_name: str,

369

password: Optional[str] = None,

370

notification: Optional[bool] = None) -> T_resp_json:

371

"""

372

Create user (Server/DC only).

373

374

Parameters:

375

- username: Unique username

376

- email: Email address

377

- display_name: Display name

378

- password: Initial password

379

- notification: Send notification email

380

381

Returns:

382

dict: Created user data

383

"""

384

```

385

386

### Project Management

387

388

```python { .api }

389

def projects(self, included_archived: Optional[bool] = None,

390

expand: Optional[str] = None) -> List[dict]:

391

"""

392

Get all projects.

393

394

Parameters:

395

- included_archived: Include archived projects

396

- expand: Additional data to expand

397

398

Returns:

399

List[dict]: Project list with metadata

400

"""

401

402

def get_project(self, key: str, expand: Optional[str] = None) -> T_resp_json:

403

"""

404

Get project details.

405

406

Parameters:

407

- key: Project key

408

- expand: Additional data to expand

409

410

Returns:

411

dict: Project information with components, versions, roles

412

"""

413

414

def get_project_components(self, key: str) -> List[dict]:

415

"""

416

Get project components.

417

418

Parameters:

419

- key: Project key

420

421

Returns:

422

List[dict]: Component list

423

"""

424

425

def get_project_versions(self, key: str,

426

expand: Optional[str] = None) -> List[dict]:

427

"""

428

Get project versions.

429

430

Parameters:

431

- key: Project key

432

- expand: Additional data to expand

433

434

Returns:

435

List[dict]: Version list

436

"""

437

438

def get_all_project_issues(self, project: str, fields: str = "*all",

439

start: int = 0, limit: Optional[int] = None) -> List[dict]:

440

"""

441

Get all issues in project.

442

443

Parameters:

444

- project: Project key

445

- fields: Fields to retrieve

446

- start: Starting index

447

- limit: Maximum results

448

449

Returns:

450

List[dict]: Project issues

451

"""

452

```

453

454

### Group Management

455

456

```python { .api }

457

def get_groups(self, query: Optional[str] = None,

458

exclude: Optional[str] = None, limit: int = 20) -> List[dict]:

459

"""

460

Search groups.

461

462

Parameters:

463

- query: Search query

464

- exclude: Groups to exclude

465

- limit: Maximum results

466

467

Returns:

468

List[dict]: Matching groups

469

"""

470

471

def create_group(self, name: str) -> T_resp_json:

472

"""

473

Create group.

474

475

Parameters:

476

- name: Group name

477

478

Returns:

479

dict: Created group data

480

"""

481

482

def add_user_to_group(self, username: Optional[str] = None,

483

group_name: Optional[str] = None,

484

account_id: Optional[str] = None) -> T_resp_json:

485

"""

486

Add user to group.

487

488

Parameters:

489

- username: Username (Server/DC)

490

- group_name: Group name

491

- account_id: Account ID (Cloud)

492

493

Returns:

494

dict: Operation result

495

"""

496

497

def get_all_users_from_group(self, group: str,

498

include_inactive_users: bool = False,

499

start: int = 0, limit: int = 50) -> List[dict]:

500

"""

501

Get group members.

502

503

Parameters:

504

- group: Group name

505

- include_inactive_users: Include inactive users

506

- start: Starting index

507

- limit: Maximum results

508

509

Returns:

510

List[dict]: Group member list

511

"""

512

```

513

514

### Filter Management

515

516

```python { .api }

517

def create_filter(self, name: str, jql: str,

518

description: Optional[str] = None,

519

favourite: bool = False) -> T_resp_json:

520

"""

521

Create saved filter.

522

523

Parameters:

524

- name: Filter name

525

- jql: JQL query

526

- description: Filter description

527

- favourite: Mark as favourite

528

529

Returns:

530

dict: Created filter data

531

"""

532

533

def get_filter(self, filter_id: T_id) -> T_resp_json:

534

"""

535

Get filter details.

536

537

Parameters:

538

- filter_id: Filter ID

539

540

Returns:

541

dict: Filter information including JQL and sharing

542

"""

543

544

def update_filter(self, filter_id: T_id, jql: str, **kwargs) -> T_resp_json:

545

"""

546

Update filter.

547

548

Parameters:

549

- filter_id: Filter ID

550

- jql: New JQL query

551

- **kwargs: Additional properties (name, description, favourite)

552

553

Returns:

554

dict: Updated filter data

555

"""

556

```

557

558

### Agile and Boards

559

560

```python { .api }

561

def get_all_agile_boards(self, board_name: Optional[str] = None,

562

project_key: Optional[str] = None,

563

board_type: Optional[str] = None,

564

start: int = 0, limit: int = 50) -> T_resp_json:

565

"""

566

Get agile boards.

567

568

Parameters:

569

- board_name: Filter by board name

570

- project_key: Filter by project

571

- board_type: Board type (scrum, kanban)

572

- start: Starting index

573

- limit: Maximum results

574

575

Returns:

576

dict: Board list with pagination

577

"""

578

579

def create_agile_board(self, name: str, type: str, filter_id: T_id,

580

location: Optional[dict] = None) -> T_resp_json:

581

"""

582

Create agile board.

583

584

Parameters:

585

- name: Board name

586

- type: Board type (scrum, kanban)

587

- filter_id: Saved filter ID for board query

588

- location: Board location configuration

589

590

Returns:

591

dict: Created board data

592

"""

593

594

def create_sprint(self, name: str, board_id: T_id,

595

start_date: Optional[str] = None,

596

end_date: Optional[str] = None,

597

goal: Optional[str] = None) -> T_resp_json:

598

"""

599

Create sprint.

600

601

Parameters:

602

- name: Sprint name

603

- board_id: Board ID

604

- start_date: Start date (ISO format)

605

- end_date: End date (ISO format)

606

- goal: Sprint goal

607

608

Returns:

609

dict: Created sprint data

610

"""

611

612

def add_issues_to_sprint(self, sprint_id: T_id, issues: List[str]) -> T_resp_json:

613

"""

614

Add issues to sprint.

615

616

Parameters:

617

- sprint_id: Sprint ID

618

- issues: List of issue keys

619

620

Returns:

621

dict: Operation result

622

"""

623

624

def get_all_sprints_from_board(self, board_id: T_id) -> T_resp_json:

625

"""

626

Get all sprints from board.

627

628

Parameters:

629

- board_id: Board ID

630

631

Returns:

632

dict: Sprints list with status and dates

633

"""

634

635

def get_sprint_issues(self, sprint_id: T_id, start: int = 0,

636

limit: int = 50) -> T_resp_json:

637

"""

638

Get issues in sprint.

639

640

Parameters:

641

- sprint_id: Sprint ID

642

- start: Starting index

643

- limit: Maximum results

644

645

Returns:

646

dict: Sprint issues with status

647

"""

648

649

def move_issues_to_backlog(self, issue_keys: List[str]) -> T_resp_json:

650

"""

651

Move issues to backlog.

652

653

Parameters:

654

- issue_keys: List of issue keys to move

655

656

Returns:

657

dict: Operation result

658

"""

659

660

def get_epics(self, board_id: T_id, start: int = 0,

661

limit: int = 50) -> T_resp_json:

662

"""

663

Get epics from board.

664

665

Parameters:

666

- board_id: Board ID

667

- start: Starting index

668

- limit: Maximum results

669

670

Returns:

671

dict: Epics list

672

"""

673

674

def epic_issues(self, epic: str, fields: str = "*all",

675

expand: Optional[str] = None) -> T_resp_json:

676

"""

677

Get issues in epic.

678

679

Parameters:

680

- epic: Epic key

681

- fields: Fields to retrieve

682

- expand: Additional data to expand

683

684

Returns:

685

dict: Epic issues

686

"""

687

```

688

689

### Tempo Integration

690

691

Comprehensive Tempo time tracking, team management, and account administration for advanced project management and resource planning.

692

693

```python { .api }

694

def tempo_timesheets_get_worklogs(self, from_date: str, to_date: str,

695

username: Optional[str] = None,

696

project_key: Optional[str] = None) -> T_resp_json:

697

"""

698

Get worklogs from Tempo.

699

700

Parameters:

701

- from_date: Start date (YYYY-MM-DD format)

702

- to_date: End date (YYYY-MM-DD format)

703

- username: Filter by username

704

- project_key: Filter by project

705

706

Returns:

707

dict: Worklog entries with time tracking data

708

"""

709

710

def tempo_timesheets_write_worklog(self, issue: str, time_sec: int,

711

start_date: str, username: str,

712

comment: Optional[str] = None) -> T_resp_json:

713

"""

714

Create Tempo worklog entry.

715

716

Parameters:

717

- issue: Issue key

718

- time_sec: Time spent in seconds

719

- start_date: Work date (YYYY-MM-DD format)

720

- username: Username for worklog

721

- comment: Optional comment

722

723

Returns:

724

dict: Created worklog data

725

"""

726

727

def tempo_teams_get_all_teams(self, expand: Optional[str] = None) -> T_resp_json:

728

"""

729

Get all Tempo teams.

730

731

Parameters:

732

- expand: Additional data to expand

733

734

Returns:

735

dict: Teams list with members and configuration

736

"""

737

738

def tempo_teams_add_member(self, team_id: T_id, member_key: str) -> T_resp_json:

739

"""

740

Add member to Tempo team.

741

742

Parameters:

743

- team_id: Team ID

744

- member_key: User key to add

745

746

Returns:

747

dict: Updated team membership

748

"""

749

750

def tempo_account_get_accounts(self, skip: int = 0, limit: int = 50) -> T_resp_json:

751

"""

752

Get Tempo accounts for billing/project tracking.

753

754

Parameters:

755

- skip: Number of results to skip

756

- limit: Maximum results to return

757

758

Returns:

759

dict: Accounts list with billing information

760

"""

761

762

def tempo_account_add_account(self, data: dict) -> T_resp_json:

763

"""

764

Create Tempo account.

765

766

Parameters:

767

- data: Account data (key, name, customer_id, etc.)

768

769

Returns:

770

dict: Created account data

771

"""

772

773

def tempo_holiday_get_schemes(self) -> T_resp_json:

774

"""

775

Get holiday schemes for time tracking.

776

777

Returns:

778

dict: Holiday schemes with dates and rules

779

"""

780

781

def tempo_timesheets_get_team_utilization(self, team_id: T_id,

782

from_date: str, to_date: str) -> T_resp_json:

783

"""

784

Get team utilization metrics.

785

786

Parameters:

787

- team_id: Team ID

788

- from_date: Start date

789

- to_date: End date

790

791

Returns:

792

dict: Team utilization statistics and capacity data

793

"""

794

```

795

796

### Administration

797

798

```python { .api }

799

def get_server_info(self, do_health_check: bool = False) -> T_resp_json:

800

"""

801

Get server information.

802

803

Parameters:

804

- do_health_check: Include health check data

805

806

Returns:

807

dict: Server version, build info, health status

808

"""

809

810

def health_check(self) -> T_resp_json:

811

"""

812

Perform health check.

813

814

Returns:

815

dict: System health status

816

"""

817

818

def reindex(self, comments: bool = True, change_history: bool = True,

819

worklogs: bool = True,

820

indexing_type: str = "BACKGROUND_PREFERRED") -> T_resp_json:

821

"""

822

Reindex Jira.

823

824

Parameters:

825

- comments: Reindex comments

826

- change_history: Reindex change history

827

- worklogs: Reindex worklogs

828

- indexing_type: Indexing strategy

829

830

Returns:

831

dict: Reindex status

832

"""

833

834

def get_all_fields(self) -> List[dict]:

835

"""

836

Get all fields (system and custom).

837

838

Returns:

839

List[dict]: Field definitions with types and options

840

"""

841

842

def create_custom_field(self, name: str, type: str,

843

search_key: Optional[str] = None,

844

description: Optional[str] = None) -> T_resp_json:

845

"""

846

Create custom field.

847

848

Parameters:

849

- name: Field name

850

- type: Field type (text, number, select, etc.)

851

- search_key: Searcher key

852

- description: Field description

853

854

Returns:

855

dict: Created field data

856

"""

857

```

858

859

## Usage Examples

860

861

### Basic Issue Operations

862

863

```python

864

from atlassian import Jira

865

866

jira = Jira(

867

url="https://your-domain.atlassian.net",

868

username="email@example.com",

869

password="api-token"

870

)

871

872

# Create issue

873

issue_data = {

874

"project": {"key": "PROJ"},

875

"summary": "New feature request",

876

"description": "Detailed description of the feature",

877

"issuetype": {"name": "Story"},

878

}

879

new_issue = jira.create_issue(fields=issue_data)

880

881

# Get issue

882

issue = jira.get_issue("PROJ-123", fields="summary,status,assignee")

883

884

# Update issue

885

jira.update_issue_field("PROJ-123", {

886

"summary": "Updated summary",

887

"description": "Updated description"

888

})

889

890

# Transition issue

891

jira.set_issue_status("PROJ-123", "In Progress")

892

```

893

894

### Search and Export

895

896

```python

897

# JQL search

898

results = jira.jql("project = PROJ AND status = 'To Do'", limit=50)

899

issues = results["issues"]

900

901

# Get all issues (handles pagination)

902

all_issues = jira.jql_get_list_of_tickets(

903

"project = PROJ ORDER BY created DESC"

904

)

905

906

# Export to CSV

907

csv_content = jira.csv(

908

"project = PROJ AND status = Done",

909

limit=1000,

910

all_fields=True

911

)

912

```

913

914

### User and Project Management

915

916

```python

917

# User operations

918

user = jira.user(account_id="account-id-123")

919

users = jira.user_find_by_user_string(query="john@example.com")

920

921

# Project operations

922

projects = jira.projects()

923

project = jira.get_project("PROJ", expand="description,lead,components")

924

components = jira.get_project_components("PROJ")

925

```

926

927

### Advanced Features

928

929

```python

930

# Bulk operations

931

issues_to_create = [

932

{"project": {"key": "PROJ"}, "summary": "Task 1", "issuetype": {"name": "Task"}},

933

{"project": {"key": "PROJ"}, "summary": "Task 2", "issuetype": {"name": "Task"}},

934

]

935

bulk_result = jira.create_issues(issues_to_create)

936

937

# Agile operations

938

boards = jira.get_all_agile_boards(project_key="PROJ")

939

sprint = jira.create_sprint("Sprint 1", board_id=123)

940

jira.add_issues_to_sprint(sprint["id"], ["PROJ-1", "PROJ-2"])

941

942

# Filter management

943

filter_data = jira.create_filter(

944

"My Issues",

945

"assignee = currentUser() AND resolution = Unresolved"

946

)

947

```

948

949

## Error Handling

950

951

```python

952

from atlassian.errors import ApiNotFoundError, ApiPermissionError

953

954

try:

955

issue = jira.get_issue("INVALID-123")

956

except ApiNotFoundError:

957

print("Issue not found")

958

except ApiPermissionError:

959

print("Permission denied")

960

```

961

962

## Types

963

964

```python { .api }

965

from atlassian.typehints import T_id, T_resp_json

966

from typing import List, Dict, Optional, Union

967

968

# Common parameter types

969

IssueKey = str

970

ProjectKey = str

971

JQLQuery = str

972

IssueFields = Dict[str, Any]

973

UserIdentifier = Union[str, dict] # username/account_id or user object

974

IssueUpdate = Dict[str, List[dict]] # Update operations

975

```