Skip to content

Built on PayPal

Your AI agent pays.You keep signed proof.

Behest checks each purchase against a mandate you signed, pays through PayPal only inside it, and signs a receipt any seller can verify.

PayPal sandbox only. No real money moves.

Purchase from Ravi's Spice Co.

Spice gift box

Status: Paid$40.00

Held because $40.00 is over your $25.00 approval limit. You approved it at PayPal, and it was paid.

  1. Step 5, Receipt: done

    Signed receipt

    eyJhbGciOiJFZERTQSIsImtpZCI6IjBmOGIxZTExZmJhMjg0ZWQiLCJ0eXAiOiJiZWhlc3QtcmVjZWlwdCtqd3MifQ.eyJjYXJ0Ijp7ImN1cnJlbmN5IjoiVVNEIiwiaGFzaCI6IjNlMWYzNmIy...Y2VzIn0sInYiOjF9.mXZWo-FYq9uFx38v3-dMcBMrkVfLvF3e8Ii7LtS668ohcjNqJCKobkQ2X504Vu7c9KsUDMHemD6tmoZmfPu5CA

A sample purchase, signed with a throwaway key. Open any step to see its proof.

01How it works

Every purchase takes five steps.Each one leaves proof.

  1. 01

    Mandate

    You write

    “$60 a month on groceries and spices, ask me above $25, never electronics”

    Behest reads it back

    • Your agent can spend up to $60.00 per calendar month (UTC).
    • Purchases over $25.00 need your approval.
    • Allowed categories: groceries, spices.
    • Never: electronics.

    You say what your agent may buy in plain words. Code reads the policy back to you, and Behest signs it when you confirm.

  2. 02

    Gate

    1. Passbudget_remaining$40.00 fits in the $41.25 left this month
    2. Askask_threshold$40.00 is over your $25.00 approval limit
    3. Blockcategory_allowedelectronics is not allowed by your mandate

    Twelve deterministic rules check every cart against the signed policy. No model takes part.

  3. 03

    Intent check

    • Verdict: AllowedbecomesVerdict: Allowedwhen the check finds consistent
    • Verdict: AllowedbecomesVerdict: Needs approvalwhen the check finds needs_human
    • Verdict: Needs approvalbecomesVerdict: Blockedwhen the check finds inconsistent

    Claude compares the cart with what you asked for. It can move a verdict toward you, never away.

  4. 04

    PayPal

    Verdict: Allowed

    Charged to your saved PayPal wallet

    No click from you, inside the mandate.

    Spice gift box$40.00

    $40.00 is over your $25.00 approval limit

    An allowed purchase is charged to your saved PayPal wallet. One that needs you waits until you approve it at PayPal.

  5. 05

    Receipt

    eyJhbGciOiJFZERTQSIsImtpZCI6IjBmOGIxZTExZmJhMjg0ZWQiLCJ0eXAiOiJiZWhlc3QtcmVjZWlwdCtqd3MifQ.eyJjYXJ0Ijp7ImN1cnJlbmN5IjoiVVNEIiwiaGFzaCI6...In0sInYiOjF9.mXZWo-FYq9uFx38v3-dMcBMrkVfLvF3e8Ii7LtS668ohcjNqJCKobkQ2X504Vu7c9KsUDMHemD6tmoZmfPu5CA

    • Header
    • Payload
    • Signature
    • EdDSA, key 0f8b1e11fba284ed

    Behest signs an Ed25519 receipt binding the mandate, the cart, every rule result and the capture. The seller verifies it.

02Security

We attacked it the wayagents get attacked.

Attacks replayed against every layer
8
Stopped in the live run, out of 8
7
Model calls in the live run
38
What the live run cost, estimated
$0.31

In January 2026, researchers showed that a few sentences in a product listing steer shopping agents built on Google's Agent Payments Protocol, even with a signed mandate. Behest replays that attack against each of its layers and publishes what each one did, including what got through.

arXiv 2601.22569

See every attack, layer by layer
  • The gate decides.

    Allow, ask or block comes from plain TypeScript rules. No model can approve a purchase.

  • Models only tighten.

    The intent check can turn allow into ask or block, never the reverse. A check that cannot run sends the purchase to you.

  • Outside text is quoted data.

    Listings, search results and market prices reach a model only inside quoted blocks, and a listing that addresses AI agents is hidden from them.

  • Retries never double charge.

    Every PayPal call that moves money carries a request id made from the purchase, so PayPal answers a repeat with the first result.

03Built on PayPal

Every step that moves moneyruns through PayPal.

