Skip to main content

certilayer

Verify human sessions server-side in 3 lines.

The official Python SDK for CertiLayer — a fully async client for calling CertiLayer's HCS (Human Confidence Score) API after your Web, iOS, Android, or React Native SDK has captured a session. Gate critical actions — login, checkout, signup, password changes — with a single await.

PyPI version License: MIT


Installation

pip install certilayer

Framework integrations are optional extras — install only what you need:

pip install certilayer[fastapi]   # FastAPI dependency helper
pip install certilayer[django]    # Django middleware

⚠️ Secret key — server-side only

CertiLayerClient takes your secret key (certilayer_live_sk_... or certilayer_test_sk_...). This SDK is for server environments only — never ship this key to a browser, mobile app, or any client-side code. For the client side, use @certilayer/web (or the iOS/Android/React Native SDK), which takes your public key instead.


Quick start

from certilayer import CertiLayerClient

client = CertiLayerClient(api_key="certilayer_live_sk_...")
result = await client.verify_session(session_id)

if result.verdict == "synthetic":
    raise HTTPException(status_code=403, detail="bot_detected")

session_id is the session ID produced by whichever client-side SDK (@certilayer/web, iOS, Android, or React Native) is running on the same page/app the user is on.

Use the client as an async context manager, or call aclose() yourself on shutdown:

async with CertiLayerClient(api_key="certilayer_live_sk_...") as client:
    result = await client.verify_session(session_id)

Client configuration

CertiLayerClient(
    api_key: str,
    base_url: str = "https://api.certilayer.net/v1",
    timeout_s: float = 10.0,
    max_retries: int = 2,
)
Parameter Default Notes
api_key Required. Raises INVALID_API_KEY if empty.
base_url https://api.certilayer.net/v1 Override only for self-hosted deployments.
timeout_s 10.0 Per-request timeout, in seconds.
max_retries 2 Retries 5xx and network errors with exponential backoff. 4xx errors are never retried.

API reference

await client.verify_session(session_id, critical=False) -> VerifyResult

Full verification — returns score, verdict, and session metadata.

@dataclass(frozen=True)
class VerifyResult:
    score: float          # 0.0 – 1.0
    verdict: HCSVerdict   # 'human_verified' | 'human_likely' | 'synthetic'
    session_id: str
    scored_at: str          # UTC ISO-8601

Pass critical=True immediately before a high-stakes action (payment, password change, account mutation). This tells the policy engine to apply stricter critical-action rules, which can escalate a grey-zone score to a step-up challenge or session termination instead of a softer response.

try:
    await client.verify_session(session_id, critical=True)
except CertiLayerError as e:
    if e.code == "STEP_UP_REQUIRED":
        return prompt_webauthn()
    raise

await client.quick_check(session_id, min_score=0.30, critical=False) -> QuickCheckResult

Lighter than verify_session() — just a pass/fail gate decision without full session metadata.

@dataclass(frozen=True)
class QuickCheckResult:
    score: float
    verdict: HCSVerdict
    passed: bool           # True if score >= min_score
check = await client.quick_check(session_id)
if not check.passed:
    return JSONResponse({"error": "bot_detected"}, status_code=403)

HCS verdict thresholds

Verdict Score range Recommended action
human_verified ≥ 0.35 Allow — high confidence
human_likely 0.30 – 0.35 Soft friction / step-up auth
synthetic < 0.30 Block or challenge

Unknown/future verdict strings from the API fall back to synthetic as a safe default.


Framework integrations

FastAPI

from fastapi import Depends
from certilayer import CertiLayerClient

client = CertiLayerClient(api_key=settings.CERTILAYER_KEY)
guard  = client.fastapi_dependency(min_score=0.90)

@app.post("/checkout", dependencies=[Depends(guard)])
async def checkout(): ...
client.fastapi_dependency(
    session_header: str = "x-certilayer-session",
    min_score: float = 0.30,
)

Reads the session ID from the given header and raises HTTPException(403) if the check fails. Fails open (allows the request) if the CertiLayer API call itself errors — a transient outage never blocks real users.

Django

# settings.py
client = CertiLayerClient(api_key=settings.CERTILAYER_KEY)
MIDDLEWARE = [
    ...
    client.django_middleware(),
]
client.django_middleware(
    session_header: str = "HTTP_X_CERTILAYER_SESSION",
    min_score: float = 0.30,
    reject_status: int = 403,
)

Note the header name uses Django's META convention — Django automatically converts an x-certilayer-session HTTP header into HTTP_X_CERTILAYER_SESSION. Like the FastAPI dependency, this fails open on transient CertiLayer API errors.


Error handling

All SDK errors raise CertiLayerError with a machine-readable .code:

from certilayer import CertiLayerError

try:
    result = await client.verify_session(session_id)
except CertiLayerError as e:
    if e.code == "SESSION_NOT_FOUND":
        return JSONResponse({"error": "session_expired"}, status_code=400)
    raise
Code Meaning
INVALID_API_KEY API key missing, empty, or rejected by the server
SESSION_NOT_FOUND No session exists for the given session_id
SESSION_EXPIRED Session exists but has exceeded its TTL
STEP_UP_REQUIRED Policy engine requires additional verification (WebAuthn/OTP)
SESSION_TERMINATED Policy engine has revoked this session as confidently synthetic
RATE_LIMITED Too many requests — back off and retry
NETWORK_ERROR Could not reach the CertiLayer API
TIMEOUT Request exceeded timeout_s
UNEXPECTED_ERROR Unclassified server or SDK error

Requirements

  • Python 3.9+
  • httpx (installed automatically as a dependency)

License

MIT

Support

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

certilayer-1.0.0.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

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

certilayer-1.0.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file certilayer-1.0.0.tar.gz.

File metadata

  • Download URL: certilayer-1.0.0.tar.gz
  • Upload date:
  • Size: 14.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for certilayer-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f1fef05413a5b4ee1da877446189c5a6d8251346f872ff6170b165a10b8bde25
MD5 fd887db1b49c79ed9f2e462a62ca1b12
BLAKE2b-256 ace52d0e09d8c5abf679239b53b292c8da498d003575b70948ad0cba8f8f4bff

See more details on using hashes here.

File details

Details for the file certilayer-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: certilayer-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for certilayer-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6195376814ff1bbe571eddd17ddca73f68feddbb0697b7981d9e6938bd88aa5e
MD5 d12cb70f84860fd3f48edc0104b57ea9
BLAKE2b-256 233993ceef5d4cb57853e9cbf677667e0e3d8d4f328ee564eff95074a983dfba

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 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