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/sdks/python

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:

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

Metadata

Release files for praxicraft 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for praxicraft 0.1.3
File Size Uploaded
praxicraft-0.1.3.tar.gz 19.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for praxicraft 0.1.3
File Interpreter ABI Platform
praxicraft-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 38.2 kB

Release files / praxicraft-0.1.3.tar.gz

Download URL praxicraft-0.1.3.tar.gz
Size 19.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ceac856b953c64d08fe85519874f5101fa446cf3c3efa7d8dd87a5581df5c141
BLAKE2b-256 checksum
How to use checksums
d2165073b3d982e8c9054dd375ef5e03e7edfc3d69ee61bdf13b3fbca59e07f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.

Transparency log

Release files / praxicraft-0.1.3-py3-none-any.whl

Download URL praxicraft-0.1.3-py3-none-any.whl
Size 18.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
23e9ed63b2aca9289739d9cb86a118deb5fc8b9b6464e7b5a2db7f9d644667a6
BLAKE2b-256 checksum
How to use checksums
53b75a8f62d54a6ffbd058056e4c924a14c07f7b17fbcdc67a48409f72319f36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.

Transparency log

Release history Release notifications | RSS feed

1.0.0

2 release files

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page