KaizoCoreKaizoCore docs

Ack tokens

The server-attested, single-use credential required at the moment of checkout.

The problem an ack token solves

Even with continuous PULSE verification, there's a specific moment that matters more than any other: the instant a purchase, login, or signup is actually submitted. A detector that's watching behavior throughout the session but doesn't specifically attest to that moment leaves a gap — what stops a bot from waiting for a real user's session to look clean, then racing a submission?

The ack token closes this by making checkout (or any action you gate this way) require a fresh, server-issued, single-use credential that's only handed out when the session currently qualifies — not a general "this session is fine" flag issued once and reused.

What's in the token

A signed opaque token, HMAC-SHA256, containing:

  • session_token — which session this was issued for
  • customer_id — bound to your account, not usable cross-tenant
  • issued_at / expires_at — a 30-second TTL
  • purchase_context_hash — a SHA-256 hash of whatever context you supply (e.g. cart contents, amount) — never the plaintext, but bound tightly enough that a token issued for one purchase can't be replayed against a different one
  • nonce — consumed exactly once; a second verification attempt with the same nonce fails

The signing key is entirely separate from your pk_live_/sk_live_ request- signing keys, specifically so that a key an attacker could self-derive from your site's own HTML (the public key scheme is intentionally client- computable) can never be used to forge an ack token.

What gates issuance

POST /v1/ack-token/issue only returns a real token if all of the following hold:

  1. The session token carries a valid server signature (proof a real collect() call actually minted it, not a client-fabricated value).
  2. There's real, cached collection evidence for this session — no evidence means no token, full stop (no_collect_evidence).
  3. Cached ML confidence signals (ml_bot_prob, if_anomaly_dev) both stay under conservative thresholds (0.5).
  4. The session has sustained at least a minimum number of consecutive clean PULSE ticks — a default of 2 (roughly 8 seconds of sustained clean heartbeats), server-side adaptive and never client-supplied. This threshold rises automatically for a customer currently seeing a velocity spike (500+ requests from one IP), the same way proof-of-work difficulty adapts under load.

Failing any of these returns 403 with a specific reasoninsufficient_pulse_history, behavioral_risk_too_high, no_collect_evidence, or invalid_session_token — rather than a generic denial, so you can distinguish "this looks like a bot" from "this session just hasn't been open long enough yet" in your own UX.

Verifying a token

POST /v1/ack-token/verify checks:

  • Signature validity and expiry (30 seconds — tokens are meant to be verified immediately, not stored)
  • Customer binding
  • Purchase-context match (the hash you supply at verify time must match what was hashed at issue time)
  • Single-use enforcement via an atomic get-then-delete against a nonce store — a second verify with the same token returns nonce_already_used_or_expired, whether or not the first verify actually succeeded

What this defeats, and what it doesn't

Real, disclosed limit

The ack token raises the cost of automated checkout dramatically — a captured or replayed fingerprint, or a fast scripted submission, cannot get through without also sustaining real, clean behavioral signal for several seconds beforehand. It does not stop an attacker willing to run many real (slower) browser instances in parallel to farm tokens one at a time. That puts the attacker back in the territory PULSE and the behavioral layers are built to catch — real browser, real timing, real cost — rather than eliminating the attack entirely. See FAQ.

Same pattern as, and different from, other attestation schemes

The ack token's basic shape — a server signs a short-lived credential attesting to some real-world property, rather than trusting the client's own claim — is the same category of pattern as Apple App Attest, Google's Web Environment Integrity, or Cloudflare Turnstile. The token itself is delivery plumbing; the actual product is the decision logic (PULSE history, ML confidence, collect-evidence) that decides whether to issue it.

On this page