Inspiration

For a small online shop, one PayPal dispute can cost more than the order. Lose a claim and PayPal keeps a $15 fee on top of the refund. Once claims pass 1.5% of sales, every claim costs $30, even the ones you win. The seller usually has ten days to answer, and Seller Protection only helps if the order went to the address on the PayPal payment, with the right proof. Small sellers rarely know these rules, so they refund cases they would have won and fight cases they were always going to lose. I wanted an agent that knows PayPal's rules, does the reading, the arithmetic and the writing, and leaves the decision with the seller.

What it does

Truce handles a shop's PayPal disputes from start to finish:

  • Syncs the disputes from PayPal, live, every night, and on every webhook.
  • Reads each case. It gathers the evidence: the order and the PayPal payment, the tracking, the listing as the buyer saw it, the shop's policies, the messages, the buyer's photos and similar past cases. It checks Seller Protection rule by rule.
  • Prices every move. For fight, settle and refund it works out the expected loss, the worst case, PayPal's dispute fee, and whether the move counts toward the claims ratio.
  • Recommends one, with reasons. Every reason cites its evidence (E1, E2…). If it doesn't pick the cheapest move, it has to say why.
  • Drafts the reply and checks it. The draft is a message, an offer, a refund note or the evidence for PayPal's reviewer. Every factual sentence is checked against the evidence before the seller sees it.
  • Answers through PayPal on approval. One tap sends it through the Disputes API: a message, a partial-refund offer, a refund, or proof of fulfillment with a PDF of the order and every scan.

Around that:

  • Prevention. Before an order ships, Truce compares the label with the address on the PayPal payment. A different address voids Seller Protection, so Truce drafts a kind note asking the buyer to update it in PayPal first.
  • Ask Truce, each shop's home, is a chat with eight tools: "Which case should I deal with first?", "Why did we lose the mug dispute?". Told "Refund Chris and say sorry", it prepares the refund as a card the seller approves.
  • Shop health shows what Truce has kept, the fees avoided, the claims ratio against PayPal's line, and the patterns behind the shop's disputes, with how to prevent them.

To try it, sign up and open the sample shop, Wick & Ember: your own copy, with about 240 orders and five open disputes that each need a different move. Or connect your own PayPal REST app, sandbox or live.

How it uses PayPal

PayPal is the core, not a checkout button. Truce talks to each seller's own PayPal REST app:

Feature PayPal
Connect a shop OAuth client credentials with the seller's own app. The token's scopes say what Truce can do (disputes, Transaction Search, tracking); the secret is sealed with AES-256-GCM
Sync disputes Customer Disputes v1, listing and fetching the ones that changed; each shop's CUSTOMER.DISPUTE.* webhook, accepted only after verify-webhook-signature
The evidence Payments v2 captures (Seller Protection status, the order), Orders v2 (items, the address on the payment, trackers) and shipping trackers
The claims ratio Transaction Search: the last 90 days of sales
Answer send-message, make-offer, accept-claim, provide-evidence (multipart, with a PDF) and provide-supporting-info, each checked first against the dispute's own links and allowed_response_options
Prevent The address on the PayPal payment checked against the label before shipping, and tracking added to the PayPal order
Demo storefront Orders v2 with PayPal checkout buttons, taking real sandbox payments

Fees, deadlines, the claims ratio and Seller Protection come from PayPal's published rules, as tested code.

How I built it, and the AI tools

NVIDIA Nemotron on Nebius Token Factory, routed by difficulty, through the stock openai SDK with my own tool loop:

Step Model Why
Triage, gather (with tools), weigh the evidence Nemotron 3.5 Lightning Fast and cheap: about 0.5 s a call
Read the buyer's photos Nemotron 3.5 Super VL, thinking on Reads a ruler or a crack in a photo
Draft, and the Ask Truce chat Nemotron 3.5 Super VL Good writing, sees the photos, quick tool use
Decide fight, settle or refund Nemotron 3 Ultra, thinking on The hardest judgement
Check every sentence of the draft Nemotron 3 Ultra A strict reader
Find similar past cases Qwen3 Embedding 8B Embeddings, cached
  • Tavily reads the listing and the shop's policies from the shop's own website, as evidence that cites its page.
  • Structured answers come back as forced tool calls with zod schemas, validated across fields: every cited evidence ID must exist, and a move other than the cheapest needs a reason.
  • The models never do the arithmetic. Code computes each move's cost and hands it over; the model has to argue from it. Code also checks every amount and tracking number in a draft.
  • Safe by design. Buyer text reaches the models fenced as untrusted data. Nothing a model writes reaches the buyer or PayPal without the seller's tap.
  • Everything streams: each analysis step, each tool call, the draft as it's written, and the cost of every call. A whole case costs about 1.3¢.
  • Stack: Next.js 16 and React 19 on Google Cloud Run, Firebase Authentication, Firestore, Cloud Scheduler for the nightly check, and Secret Manager. Over 400 tests.

Challenges I ran into

  • The PayPal sandbox. Sandbox disputes are opened by hand from a buyer account and reach the API about seven minutes later, already as claims. The unauthorized reason code is spelt UNAUTHORISED, and the sandbox-only adjudicate call answered ACTION_NOT_ALLOWED_IN_CURRENT_DISPUTE_STATE. The sample shop simulates PayPal's side so anyone can see a whole case play out.
  • Answering the right way. Each dispute only allows certain answers at each stage, so every approval maps to exactly one call, checked against the dispute's own links and allowed_response_options first.
  • Keeping the numbers exact. A model can't be trusted with fees and deadlines, so every figure comes from code.

Accomplishments that I'm proud of

  • A complete product: sign-up, onboarding with a real PayPal connection, a sample shop anyone can try, approvals that go through PayPal's API, prevention before shipping, the overnight check, chat and shop health.
  • The right call on all five sample cases, each a different move: fight with tracking, settle for $10, fight with proof for PayPal, refund by the shop's own policy, and refund when there's no proof of delivery.
  • About 1.3¢ a case, so Truce can charge a flat price instead of a cut of what it wins.

What I learned

PayPal's rules reward preparation: the right address and the right tracking at shipping time decide most disputes before they start. And an agent becomes trustworthy once it can't touch the numbers and can't act without approval.

What's next for Truce

One-click PayPal connect (partner onboarding), carrier tracking APIs for real scan data, email notifications, and billing at a flat price: never a cut of what the seller wins.

Built With

  • cloud-firestore
  • cloud-scheduler
  • firebase-authentication
  • google-cloud-run
  • nebius-token-factory
  • next.js
  • nvidia-nemotron
  • paypal
  • paypal-checkout
  • paypal-disputes-api
  • paypal-orders-api
  • paypal-rest-api
  • qwen3-embedding
  • react
  • secret-manager
  • tailwind-css
  • tavily
  • typescript
  • vitest
  • zod
Share this project:

Updates

Submission history