Skip to content
jira-api logo

Jira REST API v3 Documentation

jira-api

Provides Comprehensive reference for Atlassian Jira REST API v3 documentation and best practices. Use when asking about Jira API endpoints, authentication, request/response formats, JQL queries, Atlassian Document Format (ADF), webhooks, error handling, rate limiting, and API usage patterns. Trig...

SKILL.md

Full skill instructions

Jira REST API v3 Documentation

Purpose

This skill provides authoritative guidance on using the Atlassian Jira REST API v3, including endpoint references, authentication methods, request/​response formats, query languages, and best practices for programmatic Jira automation and integration.

Quick Start

To get started with the Jira API:

  1. Authenticate: Use Basic Auth with API token (email:token in base64)
  2. Make a request: GET /​rest/​api/​3/​issue/​{issueIdOrKey}
  3. Parse response: Standard JSON with issue details, changelog, and custom fields

For the project's JiraClient class:

from jira_tool.client import JiraClient

client = JiraClient()
issue = client.get_issue("PROJ-123")

Instructions

Step 1: Understanding Jira REST API v3 Basics

The Jira REST API v3 is the current standard API for Jira Cloud. Key characteristics:

  • Base URL: https://{jira-instance}.atlassian.net/​rest/​api/​3/
  • Authentication: Basic Auth with API tokens (not passwords)
  • Data Format: JSON for requests and responses
  • Versioning: v3 is the latest; v2 is deprecated

Official Documentation: https://developer.atlassian.com/cloud/jira/platform/rest/v3/

Step 2: Authentication Methods

Basic Auth with API Token (Recommended)

This is what the project uses. Steps:

  1. Generate API token in Jira user settings (atlassian account)
  2. Create header: Authorization: Basic {base64(email:token)}
  3. Add Accept: application/​json and Content-Type: application/​json headers
from base64 import b64encode

email = "[email protected]"
api_token = "your-api-token"
credentials = f"{email}:{api_token}"
auth_header = b64encode(credentials.encode()).decode()
headers = {
    "Authorization": f"Basic {auth_header}",
    "Accept": "application/​json",
    "Content-Type": "application/​json",
}

The JiraClient class handles this automatically:

client = JiraClient(
    base_url="https://company.atlassian.net",
    username="[email protected]",
    api_token="token-from-atlassian"
)
OAuth 2.0

For third-party applications:

  • Requires OAuth app registration
  • More complex but better for user-facing integrations
  • See references/​reference.md for OAuth flow details

Step 3: Core API Endpoints

Common endpoints you'll use frequently:

Issue Operations

  • GET /​rest/​api/​3/​issue/​{issueIdOrKey} - Get issue details
  • POST /​rest/​api/​3/​issues - Create issue
  • PUT /​rest/​api/​3/​issue/​{issueIdOrKey} - Update issue
  • DELETE /​rest/​api/​3/​issue/​{issueIdOrKey} - Delete issue
  • POST /​rest/​api/​3/​issue/​{issueIdOrKey}/​comment - Add comment

Searching & Filtering

  • GET /​rest/​api/​3/​search - Search issues with JQL
  • POST /​rest/​api/​3/​issues/​search - Search (alternative POST method)

Projects

  • GET /​rest/​api/​3/​project - List projects
  • GET /​rest/​api/​3/​project/​{projectIdOrKey} - Get project details

Users

  • GET /​rest/​api/​3/​users/​search - Search users
  • GET /​rest/​api/​3/​user?accountId={id} - Get user details
  • GET /​rest/​api/​3/​myself - Get current user

Workflows & Transitions

  • GET /​rest/​api/​3/​issue/​{issueIdOrKey}/​transitions - Get available transitions
  • POST /​rest/​api/​3/​issue/​{issueIdOrKey}/​transitions - Transition issue

Custom Fields

  • GET /​rest/​api/​3/​field - List all fields (including custom)
  • GET /​rest/​api/​3/​field/​search - Search for fields

Webhooks

  • GET /​rest/​api/​3/​webhook - List webhooks
  • POST /​rest/​api/​3/​webhook - Create webhook
  • DELETE /​rest/​api/​3/​webhook/​{id} - Delete webhook

Step 4: Request Formats and Parameters

Search with JQL (JQL Query Language)

Most powerful way to query issues:

GET /​rest/​api/​3/​search?jql=project=PROJ AND status="In Progress"&maxResults=50

JQL Examples:

# Recent issues
project = PROJ AND created >= -7d

# Assigned to me
assignee = currentUser()

# Status workflow
status in (Open, "In Progress") AND updated >= -1d

# Custom fields (need field ID)
customfield_10014 = "Epic Name"

