praxicraft / assess
Official PHP SDK for the Praxicraft Assess Public API
Requires
- php: ^8.1
- ext-curl: *
- ext-hash: *
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^10.5
This package is auto-updated.
Last update: 2026-08-21 22:34:24 UTC
README
Official PHP client for the Praxicraft Assess Public API.
Use it to invite candidates, check invite quota, manage webhooks, enroll hiring pipelines, and fetch results from your ATS, backend, or automation scripts.
composer require praxicraft/assess
Until Packagist publish, install from GitHub:
composer require praxicraft/assess:dev-main
Requires PHP 8.1+. Full API reference: docs.praxicraft.com/sdks/php
Table of Contents
Authentication
Create an organisation API key in Assess:
Assess → Developer → API Keys → create key → copy ct_live_… (shown once).
export PRAXICRAFT_API_KEY="ct_live_xxxxxxxxxxxxxxxx"
Or pass the key when constructing the client:
use Praxicraft\Assess\Client; $client = new Client(['apiKey' => 'ct_live_xxxxxxxxxxxxxxxx']);
Optional: override the API host with PRAXICRAFT_API_BASE_URL or new Client(['baseUrl' => '...']).
Default host: https://assess.praxicraft.com.
Never commit API keys. Prefer environment variables or a secrets manager.
Scopes and rotation: Authentication
Quickstart
use Praxicraft\Assess\Client; $client = new Client(); // reads PRAXICRAFT_API_KEY $page = $client->assessments->list(); foreach ($page['results'] as $assessment) { echo $assessment['slug'], ' ', $assessment['status'], PHP_EOL; } // Invite a candidate (idempotent on email — safe to retry) $invite = $client->invites->create('senior-backend-screen', [ 'email' => 'candidate@example.com', 'name' => 'Jane Doe', 'send_email' => true, ]); echo $invite['invite_token'], ' ', $invite['invite_url'] ?? '', PHP_EOL; $result = $client->results->retrieve($invite['invite_token']); print_r($result);
Responses are flat JSON (same shape as the Public API — no { "data": … } wrapper).
What you can do
| Resource | Common methods |
|---|---|
$client->org |
retrieve(), stats() |
$client->assessments |
list(), retrieve(), create(), update(), activate(), listCases(), attachCases(), replaceCases(), removeCase() |
$client->invites |
create(), bulkCreate(), list(), retrieve(), remind(), cancel() |
$client->results |
list(), retrieve(), iterAll() |
$client->webhooks |
list(), create(), retrieve(), update(), delete(), test(), deliveries() |
$client->pipelines |
list(), retrieve(), enroll(), bulkEnroll(), listEnrollments(), getEnrollment() |
Webhooks::verifySignature |
Verify X-Praxicraft-Signature on webhook payloads |
All paths target /api/v1/public/… on the Assess host.
Check invite quota before bulk sends
$org = $client->org->retrieve(); if (($org['invites_remaining'] ?? 0) < count($candidates)) { throw new RuntimeException('Not enough invites remaining this month'); }
Bulk invites
$client->invites->bulkCreate('senior-backend-screen', [ ['email' => 'a@example.com', 'name' => 'Alex'], ['email' => 'b@example.com', 'name' => 'Blair'], ], ['send_email' => true]);
Build and activate an assessment via API
$assessment = $client->assessments->create(['title' => 'Backend screen']); $client->assessments->attachCases($assessment['slug'], [ 'cases' => [['case_id' => '<platform-or-org-case-uuid>', 'source' => 'platform']], ]); $client->assessments->activate($assessment['slug']);
Register and test a webhook
$hook = $client->webhooks->create([ 'url' => 'https://example.com/hooks/praxicraft', 'events' => ['assessment.completed', 'candidate.passed'], ]); // Store $hook['secret_key'] (whsec_…) — shown once $client->webhooks->test($hook['id']); $client->webhooks->update($hook['id'], ['is_active' => true]);
Enroll into a hiring pipeline
$enrollment = $client->pipelines->enroll('grad-2025', [ 'email' => 'alex@example.com', 'name' => 'Alex Lee', 'send_email' => true, ]); $status = $client->pipelines->getEnrollment($enrollment['enrollment_id']);
Paginate cohort results
foreach ($client->results->iterAll('senior-backend-screen', ['page_size' => 50]) as $row) { echo ($row['email'] ?? ''), ' ', ($row['score_percentage'] ?? ''), ' ', ($row['passed'] ?? ''), PHP_EOL; }
Verify webhook signatures
Assess signs the raw request body with your webhook secret (whsec_…):
use Praxicraft\Assess\Webhooks; function handleWebhook(string $rawBody, string $signatureHeader, string $secret): bool { return Webhooks::verifySignature($secret, $rawBody, $signatureHeader); }
Header format: X-Praxicraft-Signature: sha256=<hex>
Event catalog and payload examples: Webhooks
Errors
Public API errors look like:
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "This API key does not have the 'candidates:read' scope."
}
}
The SDK raises typed exceptions. Branch on $exc->errorCode, not the message text:
use Praxicraft\Assess\Exception\AuthenticationException; use Praxicraft\Assess\Exception\InsufficientScopeException; use Praxicraft\Assess\Exception\RateLimitException; use Praxicraft\Assess\Exception\ValidationException; try { $client->invites->create('demo', ['email' => 'candidate@example.com']); } catch (ValidationException $exc) { echo $exc->errorCode, ' ', json_encode($exc->details), PHP_EOL; } catch (InsufficientScopeException $exc) { echo $exc->errorCode, PHP_EOL; } catch (AuthenticationException $exc) { echo $exc->errorCode, PHP_EOL; } catch (RateLimitException $exc) { echo $exc->retryAfter, PHP_EOL; }
Error codes: Errors
Requirements & support
- PHP 8.1, 8.2, or 8.3+
- Extensions:
curl,json,hash - Product docs: docs.praxicraft.com
- Issues: GitHub Issues