Skip to content
MOLTBOUNDAI AGENT CHECKOUT RAILMoltbound home Sandbox

Approval guarantees

Every rule, and how to check it.

These are the rules Moltbound enforces on every approval. Each one has an automated test that runs before every release, and you don't have to take our word for it: an agent can try each attack itself, with no browser or passkey, using the simulated human. This is a sandbox: partners are fictional and purchases are simulated.

01Only a person can approve

Agents can ask, never approve. Approving needs the person's passkey on Moltbound's own page (frame-ancestors 'none'). An agent credential on any approval route is refused.

Try:
Approve with the agent's own token
You get:
HTTP 403 principal_session_required (passkey flow) · HTTP 401 invalid_sim_human_token (simulated human)
Test:
ia1.test.ts T1 · guarantees.test.ts G5

02One approval buys once

Each approval is single-use. Repeating the purchase call returns the same purchase; nothing is bought twice.

Try:
Send the purchase twice
You get:
HTTP 202 with the same purchase_id
Test:
guarantees.test.ts G1

03Tied to the exact quote

An approval covers one quote, one agent and one mandate. It can't be moved to a cheaper, dearer or different quote.

Try:
Use the approval for a different bid
You get:
HTTP 403 consent_mismatch (before use) · HTTP 403 consent_used (after use)
Test:
guarantees.test.ts G2 · ia1.test.ts

04Invisible to other agents

Another agent, session or person can't see an approval, let alone use or approve it.

Try:
Use or approve it from another session
You get:
HTTP 404 not_found
Test:
guarantees.test.ts G3

05Short-lived

Unanswered requests expire after 15 minutes. An approval must be used within 15 minutes, then it expires.

Try:
Buy after the window
You get:
HTTP 403 consent_expired
Test:
v73-followup.test.ts

06Refusal wins

If the person says no, the request is closed for good. What an agent claims in chat counts for nothing: only the decision on Moltbound's page counts. Saying no needs no passkey, so it is never harder than saying yes.

Try:
Approve after a decline
You get:
HTTP 409 consent_request_denied
Test:
guarantees.test.ts G4 · receipt-v2.test.ts

07The passkey signs over what was shown

The passkey challenge is built from a fingerprint of the exact approval screen: price, partner, deductibles, exclusions, cooling-off and wording. If the quote changes after the request, the approval fails and the person is asked again.

Try:
Change the terms after the request
You get:
Digest mismatch: a new approval is required
Test:
ia1.test.ts

08The receipt records what was approved

Every receipt holds the quote id, the approval screen fingerprint and a salted fingerprint of the quote details, signed and kept in a tamper-evident log. The person and their agent can download the screen and recompute both fingerprints.

Try:
Alter a receipt
You get:
POST /kapi/receipts/verify reports it as altered
Test:
receipt-v2.test.ts · v77-signed-receipts.test.ts

09A no is recorded too

A decline is signed and logged like an approval (decline record, id rdec_…), so there is proof of the no as well as the yes.

Try:
Deny a decline happened
You get:
The decline record verifies at /verify
Test:
receipt-v2.test.ts · guarantees.test.ts G4

Check it yourself (agents)

  1. POST /kapi/sandbox/human-sim/start with an email you can read, then POST /kapi/sandbox/human-sim/verify with the 6-digit code. You get a session_token (you, the agent) and a sim_human_token (the simulated person).
  2. Get quotes, then POST /kapi/sandbox/sessions/<id>/approval-request for one bid.
  3. Play the person with POST /kapi/sandbox/human-sim/approve or /decline, then try the attacks above.
  4. After the decision, GET /kapi/bind-consent-requests/<id> returns the approval screen, the quote details and their salt. Recompute sha256(canonical_json(disclosure)) and sha256(salt + ":" + canonical_json(inputs)) and compare them with the receipt.

Full steps and expected errors: /llms.txt · Check a receipt: /verify · More on data and keys: /security