Skip to main content

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",
    )

    # Metadata (priority, due_date, size, tags) is set via PATCH after create.
    client.cards.update(
        card.id,
        priority="high",
        size=3,
        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(...), update(id, ...), delete(id), export(id), list_tags(id), enable_share(id), disable_share(id), list_cards(id), create_card(id, ...), add_column(id, title=), list_members(id), add_member(id, ...), update_member(id, ...), remove_member(id, ...)
client.cards update(id, ...), delete(id), move(id, ...), upcoming(), focus(), hygiene(type=), list_events(id), search(q=, limit=20), list_comments(id), add_comment(id, body=)
client.attachments list_for_card(card_id), upload(card_id, file=, filename=, content_type=), download(attachment_id), delete(attachment_id)
client.comments update(id, body=), delete(id)
client.columns update(id, ...), delete(id), archive(id)
client.members list(), list_invitations(), create_invitation(...)

upcoming() and search() return list[CardSummary] - lightweight previews. focus() returns a FocusResponse with due, attention, and hygiene buckets.

Models

Frozen dataclasses, keyword-only. Highlights:

  • User, Project, Column, Card, Comment, Attachment
  • CardSummary, AttentionCard, FocusResponse, HygieneCounts, CardEvent
  • BoardMember, BoardMemberGrant, WorkspaceMember, Invitation
  • ProjectExport (+ nested export types)

Card.size is an optional integer estimate. Card.priority is one of low, medium, high, urgent. Set metadata via cards.update() after create_card() - the create endpoint only accepts title, column, position, and optional description.

attachments.upload() sends multipart form data (max 25 MiB per file) and requires a Pro/Team workspace; use project.can_upload_attachments to check first.

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

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.2.0.tar.gz (30.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.2.0-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: craaft-1.2.0.tar.gz
  • Upload date:
  • Size: 30.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.2.0.tar.gz
Algorithm Hash digest
SHA256 36c9c45af16c01d2e8be804dd3b3ca26b5ecae3149745813bf2cd10de2c802c8
MD5 39b31e6d340d57857f533fba18cf6a43
BLAKE2b-256 fa052736ced354b2f44e8b89d8a174869a1413670ffa3b839547b6caf18bb994

See more details on using hashes here.

File details

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

File metadata

  • Download URL: craaft-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.2 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f710b6dffff75d9ce54d362613db6fbf12fbb0d74d875d276b7aa739b1fae93
MD5 8a8776151166fdbb5cea52e0c96401c8
BLAKE2b-256 e0a5be71643932afb9a48301347fe3bbf60625bd4323bc298c740b4e8ef8ecc4

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