Behest is the merchant of record: a saved wallet can only pay the business that saved it, so Behest takes the payment and pays the seller out.

  • Vault v3 saved wallets

    /v3/vault/payment-tokens

    1. Mandate signedsetup token created
    2. Approved at PayPalby the buyer, once
    3. Wallet savedpayment token
    4. Charged, no clickvault_id

    The buyer saves their PayPal wallet once, with no purchase, while signing the mandate. Allowed purchases charge it with no click.

  • Orders v2

    /v2/checkout/orders

    • COMPLETEDCaptured
    • PENDINGCaptured, settling
    • DECLINEDNo money moved

    Creates and captures every order: charged to the saved wallet when allowed, approved by the buyer at PayPal when held.

  • Payouts

    /v1/payments/payouts

    • PENDINGPolled again
    • SUCCESSSeller paid
    • RETURNEDAn operator settles it

    Pays the seller once it has verified the receipt and accepted the order, and polls the payout until PayPal settles it.

  • Refunds

    /v2/payments/captures/{id}/refund

    refund $40.00ofcapture 3GG2...4321

    request id b7d2f0c4...:refund

    The request as it would go for the sample purchase

    Refunds the buyer from Behest’s capture when a seller rejects the order, once, under the purchase’s own request id.

  • Disputes with evidence

    /v1/customer/disputes

    • mandate
    • readback
    • receipt
    • cart
    • decision
    • purchase_log
    • approval
    • tracking

    Matches each dispute to its purchase and answers it with the operator’s reviewed narrative, citing these evidence items.

  • Webhooks

    /v1/notifications/verify-webhook-signature

    Signature verified
    • CHECKOUT.ORDER.APPROVED
    • PAYMENT.CAPTURE.COMPLETED
    • PAYMENT.CAPTURE.DENIED
    • PAYMENT.CAPTURE.REFUNDED
    • PAYMENT.CAPTURE.REVERSED
    • CUSTOMER.DISPUTE.CREATED
    • CUSTOMER.DISPUTE.UPDATED
    • CUSTOMER.DISPUTE.RESOLVED
    • PAYMENT.PAYOUTS-ITEM.SUCCEEDED
    • PAYMENT.PAYOUTS-ITEM.FAILED

    Acts on an order, capture, refund, payout or dispute event only after PayPal confirms its signature.

  • Agent Toolkit, read only

    @paypal/agent-toolkit

    • list_disputes
    • get_dispute
    • get_order
    • get_shipment_tracking

    Gives the dispute evidence agent these four tools and no other.

04Receipts

Every paid purchasegets a signed receipt.

This is the sample purchase's receipt, decoded. A seller checks it before accepting the order; so can anyone else.

How a seller verifies it

  1. 1Fetch Behest's public keys from /.well-known/jwks.json.
  2. 2Check the Ed25519 signature with the key the header names, and that the type is behest-receipt+jws.
  3. 3Compare the cart hash and the amount with the order received, and the seller with yourself.
  4. 4Or post the receipt, the cart and your seller slug to /api/receipts/verify. It answers with the payload, or with the check that failed.

This sample was signed with a throwaway key, 0f8b1e11fba284ed, so it verifies against the key set beside it in lib/demo/sample-receipt.json, not against the live one.

Signed receipt