# Text search
summary ~ "bug fix" OR description ~ "critical"

# Complex filtering
(project = PROJ OR project = OTHER)
  AND status != Done
  AND priority >= High
  AND created >= 2024-01-01

JQL Functions:

  • currentUser() - Current authenticated user
  • endOfDay(), startOfDay() - Date functions
  • now() - Current timestamp
  • issueFunction() - Advanced scripting
Query Parameters

Common parameters for /​search:

  • jql - JQL query string
  • startAt - Pagination start (default 0)
  • maxResults - Items per page (default 50, max 100)
  • fields - Comma-separated field names to return
  • expand - Additional data to include (changelog, transitions)
  • orderBy - Sort order (e.g., "created DESC")
# Using JiraClient
issues = client.search_issues(
    jql="project = PROJ AND status = Open",
    startAt=0,
    maxResults=100,
    expand=["changelog"]
)
Create Issue Request

Request body for POST /​rest/​api/​3/​issues:

{
  "fields": {
    "project": {"key": "PROJ"},
    "summary": "Issue summary",
    "description": {
      "type": "doc",
      "version": 1,
      "content": [
        {
          "type": "paragraph",
          "content": [{"type": "text", "text": "Description text"}]
        }
      ]
    },
    "issuetype": {"name": "Task"},
    "assignee": {"accountId": "user-account-id"},
    "priority": {"name": "High"},
    "labels": ["bug", "urgent"]
  }
}
Update Issue Request

PUT /​rest/​api/​3/​issue/​{issueKey}:

{
  "fields": {
    "summary": "Updated summary",
    "description": {"type": "doc", "version": 1, "content": []},
    "priority": {"name": "Medium"},
    "assignee": {"accountId": "new-user-id"}
  }
}

Step 5: Expansion and Field Selection

Use expand parameter to include additional data:

GET /​rest/​api/​3/​issue/​PROJ-123?expand=changelog,transitions

Common expansions:

  • changelog - Issue change history (required for state duration analysis)
  • transitions - Available workflow transitions
  • editmeta - Metadata about what fields can be edited
  • names - Human-readable field names

Field Selection - Return only needed fields:

GET /​rest/​api/​3/​search?fields=key,summary,status,assignee&maxResults=100

Step 6: Pagination

For large result sets, use pagination:

start_at = 0
max_results = 50
all_issues = []

while True:
    issues = client.search_issues(
        jql="project = PROJ",
        startAt=start_at,
        maxResults=max_results
    )
    all_issues.extend(issues)

    if len(issues) < max_results:
        break
    start_at += max_results

Response includes pagination metadata:

{
  "startAt": 0,
  "maxResults": 50,
  "total": 523,
  "isLast": false,
  "values": [...]
}

Step 7: Atlassian Document Format (ADF)

Rich text content (descriptions, comments) uses ADF. The project's JiraDocumentBuilder simplifies this:

from jira_tool.formatter import JiraDocumentBuilder

doc = JiraDocumentBuilder()
doc.add_heading("Title", level=1)
doc.add_paragraph(doc.bold("Key"), doc.add_text(": "), doc.add_text("Value"))
doc.add_bullet_list(["Item 1", "Item 2"])
doc.add_code_block("code content", language="python")
adf = doc.build()  # Returns ADF dict for API

ADF Structure:

{
  "type": "doc",
  "version": 1,
  "content": [
    {
      "type": "heading",
      "attrs": {"level": 1},
      "content": [{"type": "text", "text": "Heading"}]
    },
    {
      "type": "paragraph",
      "content": [{"type": "text", "text": "Paragraph"}]
    }
  ]
}

Common ADF nodes:

  • heading - Headings (levels 1-6)
  • paragraph - Text paragraphs
  • bulletList / orderedList - Lists
  • codeBlock - Code blocks
  • panel - Info panels (info, note, warning, success, error)
  • blockquote - Block quotes
  • table - Tables

See references/​reference.md for comprehensive ADF examples.

Step 8: Error Handling and Status Codes

Common HTTP status codes:

CodeMeaningHandling
200SuccessParse response normally
201CreatedResource created successfully
204No ContentSuccessful but empty response
400Bad RequestCheck request format/​parameters
401UnauthorizedCheck authentication credentials
403ForbiddenCheck permissions
404Not FoundIssue/​resource doesn't exist
429Too Many RequestsRate limited - implement backoff
500Server ErrorRetry with exponential backoff

Error Response Format:

{
  "errorMessages": ["Error message"],
  "errors": {
    "fieldName": "Field-specific error"
  }
}

The JiraClient includes automatic retry logic for 429, 500, 502, 503, 504:

