PHPackages                             craaft/craaft - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. craaft/craaft

ActiveLibrary[API Development](/categories/api)

craaft/craaft
=============

PHP client for the Craaft API.

v1.0.0(today)10MITPHPPHP ^8.2

Since Jun 30Pushed todayCompare

[ Source](https://github.com/craaft/php-sdk)[ Packagist](https://packagist.org/packages/craaft/craaft)[ RSS](/packages/craaft-craaft/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (1)Versions (2)Used By (0)

Craaft PHP SDK
==============

[](#craaft-php-sdk)

A small, synchronous PHP client for the [Craaft API](https://craaft.io). It wraps the REST endpoints with readonly typed DTOs, a sensible retry policy, and a friendly exception hierarchy. Mirrors the feature set of the official Python SDK.

Install
-------

[](#install)

```
composer require craaft/craaft
```

PHP 8.2 or newer. Only `ext-curl`, `ext-json`, and `ext-mbstring` are required — no Guzzle, no PSR-18, nothing else to install.

Quickstart
----------

[](#quickstart)

```
use Craaft\CraaftClient;
use Craaft\Enums\Priority;

// Reads CRAAFT_API_TOKEN (and optionally CRAAFT_BASE_URL) from the environment.
$client = new CraaftClient();

$me = $client->me->get();
echo "Hi {$me->name}\n";

$project = $client->projects->create('Demo', description: 'A new board');

$card = $client->projects->createCard(
    $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: Priority::High,
    size: 3,
    dueDate: new DateTimeImmutable('+7 days', new DateTimeZone('UTC')),
);

$client->cards->addComment($card->id, body: 'lgtm');

// upcoming() and search() return CardSummary previews, not full cards.
foreach ($client->cards->upcoming() as $summary) {
    echo "{$summary->title} — {$summary->dueDate?->format('c')} ({$summary->projectName})\n";
}

$client->close();
```

Configuration
-------------

[](#configuration)

```
use Craaft\CraaftClient;
use Craaft\Http\RetryConfig;

$client = new CraaftClient(
    apiKey: 'cra_...',                     // or CRAAFT_API_TOKEN env var
    baseUrl: 'https://craaft.io/api/v1',   // or CRAAFT_BASE_URL env var (default: prod)
    timeout: 30.0,                         // seconds, or [connect, read] tuple
    retry: new RetryConfig(maxAttempts: 5), // or new RetryConfig(maxAttempts: 1) to disable
    userAgent: 'my-app/1.0',
);
```

`http://` base URLs are only allowed for `localhost` / `127.0.0.1` / `::1` during development — anything else must be `https://` to avoid leaking the bearer token.

Resources
---------

[](#resources)

Sub-clientMethods`$client->me``get()`, `update(name:, email:, username:)``$client->projects``list()`, `get($id)`, `create($name, $description)`, `update($id, ...)`, `delete($id)`, `export($id)`, `listTags($id)`, `enableShare($id)`, `disableShare($id)`, `listCards($id)`, `createCard($id, ...)`, `addColumn($id, $title)`, `listMembers($id)`, `addMember($id, $userId, $role)`, `updateMember($id, $userId, $role)`, `removeMember($id, $userId)``$client->cards``update($id, ...)`, `delete($id)`, `move($id, $targetProjectId, $column)`, `upcoming()`, `focus()`, `hygiene($type)`, `listEvents($id)`, `search($q, $limit=20)`, `listComments($id)`, `addComment($id, $body)``$client->attachments``listForCard($cardId)`, `upload($cardId, $file, $filename, $contentType)`, `download($attachmentId)`, `delete($attachmentId)``$client->comments``update($id, $body)`, `delete($id)``$client->columns``update($id, ...)`, `delete($id)`, `archive($id)``$client->members``list()`, `listInvitations()`, `createInvitation($email, $role, $boardGrants)``upcoming()` and `search()` return `array` — lightweight previews. `focus()` returns a `FocusResponse` with `due`, `attention`, and `hygiene` buckets.

Models
------

[](#models)

Readonly value objects, one class per schema. Highlights:

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

Finite string fields are backed enums: `Priority` (`low`/`medium`/`high`/`urgent`), `BoardRole` (`admin`/`contributor`), `WorkspaceRole`, `Visibility`, `TextColor`, `BoardMemberSource`, `HygieneType`, `CardEventType`. Unknown enum values from the server resolve to `null` (forward-compatible).

`Card->size` is an optional **integer** estimate. Set metadata via `cards->update()`after `createCard()` — 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; check `Project->canUploadAttachments` first. It accepts a filesystem path, a `SplFileInfo`, or a string of raw bytes.

Errors
------

[](#errors)

```
use Craaft\Exceptions\CraaftApiError;
use Craaft\Exceptions\NotFoundError;
use Craaft\Exceptions\RateLimitError;

try {
    $client->projects->get('missing');
} catch (NotFoundError $e) {
    // 404
} catch (RateLimitError $e) {
    usleep((int) (($e->retryAfter ?? 1.0) * 1_000_000));
} catch (CraaftApiError $e) {
    echo $e->statusCode, ' ', $e->getMessage(), ' ', $e->requestId ?? '';
}
```

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 `ConnectionError` or `TimeoutError`.

`CraaftApiError` exposes `statusCode`, `responseBody`, `requestId`, and `getMessage()` returns the server's parsed `error` string. `RateLimitError` adds `retryAfter` (seconds, possibly fractional; null when not supplied).

Retries
-------

[](#retries)

The client retries `429`, `502`, `503`, `504`, and network errors with exponential backoff and `Retry-After`-aware pauses. Writes (`POST`/`PATCH`/`PUT`/`DELETE`) skip 5xx retries by default, since the server may have applied the change before responding. Pass `new RetryConfig(retryWritesOn5xx: true)` if your workload is safe to retry. To disable retries entirely, pass `new RetryConfig(maxAttempts: 1)`.

Development
-----------

[](#development)

```
composer install
composer test           # or: vendor/bin/phpunit
```

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fc5d3604a6b0250bca6056c44dd38f0b48e140dbf673c135c1bc30dbf16edc64?d=identicon)[underwulf](/maintainers/underwulf)

---

Top Contributors

[![sn](https://avatars.githubusercontent.com/u/77145?v=4)](https://github.com/sn "sn (1 commits)")

---

Tags

craaftphprest-apiapiclientsdkcraaft

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/craaft-craaft/health.svg)

```
[![Health](https://phpackages.com/badges/craaft-craaft/health.svg)](https://phpackages.com/packages/craaft-craaft)
```

###  Alternatives

[kunalvarma05/dropbox-php-sdk

Dropbox PHP API V2 SDK (Unofficial)

3613.1M18](/packages/kunalvarma05-dropbox-php-sdk)[jolicode/slack-php-api

An up to date PHP client for Slack's API

2554.6M13](/packages/jolicode-slack-php-api)[deepseek-php/deepseek-php-client

deepseek PHP client is a robust and community-driven PHP client library for seamless integration with the Deepseek API, offering efficient access to advanced AI and data processing capabilities.

46784.5k5](/packages/deepseek-php-deepseek-php-client)[qwen-php/qwen-php-client

robust and community-driven PHP SDK library for seamless integration with the qwen AI API, offering efficient access to advanced AI and data processing capabilities

203.2k1](/packages/qwen-php-qwen-php-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
