Skip to main content

Python client for the Craaft API.

Project description

Craaft Python SDK

A small, synchronous Python client for the Craaft API. It wraps the REST endpoints with typed dataclasses, a sensible retry policy, and a friendly exception hierarchy.

Install

pip install craaft

Python 3.10 or newer.

Quickstart

from datetime import datetime, timedelta, timezone

from craaft import CraaftClient

# Reads CRAAFT_API_TOKEN (and optionally CRAAFT_BASE_URL) from the environment.
with CraaftClient() as client:
    me = client.me.get()
    print(f"Hi {me.name}")

    project = client.projects.create(name="Demo", description="A new board")

    card = client.projects.create_card(
        project.id,
        title="Ship the SDK",
        column="todo",
        position=1.0,
        description="all the bits",
    )

    # Some fields (priority, due_date, size) are best set via PATCH after
    # the card exists, since POST drops them on some server builds.
    client.cards.update(
        card.id,
        priority="high",
        due_date=datetime.now(timezone.utc) + timedelta(days=7),
    )

    client.cards.add_comment(card.id, body="lgtm")

    # upcoming() and search() return CardSummary previews, not full cards.
    for summary in client.cards.upcoming():
        print(summary.title, summary.due_date, summary.project_name)

Examples

The examples/ directory has runnable scripts for the most common patterns. Each one is self-contained and cleans up after itself, so they're safe to run repeatedly:

File What it shows
quickstart.py Sign in, create a card, leave a comment.
card_lifecycle.py Create, set priority and due date via PATCH, comment, move between columns, delete.
error_handling.py Which exceptions to catch and what fields they carry.
retries.py Tuning RetryConfig and reacting to RateLimitError yourself.
searching.py cards.search() and cards.upcoming(), both returning CardSummary.
advanced_client.py Custom session, alternate base URL, user-agent, debug logging.

Set CRAAFT_API_TOKEN (and optionally CRAAFT_BASE_URL) in your environment, then python examples/quickstart.py.

Configuration

from craaft import CraaftClient, RetryConfig

client = CraaftClient(
    api_key="cra_...",                     # or CRAAFT_API_TOKEN env var
    base_url="https://craaft.io/api/v1",   # or CRAAFT_BASE_URL env var (default: prod)
    timeout=30.0,                          # seconds, or (connect, read) tuple
    retry=RetryConfig(max_attempts=5),     # or retry=None to disable
    user_agent="my-app/1.0",
)

Resources

Sub-client Methods
client.me get(), update(name=, email=, username=)
client.projects list(), get(id), create(name=, description=), update(id, ...), delete(id), list_cards(id), create_card(id, title=, column=, position=, ...), add_column(id, title=)
client.cards update(id, ...), delete(id), upcoming(), search(q=, limit=20), list_comments(id), add_comment(id, body=)
client.comments update(id, body=), delete(id)
client.columns update(id, ...), delete(id)

upcoming() and search() return list[CardSummary] - lightweight previews with project_name, column_key, and column_title. Every other read returns a full Card.

Models

Frozen dataclasses, keyword-only:

  • User - id, email, name, username, avatar_url, has_password
  • Project - id, workspace_id, name, description, is_favorite, public_token, custom_css, background_image, color_scheme, text_color, total_cards, column_counts, columns, created_at, updated_at
  • Column - id, key, title, color, position, is_done, card_limit
  • Card - id, project_id, column, title, position, description, due_date, assigned_user_id, size, priority, created_by, attachment_count, created_at, updated_at
  • CardSummary - id, project_id, project_name, column_key, column_title, title, description, due_date, assigned_user_id, priority, updated_at
  • Comment - id, card_id, author_id, body, created_at, updated_at

due_date is a timezone-aware datetime. Naive datetimes you pass in are treated as UTC.

Errors

from craaft import CraaftAPIError, NotFoundError, RateLimitError

try:
    client.projects.get("missing")
except NotFoundError:
    ...
except RateLimitError as e:
    sleep(e.retry_after or 1)
except CraaftAPIError as e:
    print(e.status_code, e.message, e.request_id)

Hierarchy: CraaftError is the root. API failures raise CraaftAPIError or one of its subclasses (AuthenticationError, PermissionError, NotFoundError, ConflictError, PlanLimitError, ValidationError, RateLimitError, ServerError). Network failures raise CraaftConnectionError or CraaftTimeoutError.

Retries

The client retries 429, 502, 503, 504, and network errors with exponential backoff and Retry-After-aware pauses. Writes (POST / PATCH / DELETE) skip 5xx retries by default, since the server may have applied the change before responding. Set RetryConfig(retry_writes_on_5xx=True) if your workload is safe to retry.

Logging

The client logs one DEBUG line per HTTP attempt (method, path, status, duration, attempt number) on the craaft logger. The auth header is never logged.

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("craaft").setLevel(logging.DEBUG)

Development

pip install -e ".[dev]"
pytest
ruff check
mypy

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

craaft-1.0.0.tar.gz (21.3 kB view details)

Uploaded Source

Built Distribution

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

craaft-1.0.0-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file craaft-1.0.0.tar.gz.

File metadata

  • Download URL: craaft-1.0.0.tar.gz
  • Upload date:
  • Size: 21.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for craaft-1.0.0.tar.gz
Algorithm Hash digest
SHA256 741b7d072f292ce203068a432b8941af61018ba3e5a1802321419ab6caa2d002
MD5 1c7d421ad364e450b005afa0559f9766
BLAKE2b-256 f09d3a6fc96df244e24b2a5c326003cac9a9bbafcc09745ef509354c32d9f207

See more details on using hashes here.

File details

Details for the file craaft-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: craaft-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for craaft-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cd3212d6831a7a45fee6fd526b03b553f39fb2a2ac5c797e82872c65e57c96ed
MD5 25257acc59525bb64ecf510ce35c3a8e
BLAKE2b-256 0cee6563dff6b009c7256b2e081ca632a469a0623ffe50d3b188db54ffe30703

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