A comprehensive Python wrapper for the Linear API with rich Pydantic models, simplified workflows, and an object-oriented design.
npx @tessl/cli install tessl/pypi-linear-api@0.2.0A comprehensive Python wrapper for the Linear API with rich Pydantic models, simplified workflows, and an object-oriented design. This package provides programmatic access to Linear's project management platform, enabling developers to integrate Linear functionality into their applications and workflows with type safety, automatic pagination handling, intelligent caching, and comprehensive error management.
pip install linear-apipydantic>=2.0.0, requests>=2.25.0from linear_api import LinearClientImport domain models and types:
from linear_api import (
LinearIssue,
LinearProject,
LinearUser,
LinearTeam,
LinearState,
LinearLabel,
LinearAttachment,
LinearIssueInput,
LinearIssueUpdateInput,
LinearAttachmentInput,
LinearPriority,
IntegrationService,
SLADayCountType,
ProjectStatusType,
)Import utility functions for low-level access:
from linear_api.utils import call_linear_apifrom linear_api import LinearClient
# Create client with API key
client = LinearClient(api_key="your_api_key_here")
# Or use environment variable LINEAR_API_KEY
client = LinearClient()
# Get an issue by ID
issue = client.issues.get("issue-id")
print(f"Issue: {issue.title} ({issue.state.name})")
# Create a new issue
from linear_api import LinearIssueInput
new_issue = client.issues.create(LinearIssueInput(
title="New task from API",
teamName="Engineering",
description="Task created via Python API"
))
# Get all projects for a team
projects = client.projects.get_all()
print(f"Found {len(projects)} projects")
# Get current user info
me = client.users.get_me()
print(f"Current user: {me.name} ({me.email})")The Linear API package follows a manager-based architecture that provides a clean separation of concerns:
This architecture enables both high-level abstractions for common workflows and low-level GraphQL access for advanced use cases, with comprehensive type safety throughout.
Central client configuration and authentication for accessing Linear's API with caching, connection management, and schema validation capabilities.
class LinearClient:
def __init__(
self,
api_key: Optional[str] = None,
enable_cache: bool = True,
cache_ttl: int = 3600,
auto_unwrap_connections: bool = True,
): ...
def call_api(self, query: Dict[str, Any] | str) -> Dict[str, Any]: ...
def execute_graphql(self, query: str, variables: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: ...
def clear_cache(self, cache_name: Optional[str] = None) -> None: ...
def enable_connection_unwrapping(self) -> None: ...
def disable_connection_unwrapping(self) -> None: ...Comprehensive issue management including creation, updates, querying, and relationship management with support for attachments, comments, and metadata.
class IssueManager:
def get(self, issue_id: str) -> LinearIssue: ...
def create(self, issue: LinearIssueInput) -> LinearIssue: ...
def update(self, issue_id: str, update_data: LinearIssueUpdateInput) -> LinearIssue: ...
def delete(self, issue_id: str) -> bool: ...
def get_by_team(self, team_name: str) -> Dict[str, LinearIssue]: ...
def get_by_project(self, project_id: str) -> Dict[str, LinearIssue]: ...
def get_all() -> Dict[str, LinearIssue]: ...Full project lifecycle management including creation, updates, member management, and relationship tracking with milestones, updates, and documentation.
class ProjectManager:
def get(self, project_id: str) -> LinearProject: ...
def create(self, name: str, team_name: str, description: Optional[str] = None) -> LinearProject: ...
def update(self, project_id: str, **kwargs) -> LinearProject: ...
def delete(self, project_id: str) -> bool: ...
def get_all(self, team_id: Optional[str] = None) -> Dict[str, LinearProject]: ...
def get_id_by_name(self, project_name: str, team_id: Optional[str] = None) -> str: ...Team configuration and member management including workflow states, labels, cycles, templates, and organizational hierarchy.
class TeamManager:
def get(self, team_id: str) -> LinearTeam: ...
def get_all() -> Dict[str, LinearTeam]: ...
def get_id_by_name(self, team_name: str) -> str: ...
def get_states(self, team_id: str, include_issue_ids: bool = False) -> List[LinearState]: ...
def get_members(self, team_id: str) -> List[LinearUser]: ...
def get_labels(self, team_id: str, include_issue_ids: bool = False) -> List[LinearLabel]: ...User operations including profile access, team memberships, issue assignments, and organizational data management.
class UserManager:
def get(self, user_id: str) -> LinearUser: ...
def get_all() -> Dict[str, LinearUser]: ...
def get_me() -> LinearUser: ...
def get_id_by_email(self, email: str) -> str: ...
def get_id_by_name(self, name: str) -> str: ...
def get_assigned_issues(self, user_id: str) -> Dict[str, LinearIssue]: ...Rich Pydantic models covering all Linear entities with complete field definitions, input/output types, enums, and connection types for GraphQL pagination.
class LinearIssue(LinearModel):
id: str
title: str
url: str
state: LinearState
priority: LinearPriority
team: LinearTeam
# 50+ additional fields...
class LinearIssueInput(LinearModel):
title: str
teamName: str
# Optional fields for creation...
class LinearPriority(Enum):
URGENT = 0
HIGH = 1
MEDIUM = 2
LOW = 3
NONE = 4Low-level utilities including direct GraphQL access, caching management, data processing functions, and schema validation tools for advanced use cases.
def call_linear_api(query: str | Dict[str, Any], api_key: Optional[str] = None) -> Dict[str, Any]: ...
class CacheManager:
def get(self, cache_name: str, key: Any) -> Optional[Any]: ...
def set(self, cache_name: str, key: Any, value: Any, ttl: Optional[int] = None) -> None: ...
def clear(self, cache_name: Optional[str] = None) -> None: ...Set your Linear API key as an environment variable:
export LINEAR_API_KEY="your_api_key_here"Or pass it directly to the client:
client = LinearClient(api_key="your_api_key_here")Control caching behavior:
# Disable caching entirely
client = LinearClient(enable_cache=False)
# Custom cache TTL (in seconds)
client = LinearClient(cache_ttl=7200) # 2 hours
# Runtime cache control
client.cache.disable()
client.cache.clear()
client.cache.enable()Control automatic GraphQL pagination handling:
# Disable automatic connection unwrapping for performance
client = LinearClient(auto_unwrap_connections=False)
# Runtime control
client.disable_connection_unwrapping()
client.enable_connection_unwrapping()The package provides comprehensive error handling with descriptive messages:
from linear_api import LinearClient
try:
client = LinearClient() # Will raise if no API key
issue = client.issues.get("invalid-id")
except ValueError as e:
print(f"API Error: {e}")Common error scenarios: