SandboxSandbox only. No real money. Seeded catalog. Simulated carrier.
SafePayAI
About 10 minutes · PayPal sandbox · test funds

Run the demo.
Every role, start to finish.

A guided path through the buyer, merchant, operator and reviewer screens. Each step says who to sign in as, where to go, and who acts: PayPal, the AI, the rules or a person.

What you are looking at

A buyer signs a spending mandate that sets what may be bought, and an AI agent drafts carts inside it but never pays. When an order is late or lost, plain rules decide the refund, and a person handles anything unusual. PayPal's sandbox takes the payment and sends the refund.

Before you start

Sandbox only

No real money moves. Every payment and refund is a PayPal sandbox test.

Slow first request

The backend sleeps when idle. The first request can take 30 to 45 seconds. The app shows a waking-up notice. Do not stop; it will continue on its own.

To pay: a sandbox buyer

You need a PayPal sandbox personal (buyer) account. In developer.paypal.com go to Apps & Credentials, Sandbox, Testing Tools, Sandbox Accounts, Personal. A business account cannot be the buyer. Use those sandbox details only on PayPal's own page. They never go on this site.

The walkthrough

Switching roles

Each account has one role. To change role, sign out from the top bar, then use the sign-in button in the next step. Seeded accounts need the deployment to have them switched on; if the picker says they are off, use Create account or Try the demo for the buyer steps.
  1. Buyerbuyer-alex

    A buyer signs a mandate

    Sign in as
    Sign in as buyer-alex
    Open
    /mandate/new
    Do
    1. Fill in the cap, the per-cart limit, the shops in scope and the end date.
    2. Choose Preview terms and read the terms back.
    3. Choose Sign mandate before the signing window runs out. If it expires, preview again.
    You see
    A signed mandate with its terms. Nothing can be bought outside it.

    Notice · A personYou sign. No one else can authorise spending.

  2. Buyer

    State what you need, in words

    Sign in as
    Stay signed in from the step before.
    Open
    /intent
    Do
    1. Type what you want, for example a pair of headphones under a price you set.
    2. Choose Propose cart.
    You see
    A draft cart from the seeded catalog, with every rule check listed. If the agent fails or is unsure you get a form instead.

    Notice · AIThe AI drafts. Rules check the draft against your mandate. The AI cannot approve or pay.

  3. Buyer

    Approve the cart and pay at PayPal sandbox

    Sign in as
    Stay signed in from the step before.
    Open
    /cart/<id>, opened from your draft
    Do
    1. On the cart, choose Approve cart. You are sent to the PayPal sandbox.
    2. Sign in there with your own sandbox personal (buyer) account and approve the payment.
    3. You land on the Back from PayPal page. Choose Check payment if it still says pending, then Track order.
    You see
    A captured order with its PayPal sandbox order and capture ids on the receipt.

    Notice · PayPalPayPal's sandbox creates and captures the order. Test funds only.

  4. Merchantmerchant-trailhead

    The merchant ships it

    Sign in as
    Sign in as merchant-trailhead
    Open
    /merchant
    Do
    1. Sign in as the merchant that owns the item in your cart (merchant-trailhead, merchant-hearth or merchant-pixelwire). Sign out of the buyer first.
    2. Paste the buyer's mandate id (it is in the address of /mandate/<id>) and choose Show orders.
    3. Choose Ship this on the order. Set the outcome profile to late, then choose Mark shipped.
    You see
    A shipment labelled SIMULATED CARRIER, with a promised date.

    Notice · RulesThe carrier is our own simulated clock, not real carrier or PayPal data.

  5. Operatoroperator

    The operator makes it late

    Sign in as
    Sign in as operator
    Open
    /ops
    Do
    1. In the Demo clock panel choose +7 days (use +1 day to go in steps).
    2. Watch the cases list below fill in.
    You see
    The simulated clock moves past the promised date. The late-order detector opens a case.

    Notice · RulesA deterministic detector opens the case, not a person and not the AI.

  6. Buyerbuyer-alex

    The buyer accepts the refund offer

    Sign in as
    Sign in as buyer-alex
    Open
    /home
    Do
    1. Open the active case from your home page.
    2. Read why the rules made the offer, then choose Accept offer.
    3. If the refund is held, sign in as the operator, open /ops and choose Unfreeze refunds, then confirm.
    4. If the app asks for your approval, follow the approve link it shows.
    You see
    The case moves to a refund. It goes out through PayPal's refund API and is merchant-funded.
    1. Protected
    2. Problem found
    3. Offer
    4. Decision
    5. Resolved

    Notice · PayPalThe rules set the amount. PayPal's refund API sends it, in the sandbox.

  7. Reviewerreviewer-demo

    A reviewer decides what the rules could not

    Sign in as
    Sign in as reviewer-demo
    Open
    /review
    Do
    1. Open a case from the queue, if there is one.
    2. Choose a decision (propose a refund, propose a reship, decline or close), add a note and submit.
    You see
    The case leaves the queue with your note attached. An empty queue means the rules decided everything so far.

    Notice · A personA person decides unusual cases. A refund the reviewer proposes still needs the buyer's approval.

  8. Any signed-in role

    Read the hash-chained log

    Sign in as
    Stay signed in from the step before.
    Open
    /audit
    Do
    1. Open the audit log and run the chain check.
    You see
    Every money action in order, each entry carrying the hash of the one before it.

    Notice · RulesThe log is append-only. The check re-reads the chain.

Who is who

Seeded accounts, their role and what they can do
AccountRoleWhat it can do
buyer-personaBuyerHas a signed mandate, four orders, a refund and open cases to look through.
buyer-alexBuyerStarts empty. Sign a mandate, state a need, pay, report a problem.
merchant-trailheadMerchantShips that shop's orders on the simulated carrier.
merchant-hearthMerchantShips that shop's orders on the simulated carrier.
merchant-pixelwireMerchantShips that shop's orders on the simulated carrier.
operatorOperatorMoves the simulated carrier clock and holds or releases the refund kill switch.
reviewer-demoReviewerDecides cases the rules hand to a person.

Run it yourself

Whole stack with Docker
cp .env.example .env
# edit .env: add your PayPal sandbox client id and secret
docker compose up
  • Put your PayPal sandbox client id and secret in .env. Never commit that file.
  • Optional: add a Gemini or Groq key to let the AI draft carts. Without one the app falls back to the plain form.
  • Create the seeded accounts with services/api-gateway/scripts/seed.py. It reads the SEED_* password variables you set yourself.
  • To show the seeded-account picker set PS_APIGATEWAY_DEMO_PERSONA_LOGIN=true on the gateway.
  • Open http://localhost:3000.
Web app only
cd services/web
pnpm install
pnpm dev

Copy .env.example to .env.local and point PS_WEB_GATEWAY_INTERNAL_URL at a running gateway. The app is at http://localhost:3000.

Honest limits

Simulated carrier · sandbox
  • Sandbox only. No real money moves and no real PayPal account is used.
  • The catalog is seeded, not a live marketplace.
  • Carrier and delivery status is simulated by our own clock. It is not real carrier or PayPal data.
  • The AI classifies and drafts only. On any error or low confidence it hands the case to a person.
  • Refunds are merchant-funded, via PayPal's refund API.
  • Not affiliated with or endorsed by PayPal.

Ready?