Skip to main content

chitmark (Python)

Official Python SDK for Chitmark: trust decisions on agent-mediated actions, tuned by business outcomes.

AI agents and multi-account farms drain free tiers, trial credits, and API allowances while looking exactly like your best customers. Chitmark scores each action in under 50 ms and returns allow, challenge, or deny: cheap for one real human, expensive at farm scale. Then your outcomes (conversion, credit burn, chargeback) come back through feedback and tune the next decision.

PyPI version

Requires Python >= 3.10. Fully typed (py.typed), synchronous httpx under the hood.

Try it without a key: run the playground. Live service health: chitmark.com/status.

Install

pip install chitmark
# or
uv add chitmark

Quick start

from chitmark import Chitmark

with Chitmark(api_key="ck_live_...") as client:
    verdict = client.verify(
        action="signup",
        session="sess_9f3a",
        surface="app.acme.com/signup",
        subject={
            "email": "buyer@acmecorp.com",  # hashed client-side before the wire
            "ip": "203.0.113.7",  # truncated to /24 client-side
            "userAgent": "Mozilla/5.0 ...",
        },
    )

# Persist verdict["eventId"] on the account row: feedback joins only on that id.

The three verbs

Method Endpoint Purpose
client.verify(...) POST /v1/verify Decide
client.feedback(...) POST /v1/feedback Learn
client.challenge(...) POST /v1/challenge Escalate

Golden rule: fail to challenge, never to allow. Timeouts and transport errors return a degraded challenge verdict (never allow, never a raised error on verify); HTTP errors raise ChitmarkApiError with the status attached.

Feedback: the data moat

Attribution is a schema contract, not a fuzzy match: store the eventId from verify on the account row, then report outcomes against that same id. Never a derived or guessed id.

# At signup: persist the join key
verdict = client.verify(action="signup", subject={"email": "a@b.com"})
db.accounts.update(user_id, chitmark_event_id=verdict["eventId"])

# Later, when a label matures:
client.feedback(
    event_id=account.chitmark_event_id,  # the stored join key: never guessed
    outcome="credit_burn",
    value=87.4,  # dollar amount: unit rides along (default "usd")
    observed_at="2026-08-06T04:00:00Z",
)

Exact duplicate feedback bodies derive the same warehouse id, so retrying a connector never double-counts a burned value. unit ships only alongside value: a currency without an amount is wire noise.

Challenges: friction priced per action

When verify returns challenge, issue one, solve the proof locally, and complete it. Proof-of-work difficulty is server-issued (4 by default, up to 6 at higher risk tiers): about 65k hashes, milliseconds for one human's device, real money at farm scale.

import hashlib

issued = client.challenge(event_id=verdict["eventId"], session="sess_9f3a")
instructions = issued["instructions"]

if instructions["type"] == "pow":
    prefix = "0" * instructions["difficulty"]
    nonce = 0
    while True:
        digest = hashlib.sha256(
            f"{issued['challengeId']}:{instructions['seed']}:{nonce}".encode()
        ).hexdigest()
        if digest.startswith(prefix):
            break
        nonce += 1

    client.complete_challenge(
        event_id=verdict["eventId"],
        challenge_id=issued["challengeId"],
        session="sess_9f3a",
        proof={"type": "proof_of_work", "nonce": str(nonce)},
    )
    # Re-verify with context={"challengeId": ...} so the next verdict honors it.

Signed verdict receipts

Every production verdict ships a verdictToken: an ES256 JWT bound to session, origin, and event. Verify it before acting on high-value decisions (install the verdict extra for the crypto dependency):

pip install "chitmark[verdict]"
from chitmark.verify_token import verify_verdict_token

claims = verify_verdict_token(
    verdict["verdictToken"],
    session="sess_9f3a",  # enforce session binding (recommended)
    aud="api.chitmark.com",  # enforce origin binding
)
# claims: {"eventId", "decision", "actorType", "confidence", "jti", "exp", ...}

Rejects expired tokens, unknown keys, bad signatures, and session or origin mismatches with typed error codes.

PII modes

Mode Behavior
hashed (default) SHA-256 email, /24 IP truncation, allowlisted form fields
none Derived/header-shape signals only
raw Tenant opt-in only; higher compliance review

Dependency injection and lifecycle

The client owns its httpx.Client by default and closes it on context exit. Pass your own for connection pooling or tests:

import httpx
from chitmark import Chitmark

pool = httpx.Client(base_url="https://api.chitmark.com", timeout=0.8)
client = Chitmark(api_key="ck_live_...", http_client=pool)

Develop

cd packages/sdk-python
uv sync --extra dev   # or: pip install -e ".[dev]"
pytest
ruff check .

Agent integration

Using Cursor, Claude Code, Codex, or another coding agent? Point it at chitmark.com/SKILL.md, or paste this into your prompt: Integrate Chitmark into my app following https://chitmark.com/SKILL.md.

Resources

License

Proprietary: see LICENSE.

Metadata

Release files for chitmark 0.5.1

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

Source distribution (sdist)

Source distribution for chitmark 0.5.1
File Size Uploaded
chitmark-0.5.1.tar.gz 19.0 kB Details

Built distribution (wheel)

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

Total release size: 33.9 kB

Release files / chitmark-0.5.1.tar.gz

Download URL chitmark-0.5.1.tar.gz
Size 19.0 kB
Tags Source
SHA-256 checksum
How to use checksums
89e235d86a825f9da5c85b395ca4a652ced708508919406ea9d60298d8bcfcfb
BLAKE2b-256 checksum
How to use checksums
9781d6a7ba5b29c3df2582c6f67aa045bc1eff0f9791b90040863ef67b2035fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / chitmark-0.5.1-py3-none-any.whl

Download URL chitmark-0.5.1-py3-none-any.whl
Size 14.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a210c26646974a16e9d77c2ada3a876b02b618ffcab60e9063cf13dcfefbac42
BLAKE2b-256 checksum
How to use checksums
88a86a3420f394f2064743a9a5a668f9b2acaecefb431d29526b4bc38127f524
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.2

2 release files

This release

0.5.1 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

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