Skip to main content

Modern Python Jira client — sync and async — powered by HTTPX

Project description

jirapi

Modern, type-safe Python client for the Jira Cloud REST API — built on HTTPX for first-class sync and async support.

Features

  • Sync and async — identical API surface via Jira (sync) and AsyncJira (async)
  • Full API coverage — auto-generated resource methods for 580+ Jira Cloud REST endpoints
  • Type-safe — Pydantic v2 models for every request and response payload
  • Composition pattern — resource groups (issues, projects, users, …) exposed as lazy @cached_property attributes
  • Pagination helpers — built-in iterators for offset, PageBean, and cursor pagination
  • Semantic exceptionsAuthenticationError, NotFoundError, RateLimitError, etc.
  • Modern Python — 3.11+, built-in generics, union types, no legacy typing imports
  • Minimal dependencies — just httpx and pydantic

Installation

pip install jirapi
# or
uv add jirapi

Quick Start

Synchronous

from jirapi import Jira

jira = Jira(
    url="https://yoursite.atlassian.net",
    email="you@example.com",
    api_token="your-api-token",
)

# Fetch a single issue
issue = jira.issues.get_issue("PROJ-123")
print(issue.fields.summary)

# Search projects
page = jira.projects.search_projects(query="backend", max_results=10)

# Always close when done (or use a context manager)
jira.close()

Context Manager

from jirapi import Jira

with Jira(url="https://yoursite.atlassian.net", email="...", api_token="...") as jira:
    issue = jira.issues.get_issue("PROJ-123")

Asynchronous

import asyncio
from jirapi import AsyncJira

async def main():
    async with AsyncJira(
        url="https://yoursite.atlassian.net",
        email="you@example.com",
        api_token="your-api-token",
    ) as jira:
        issue = await jira.issues.get_issue("PROJ-123")
        print(issue.fields.summary)

asyncio.run(main())

Resource Groups

All API endpoints are organised into resource groups accessible as properties on the client:

jira.issues               # Issues, changelogs, transitions
jira.projects             # Projects CRUD and search
jira.users                # User lookup and management
jira.issue_search         # JQL search
jira.dashboards           # Dashboard operations
jira.filters              # Saved filter management
jira.workflows            # Workflow definitions
jira.permissions          # Permission checks
jira.server_info          # Jira instance metadata
# … 60+ resource groups in total

Each method returns a strongly-typed Pydantic model:

from jirapi.models import IssueUpdateDetails

# Create an issue
created = jira.issues.create_issue(
    body=IssueUpdateDetails.model_validate({
        "fields": {
            "project": {"key": "PROJ"},
            "summary": "New issue from jirapi",
            "issuetype": {"name": "Task"},
        }
    })
)
print(created.key)

Error Handling

All API errors are mapped to typed exceptions:

from jirapi import Jira, NotFoundError, RateLimitError, AuthenticationError
import time

jira = Jira(url="...", email="...", api_token="...")

try:
    jira.issues.get_issue("DOES-NOT-EXIST")
except NotFoundError as e:
    print(f"Issue not found: {e}")
except RateLimitError as e:
    print(f"Rate limited — retry after {e.retry_after}s")
    time.sleep(e.retry_after or 60)
except AuthenticationError:
    print("Check your credentials")
Status Code Exception
400 ValidationError
401 AuthenticationError
403 ForbiddenError
404 NotFoundError
409 ConflictError
429 RateLimitError
5xx ServerError

Pagination

jirapi provides pagination helpers for all three patterns used by the Jira API:

from jirapi.pagination import paginate_offset, paginate_page_bean

# Offset-based (e.g. issue search)
for issue in paginate_offset(jira._request, "GET", "/rest/api/3/search", results_key="issues"):
    print(issue["key"])

# PageBean-based (e.g. project search)
for project in paginate_page_bean(jira._request, "GET", "/rest/api/3/project/search"):
    print(project["name"])

Configuration

Parameter Description Default
url Jira Cloud instance URL
email Account email for Basic auth
api_token API token from id.atlassian.com
timeout Request timeout in seconds 30.0
**httpx_client_kwargs Extra kwargs passed to the underlying HTTPX client

Development

# Install dependencies
task setup          # uv sync --all-groups

# Run quality checks
task check          # lint + format check + tests

# Run tests with coverage
task test:cov       # uv run pytest --cov=jirapi tests/unit

# Regenerate models from OpenAPI spec
uv run python scripts/generate_models.py

# Regenerate resource classes and client wiring
uv run python scripts/generate_resources.py

Architecture

jirapi/
├── __init__.py          # Public API exports
├── client.py            # Jira (sync) + AsyncJira — entry points
├── _base_client.py      # Shared HTTP logic, auth, error checking
├── _resource.py         # SyncAPIResource / AsyncAPIResource bases
├── _types.py            # Type aliases (JSON, Params, T)
├── exceptions.py        # Exception hierarchy
├── pagination.py        # Offset / PageBean / cursor iterators
├── models/              # 967 auto-generated Pydantic v2 models
│   └── __init__.py
└── resources/           # 60+ auto-generated resource modules
    ├── __init__.py
    ├── issues.py        # Issues + AsyncIssues
    ├── projects.py      # Projects + AsyncProjects
    └── ...

scripts/
├── generate_models.py     # OpenAPI → Pydantic models
└── generate_resources.py  # OpenAPI → resource classes + client wiring

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jirapi-0.1.0.tar.gz (517.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jirapi-0.1.0-py3-none-any.whl (220.1 kB view details)

Uploaded Python 3

File details

Details for the file jirapi-0.1.0.tar.gz.

File metadata

  • Download URL: jirapi-0.1.0.tar.gz
  • Upload date:
  • Size: 517.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for jirapi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e29ea0c0c611e93311ab2d5daa236e0fd75f5c6892472e4826f0b3d3c27b6ddc
MD5 83adcfdf3d1f83071082550c20846cc7
BLAKE2b-256 5df6ba976188c55f3c640e781f35acbbbbb938a23effae456d724f6a2045aa88

See more details on using hashes here.

File details

Details for the file jirapi-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: jirapi-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 220.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for jirapi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d8861d698c5c373bb39891009220e5b412fbb90a2d048a7618c0339ec8ecfc42
MD5 a3c34639e9c43c8089dd42e1335fb162
BLAKE2b-256 06d61388c6b683eb00bdeccc6f20aa56fdfe1116e5ce8604a7f1776ece6f6909

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page