client = JiraClient(max_retries=3)  # Automatic exponential backoff

Step 9: Rate Limiting

Jira Cloud has rate limits:

  • Anonymous requests: Limited
  • Authenticated: Higher limits (typically 10 requests/​second)
  • Header: X-RateLimit-* headers in response

Check rate limit headers:

response = client.session.get(url)
print(response.headers.get('X-RateLimit-Limit'))
print(response.headers.get('X-RateLimit-Remaining'))
print(response.headers.get('X-RateLimit-Reset'))

Best practices:

  • Use maxResults=100 in searches (fewer requests)
  • Cache results when possible
  • Implement exponential backoff on 429 (the client does this)
  • Batch operations when possible

Step 10: Custom Fields

Custom fields have IDs (e.g., customfield_10014). They vary per instance.

Discover custom fields:

GET /​rest/​api/​3/​field
# Using JiraClient
fields = client.list_fields()
epic_field = client.get_epic_link_field()  # Auto-discovers common field IDs

Use in queries and updates:

# In JQL
GET /​rest/​api/​3/​search?jql=customfield_10014="Epic Name"

# In updates
PUT /​rest/​api/​3/​issue/​PROJ-123
{
  "fields": {
    "customfield_10014": "Epic Name"
  }
}

Step 11: Common Patterns and Recipes

Create Issue Under Epic:

from jira_tool.formatter import JiraDocumentBuilder

doc = JiraDocumentBuilder()
doc.add_paragraph(doc.add_text("Issue description"))
adf = doc.build()

issue_data = {
    "fields": {
        "project": {"key": "PROJ"},
        "summary": "New issue",
        "description": adf,
        "issuetype": {"name": "Task"},
        "customfield_10014": "PROJ-1"  # Epic Link field
    }
}
response = client.create_issue(issue_data)

Bulk Update Issues:

# Get issues
issues = client.search_issues(
    jql="project = PROJ AND status = Open",
    maxResults=100
)

# Update each
for issue in issues:
    client.update_issue(
        issue["key"],
        {"fields": {"priority": {"name": "High"}}}
    )

Transition Workflow:

# Get available transitions
transitions = client.get_transitions("PROJ-123")

# Find the transition ID you want
for transition in transitions:
    if transition["name"] == "Done":
        transition_id = transition["id"]
        break

# Execute transition
client.transition_issue("PROJ-123", transition_id)

Search and Export:

from jira_tool.analysis.formatters import format_as_csv

issues = client.search_issues(
    jql="project = PROJ AND created >= -7d",
    expand=["changelog"]
)

csv_output = format_as_csv(issues)
print(csv_output)

Examples

Example 1: Simple API Call - Get Issue

Using Jira REST API directly:

curl -X GET \
  "https://company.atlassian.net/​rest/​api/​3/​issue/​PROJ-123" \
  -H "Authorization: Basic $(echo -n 'email:token' | base64)" \
  -H "Accept: application/​json"

Using the project's client:

from jira_tool.client import JiraClient

client = JiraClient()
issue = client.get_issue("PROJ-123")
print(f"Summary: {issue['fields']['summary']}")
print(f"Status: {issue['fields']['status']['name']}")

Example 2: Advanced Search with JQL

Find all open bugs assigned to current user:

curl -X GET \
  "https://company.atlassian.net/​rest/​api/​3/​search" \
  -G --data-urlencode 'jql=project=PROJ AND type=Bug AND assignee=currentUser() AND status != Done' \
  -G --data-urlencode 'maxResults=100' \
  -G --data-urlencode 'expand=changelog' \
  -H "Authorization: Basic ..." \
  -H "Accept: application/​json"

Using the client:

from jira_tool.client import JiraClient

client = JiraClient()
issues = client.search_issues(
    jql='project = PROJ AND type = Bug AND assignee = currentUser() AND status != Done',
    maxResults=100,
    expand=['changelog']
)

for issue in issues:
    print(f"{issue['key']}: {issue['fields']['summary']}")

Example 3: Create Issue with Rich Content

Create a detailed issue with formatted description:

from jira_tool.client import JiraClient
from jira_tool.formatter import JiraDocumentBuilder

client = JiraClient()

# Build rich content
doc = JiraDocumentBuilder()
doc.add_heading("Issue Description", level=1)
doc.add_paragraph(doc.add_text("Background: "), doc.add_text("Detailed background"))
doc.add_heading("Steps to Reproduce", level=2)
doc.add_bullet_list([
    "Step 1",
    "Step 2",
    "Step 3"
])
doc.add_panel("error", doc.add_paragraph(doc.add_text("Expected error")))
adf_description = doc.build()

