Skip to main content

Snail Orbit Python Client

Type-safe Python client for the Snail Orbit project management API.

Installation

uv add snail-orbit-client
# or
pip install snail-orbit-client

Usage

Sync Client

from snail_orbit_client import SnailOrbitClient

client = SnailOrbitClient(
    base_url='https://your-snail-orbit.example.com',
    token='your-api-token'
)

# Get current user
profile = client.auth.get_profile()
print(f'Logged in as: {profile.name}')

# List issues
for issue in client.issues.list(q='priority:high and status:open'):
    print(f'{issue.id_readable}: {issue.subject}')

# Get specific issue
issue = client.issues.get('issue-id')

# Access custom fields
priority_field = issue.fields.get('priority')
if priority_field:
    print(f'Priority: {priority_field.value}')

Async Client

import asyncio
from snail_orbit_client import SnailOrbitAsyncClient

async def main():
    async with SnailOrbitAsyncClient(
        base_url='https://your-snail-orbit.example.com',
        token='your-api-token'
    ) as client:
        profile = await client.auth.get_profile()

        async for issue in client.issues.list(q='status:open'):
            print(f'{issue.id_readable}: {issue.subject}')

asyncio.run(main())

API Resources

client.auth            # Authentication and profile
client.users           # User operations
client.projects        # Project operations
client.issues          # Issue CRUD operations
client.custom_fields   # Custom field definitions
client.activity        # Activity tracking

Issues

client.issues.list(q=None, search=None)           # List/query issues
client.issues.get(issue_id)                       # Get by ID
client.issues.get_by_readable_id(readable_id)     # Get by readable ID (e.g., 'PRJ-123')
client.issues.create(issue_data)                  # Create issue
client.issues.update(issue_id, issue_data)        # Update issue

# Comments
client.issues.get_comments(issue_id)
client.issues.create_comment(issue_id, comment_data)
client.issues.update_comment(issue_id, comment_id, comment_data)
client.issues.delete_comment(issue_id, comment_id)

# Tags
client.issues.add_tag(issue_id, tag_id)
client.issues.remove_tag(issue_id, tag_id)

# Attachments
client.issues.list_attachments(issue_id)                    # List attachments
client.issues.add_attachment(issue_id, attachment_input)    # Add attachment
client.issues.remove_attachment(issue_id, attachment_id)    # Remove attachment
client.issues.download_attachment(issue_id, attachment_id)  # Stream download
client.issues.upload_and_attach(issue_id, file)             # Upload and attach in one call

File Uploads

# Upload a file (loads into memory)
result = client.upload_file(b'content', filename='doc.pdf')
result = client.upload_file('/path/to/file.pdf')
result = client.upload_file(open('file.pdf', 'rb'))

# Streaming upload (memory-efficient for large files)
def read_chunks():
    with open('large_file.zip', 'rb') as f:
        while chunk := f.read(8192):
            yield chunk

result = client.stream_upload(read_chunks(), 'large_file.zip')

# Attach uploaded file to issue
from snail_orbit_client.models import IssueAttachmentInput
client.issues.add_attachment(issue_id, IssueAttachmentInput(id=result.id))

# Or use the convenience method
attachment = client.issues.upload_and_attach(issue_id, '/path/to/file.pdf')

Downloading Attachments

# Stream to file (memory-efficient)
with open('output.pdf', 'wb') as f:
    for chunk in client.issues.download_attachment(issue_id, attachment_id):
        f.write(chunk)

# Collect in memory (if you need bytes)
content = b''.join(client.issues.download_attachment(issue_id, attachment_id))

# Async streaming to file
async with aiofiles.open('output.pdf', 'wb') as f:
    async for chunk in client.issues.download_attachment(issue_id, attachment_id):
        await f.write(chunk)

Search and Filtering

# Issue query language
client.issues.list(q='priority:high and status:open')
client.issues.list(q='assignee:me and project:myproject')

# Text search
client.issues.list(search='database bug')

# Users and projects use filter parameter
client.users.list(search='john', filter='is_active___eq:true')
client.projects.list(filter='created_at___gte:2024-01-01')

Configuration

from snail_orbit_client import SnailOrbitClient, ClientConfig

config = ClientConfig(
    timeout=30.0,           # Request timeout in seconds
    max_retries=3,          # Maximum retry attempts
    retry_delay=1.0,        # Base delay between retries
)

client = SnailOrbitClient(
    base_url='https://your-snail-orbit.example.com',
    token='your-token',
    config=config
)

JWT Authentication

# JWT signing with service credentials
client = SnailOrbitClient(
    base_url='https://api.snail-orbit.com',
    token=('key-id', 'secret', 'user-id')
)

Error Handling

from snail_orbit_client.exceptions import (
    SnailOrbitError,
    AuthenticationError,
    NotFoundError,
    ValidationError,
    RateLimitError,
)

try:
    issue = client.issues.get('invalid-id')
except NotFoundError:
    print('Issue not found')
except AuthenticationError:
    print('Authentication failed')
except ValidationError as e:
    print(f'Validation errors: {e.validation_errors}')
except RateLimitError as e:
    print(f'Rate limited, retry after {e.retry_after}s')

Metadata

Release files for snail-orbit-client 0.13.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for snail-orbit-client 0.13.2
File Interpreter ABI Platform
snail_orbit_client-0.13.2-py3-none-any.whl Python 3 none any Details

Release files / snail_orbit_client-0.13.2-py3-none-any.whl

Download URL snail_orbit_client-0.13.2-py3-none-any.whl
Size 40.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d1068257681eaa35c1339319895f02add666b16d7b980080303c68c9deced051
BLAKE2b-256 checksum
How to use checksums
4c95ce379d5746aaf60dfb25a8e9c21d2b86fda27e22ac3c7fa1c93c24e1ca17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.13.2 This release

1 release file

0.11.1

1 release file

0.11.0

1 release file

0.6.13

1 release file

0.6.7

1 release file

0.6.2

1 release file

0.5.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page