eyJhbGciOiJFZERTQSIsImtpZCI6IjBmOGIxZTExZmJhMjg0ZWQiLCJ0eXAiOiJiZWhlc3QtcmVjZWlwdCtqd3MifQ.eyJjYXJ0Ijp7ImN1cnJlbmN5IjoiVVNEIiwiaGFzaCI6IjNlMWYzNmIyNTIwNTc2MmViZmJmNmNkOTdjZWM1Mjk0ODI5N2EzZDY1ZTRlOWRmNTZlZGFhMWMyMDU0YjhlNGMiLCJpdGVtQ291bnQiOjEsInRvdGFsQ2VudHMiOjQwMDB9LCJkZWNpc2lvbiI6eyJhcHByb3ZlciI6Imh1bWFuIiwib3V0Y29tZXMiOlt7InJlc3VsdCI6InBhc3MiLCJydWxlIjoibWFuZGF0ZV9hY3RpdmUifSx7InJlc3VsdCI6InBhc3MiLCJydWxlIjoiY2FydF92YWxpZCJ9LHsicmVzdWx0IjoicGFzcyIsInJ1bGUiOiJjYXRlZ29yeV9hbGxvd2VkIn0seyJyZXN1bHQiOiJwYXNzIiwicnVsZSI6InNlbGxlcl9hbGxvd2VkIn0seyJyZXN1bHQiOiJwYXNzIiwicnVsZSI6Imxpc3RpbmdfY2xlYW4ifSx7InJlc3VsdCI6InBhc3MiLCJydWxlIjoicGVyX3B1cmNoYXNlX21heCJ9LHsicmVzdWx0IjoicGFzcyIsInJ1bGUiOiJidWRnZXRfcmVtYWluaW5nIn0seyJyZXN1bHQiOiJwYXNzIiwicnVsZSI6InZlbG9jaXR5In0seyJyZXN1bHQiOiJhc2siLCJydWxlIjoiYXNrX3RocmVzaG9sZCJ9LHsicmVzdWx0Ijoic2tpcCIsInJ1bGUiOiJwcmljZV9iZW5jaG1hcmsifSx7InJlc3VsdCI6InBhc3MiLCJydWxlIjoicXVhbnRpdHkifSx7InJlc3VsdCI6InBhc3MiLCJydWxlIjoid2FsbGV0X2xpbmtlZCJ9XSwicHVyY2hhc2VJZCI6ImI3ZDJmMGM0LTFlMmEtNGM1NS04ZDBlLTZhOWYzYjFjMmQ0ZSIsInJ1bGVzZXRWZXJzaW9uIjoiZ2F0ZS12MSIsInZlcmRpY3QiOiJBU0sifSwiaWF0IjoxNzk0MDYwMTMxLCJpZCI6IjBmOGU2YTFjLTUyZDQtNGYyNy05YTNiLTdjMWRlMGI0ZTIxYiIsImlzcyI6ImJlaGVzdCIsIm1hbmRhdGUiOnsiaWQiOiI1YzFlOWE3ZC0zYjJmLTRlNjEtOWQwOC0yYTdmNGM2YjFlMzAiLCJqd3NIYXNoIjoiODljYWFhZTNkYjg1MDEwNDNiNTY2OGNjZDZlZTBmNzIwYTE5MjFhMmJiMWExYmZhYThmYWU2OGU0Y2FjMTQ3MiIsInBvbGljeUhhc2giOiJkMDQzNDNmN2Y3NjRkY2YxNmFjMWYyZmIwZDczMTBlN2JhOTUwZjNmZGNlYmFhMWRjZjkwODNiMTZjZGNiYzEwIn0sInBheW1lbnQiOnsiYW1vdW50Q2VudHMiOjQwMDAsImNhcHR1cmVJZCI6IjNHRzI3OTc1VVI3NjU0MzIxIiwiY2FwdHVyZWRBdCI6IjIwMjYtMTEtMDdUMTQ6MDI6MTEuMDAwWiIsIm9yZGVySWQiOiI4TUM1ODc0NVlLMTIzNDU2NyIsInByb2Nlc3NvciI6InBheXBhbCJ9LCJzZWxsZXIiOnsic2x1ZyI6InJhdmktc3BpY2VzIn0sInYiOjF9.mXZWo-FYq9uFx38v3-dMcBMrkVfLvF3e8Ii7LtS668ohcjNqJCKobkQ2X504Vu7c9KsUDMHemD6tmoZmfPu5CA

Payloadkey claims
Amount
$40.00
Verdict
Verdict: Needs approval
Approved by
The buyer, at PayPal human
Mandate policy hash
Mandate policy hash: d04343f7f764dcf16ac1f2fb0d7310e7ba950f3fdcebaa1dcf9083b16cdcbc10
PayPal capture id
PayPal capture id: 3GG27975UR7654321
Seller
ravi-spices

05FAQ

Fair questions.Straight answers.

  • Only in passing. A saved PayPal wallet can only pay the business that saved it, so Behest is the merchant of record: each purchase is paid into Behest’s PayPal account, and Behest pays the seller through Payouts once the seller verifies the receipt and accepts the order, or refunds you if they reject it. This demo runs on the PayPal sandbox, so no real money moves.
  • Without one, your signed-in session confirms the mandate. With one, your passkey signs the mandate’s policy and readback hashes with you present, and the signed mandate names that passkey and its public key, so anyone can check the signature from the mandate alone, without trusting Behest.
  • Nothing is bought that you did not allow. The gate is plain code and needs no model. If the intent check cannot run, or hits its spending cap, the purchase comes to you for approval. If the shopping agent cannot run, it stops and buys nothing, and if the mandate compiler fails, nothing is signed.
  • No. Receipts are signed with Behest’s Ed25519 key, which no seller has, and the signature covers the cart hash, the amount, the seller and every rule result. Change any of it and the signature no longer verifies against the public keys at /.well-known/jwks.json. Each receipt is also accepted once, so a replay is refused.
  • Google’s AP2 standard, which PayPal supports, also signs mandates. A signature records what you allowed; it does not stop an agent being talked into something inside it. Behest adds a deterministic gate that checks every purchase against the mandate, keeps listing text away from the model as quoted data, and turns the same signed records into dispute evidence.
  • A listing that tells agents to choose it, at a price the mandate allows, is only partly covered. A listing's category is written by a model from seller text, so a dishonest seller can list earbuds as spices. Spend caps are checked, not reserved. There is one signing key, not yet rotated. The README lists every known limitation.

06Try it

Pick a role.Run the demo.

No sign-up. Each role opens its own pages, and everything runs against the PayPal sandbox.