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.1.tar.gz (26.2 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.1-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: craaft-1.0.1.tar.gz
  • Upload date:
  • Size: 26.2 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.1.tar.gz
Algorithm Hash digest
SHA256 98e44ed408bc86f6865078009a0880a950c0f7b110e67307672bafbc23d44571
MD5 a91e80981bfd452f37d67cc08820f2e2
BLAKE2b-256 3004d0d7a40b01821bb2dcb09b9d6b2196029ba39b56a0b5e301ac1dd73ebae0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: craaft-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 17.9 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f09cf9bd63c3d1e291582d395c72e9ec3159b5e57ce526f65f5227db5ce56d8f
MD5 0c5a4872d847f9314a36f84010fc3566
BLAKE2b-256 b954667e0cb976baea8fc95275a8e324e04d41501d3c6458dab5af8c5e06d56d

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