Skip to main content

Praxicraft Python SDK

Official Python 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.

pip install praxicraft

Requires Python 3.10+. Full API reference: docs.praxicraft.com


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:

from praxicraft import Client

client = Client(api_key="ct_live_xxxxxxxxxxxxxxxx")

Optional: override the API host with PRAXICRAFT_API_BASE_URL or Client(base_url=...). Default host: https://assess.praxicraft.com.

Never commit API keys. Prefer environment variables or a secrets manager.

Scopes and rotation: Authentication


Quickstart

from praxicraft import Client

client = Client()  # reads PRAXICRAFT_API_KEY

# List assessments
page = client.assessments.list()
for assessment in page["results"]:
    print(assessment["slug"], assessment["status"])

# 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,
)
print(invite["invite_token"], invite.get("invite_url"))

# Fetch that candidate's result
result = client.results.retrieve(invite_token=invite["invite_token"])
print(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(), list_cases(), attach_cases(), replace_cases(), remove_case()
client.invites create(), bulk_create(), list(), retrieve(), remind(), cancel()
client.results list(), retrieve(), iter_all()
client.webhooks list(), create(), retrieve(), update(), delete(), test(), deliveries()
client.pipelines list(), retrieve(), enroll(), bulk_enroll(), list_enrollments(), get_enrollment()
verify_signature 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.get("invites_remaining") or 0) < len(candidates):
    raise SystemExit("Not enough invites remaining this month")

Bulk invites

client.invites.bulk_create(
    "senior-backend-screen",
    candidates=[
        {"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.attach_cases(
    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.get_enrollment(enrollment["enrollment_id"])

Paginate cohort results

for row in client.results.iter_all("senior-backend-screen", page_size=50):
    print(row.get("email"), row.get("score_percentage"), row.get("passed"))

Verify webhook signatures

Assess signs the raw request body with your webhook secret (whsec_…):

from praxicraft import verify_signature

def handle_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    return verify_signature(secret, raw_body, signature_header)

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.code, not the message text:

from praxicraft import (
    AuthenticationError,
    InsufficientScopeError,
    RateLimitError,
    ValidationError,
)

try:
    client.invites.create("demo", email="candidate@example.com")
except ValidationError as exc:
    # e.g. ASSESSMENT_NOT_ACTIVE, REMINDER_COOLDOWN, VALIDATION_ERROR
    print(exc.code, exc.details)
except InsufficientScopeError as exc:
    print(exc.code)  # INSUFFICIENT_SCOPE, INVITE_QUOTA_EXCEEDED, …
except AuthenticationError as exc:
    print(exc.code)  # INVALID_API_KEY, EXPIRED_API_KEY
except RateLimitError as exc:
    print(exc.retry_after)  # seconds from Retry-After, when present

Error codes: Errors


Requirements & support


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

praxicraft-0.1.0.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

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

praxicraft-0.1.0-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file praxicraft-0.1.0.tar.gz.

File metadata

  • Download URL: praxicraft-0.1.0.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for praxicraft-0.1.0.tar.gz
Algorithm Hash digest
SHA256 673758e44c11d79999fd78d92436deaa2f5ff5ab234fecee8346f0e96cfff6ac
MD5 920954fe5c37a08e4b7d70a5bc2bf1e5
BLAKE2b-256 56edd3a756c46f3f3aa5cb4f861d4ca7fe26b5a0bfd80c810e6fd60cb9eaa89a

See more details on using hashes here.

Provenance

The following attestation bundles were made for praxicraft-0.1.0.tar.gz:

Publisher: publish.yml on praxicraft-platform/praxicraft-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file praxicraft-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: praxicraft-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for praxicraft-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 58944fd304f4f5adfe72a05eb97e3eace0670bc17ba30ccf1048f997301a9248
MD5 ed0d9ab3023150f4b9498ec54fce5d7e
BLAKE2b-256 11219bbb83ec88f5728f10354d93e4e38892f60740ad5d6e80070622fdd30585

See more details on using hashes here.

Provenance

The following attestation bundles were made for praxicraft-0.1.0-py3-none-any.whl:

Publisher: publish.yml on praxicraft-platform/praxicraft-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.1.2

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page