# Create issue
response = client.create_issue({
    "fields": {
        "project": {"key": "PROJ"},
        "summary": "Bug: Application crashes on login",
        "description": adf_description,
        "issuetype": {"name": "Bug"},
        "priority": {"name": "Highest"},
        "labels": ["critical", "regression"]
    }
})

print(f"Created issue: {response['key']}")

Example 4: Analyze Issue State Durations

Use the project's state analyzer to track time in workflow states:

from jira_tool.client import JiraClient
from jira_tool.analysis.state_analyzer import StateDurationAnalyzer

client = JiraClient()

# Search with changelog
issues = client.search_issues(
    jql="project = PROJ AND created >= -30d",
    expand=["changelog"]
)

# Analyze state transitions
analyzer = StateDurationAnalyzer()
durations = analyzer.analyze_issues(issues)

# Export results
csv_output = analyzer.format_as_csv(durations)
print(csv_output)

Example 5: Handle Pagination

Efficiently fetch large result sets:

from jira_tool.client import JiraClient

client = JiraClient()

start_at = 0
max_results = 50
total_fetched = 0
all_issues = []

while True:
    issues = client.search_issues(
        jql="project = PROJ",
        startAt=start_at,
        maxResults=max_results
    )

    all_issues.extend(issues)
    total_fetched += len(issues)

    # Check if we got fewer results than requested (last page)
    if len(issues) < max_results:
        break

    start_at += max_results
    print(f"Fetched {total_fetched} issues...")

print(f"Total issues: {total_fetched}")

Requirements

  • Python 3.8 or higher
  • requests library (included in project)
  • Valid Jira Cloud instance with REST API v3 access
  • API token generated from Atlassian account settings
  • Environment variables: JIRA_BASE_URL, JIRA_USERNAME, JIRA_API_TOKEN

See Also

More Productivity & Planning skills

brainstorming logo
Productivity & Planning

brainstorming

Structured design dialogue that validates ideas before implementation begins.

295.4K 385.7K
View
ui-ux-pro-max logo
Productivity & Planning

ui-ux-pro-max

Comprehensive design intelligence for web and mobile UI/UX across 10 technology stacks.

133.1K 383.9K
View
writing-plans logo
Productivity & Planning

writing-plans

Comprehensive implementation plans for multi-step tasks, breaking down specs into bite-sized, testable steps.

295.4K 268K
View
using-superpowers logo
Productivity & Planning

using-superpowers

Introduction to the obra skills system with mandatory skill invocation rules and best practices.

295.4K 259.8K
View
executing-plans logo
Productivity & Planning

executing-plans

Execute a written implementation plan with critical review and task checkpoints.

295.4K 229.1K
View
dispatching-parallel-agents logo
Productivity & Planning

dispatching-parallel-agents

Delegate independent tasks to specialized agents working concurrently with isolated context.

295.4K 206.3K
View
using-git-worktrees logo
Productivity & Planning

using-git-worktrees

Isolated git worktrees with smart directory selection and safety verification.

295.4K 205.2K
View
webapp-testing logo
Productivity & Planning

webapp-testing

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

179.7K 170.6K
View
content-strategy logo
Productivity & Planning

content-strategy

Plan searchable and shareable content that drives traffic, builds authority, and generates leads.

53.3K 150.9K
View
repo-intake-and-plan logo
Productivity & Planning

repo-intake-and-plan

README-first repository scanner that extracts commands and classifies reproduction candidates without executing them.

497 139.6K
View
marketing-ideas logo
Productivity & Planning

marketing-ideas

Brainstorm and prioritize marketing strategies tailored to your SaaS stage, budget, and goals.

53.3K 137.2K
View
site-architecture logo
Productivity & Planning

site-architecture

Plan and optimize your website's page hierarchy, navigation, URL structure, and internal linking.

53.3K 112.8K
View

Productivity AI tools

Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View
SaveDay logo
Productivity

SaveDay

Capture, organize, and utilize your knowledge effortlessly.

Free
View
A
Productivity

Any Summary

Instant Summaries of Audio & Video Interviews with AnySummary

Freemium
View
M
Productivity

Map This

Transform PDFs into engaging mind maps.

Freemium
View
ChatPDF logo
Productivity

ChatPDF

Chat with any PDF instantly

Free
View
I
Productivity

intellisay

Create an optimal daily plan using your voice

Paid
View
A
Productivity

Aurora AI

A productivity platform to centralize organizational knowledge and workflows with contextual AI assistance.

Paid
View
AskYourPDF logo
Productivity

AskYourPDF

AskYourPDF Pricing Plans: Tailored to Your Needs

Free
View