-
-
The triage board: every dispute booked into someone's working hours before its deadline.
-
The case file: evidence checklist, a win estimate from fixed rules, and Marlow's recommendation.
-
Evidence and actions: only the actions PayPal allows right now get a button. One approval files the response.
-
Won: a $184 claim settled in the seller's favor in the sandbox, and counted as recovered.
-
A $62 inquiry closed with a $31 partial refund offer that the buyer accepted in PayPal.
-
Prevention: patterns counted across cases, with one suggested fix for each.
Live demo: https://hack-pp-disputedesk.vercel.app (PayPal sandbox; no login needed, and Replay plays recorded cases without using any up) Code: https://github.com/chinesepowered/hack-pp-disputedesk
Inspiration
A three person shop has nobody whose job is disputes. A dispute shows up unannounced, has a deadline, needs evidence from three places (PayPal, the carrier, the shop's own inbox), and is easy to answer badly. So the deadline slips, or the wrong evidence goes in, and a case the shop could have won is lost along with the goods.
PayPal's developer documentation says a buyer can open a dispute within 180 days, that buyer and seller have 20 days to settle an inquiry, and that PayPal decides a claim within 10 days on the evidence from both sides. PayPal's US fee page lists a standard dispute fee of 15.00 USD that it may charge when a claim or chargeback is filed. (Sources are listed in the README.)
We noticed that a dispute is really two problems: it is scheduled work with a deadline and an owner, and it is a money decision. Most tools treat it as an inbox item. We wanted a desk.
What it does
Dispute Desk pulls every dispute from the PayPal Disputes API onto one triage board.
- Books the work. Each dispute becomes a block on a Bryntum Scheduler board, placed in the earliest free slot before its deadline, inside each person's working hours. Drag a block to reassign it and the rest reflows. A missed block goes back to Unscheduled and is booked again.
- Builds the case. Order, capture and tracking come from PayPal (Orders, Payments, Transaction Search). Carrier scans, signature, messages and photos come from the shop's records. A vision model checks whether the delivery photo really shows a parcel at a door.
- Decides by rules. A fixed reason to evidence table scores what is present, missing or against you. The total is a win estimate, always labeled as an estimate. Fight, offer or accept comes from those rules plus an economics check (amount at stake, staff time, fee risk) and the owner's thresholds.
- Writes and files. Marlow drafts the response and builds an evidence pack PDF. Only the actions PayPal lists in the dispute's
linksget a button. One approval files it:provide-evidence,provide-supporting-info,make-offer,send-message,accept-claimorescalate. - Shows the money. When PayPal resolves a case, the desk reads the outcome and fund movements and updates "Recovered this month".
- Prevents the next one. It counts patterns across cases (two "not as described" disputes on the same planter with no size chart) and suggests one fix for each.
Marlow, the desk's clerk, is a calm capybara with reading glasses and a clipboard. Marlow has a job: persona, voice lines, loading, empty and success states.
In the demo, a $184 "item not received" claim goes from new to filed in three clicks and is settled in the seller's favor in the sandbox, and a $62 "not as described" inquiry is closed with a $31 partial refund the buyer accepts in PayPal.
How we built it
- Next.js (App Router), TypeScript, Tailwind CSS, deployed as one app on Vercel. State is JSON documents in files locally and Vercel Blob when hosted. PayPal stays the source of truth for anything about money.
- PayPal. The Disputes API v1 through plain REST (the server SDK does not cover it), with a
PayPal-Request-Idon every write.@paypal/paypal-server-sdkfor Orders, Payments and Transaction Search. Webhooks for dispute events with signature verification, plus polling so nothing depends on delivery. The PayPal JS SDK v6 on a small demo store so anyone can make a sandbox payment and dispute it.@paypal/agent-toolkitgives Marlow's agent its read tools. - One path for every write. Check the action is in
links, check amounts and thresholds, claim the filing, call PayPal, record the result. If PayPal does not answer, re-read the dispute rather than guess. - Bryntum Scheduler for the board: resources with working hours, deadline markers, an Unscheduled grid with drag onto the timeline, drag, resize, editor, tooltips and a drop validator.
- AI on W&B Inference through the Vercel AI SDK: Qwen for explanations, drafts and the tool-calling agent, Gemma for reading photos, GLM as a fallback. The model never decides money and cannot file: its tools produce proposals a person approves.
- Seeding with PayPal's own pages.
pnpm seedcreates and captures orders through the API, then logs in as the sandbox buyer with Playwright and opens each dispute through "Report a problem", so every dispute on the board is one PayPal itself created. - Replay mode. A sandbox dispute can be filed only once, so real runs were recorded (PayPal responses, debug ids and model outputs) and can be replayed per browser session, clearly labeled.
- The video is real runs of the app recorded with Playwright against the sandbox, title cards rendered from HTML, narration from ElevenLabs, composed with ffmpeg.
Challenges we ran into
All of these are in docs/build-log.md with what we saw and what we did.
- Disputes cannot be created through the API in a way we could make work, so the seed drives PayPal's buyer pages. The "Report a problem" form is a wizard that differs by reason (custom radios, a 120 character minimum, a masked date field, saved drafts).
- "Item not received" on an order that already has tracking skips the inquiry stage. PayPal moved it straight to a claim under review, with only
provide_supporting_infooffered and no seller deadline. We restructured seeding into flows and gave such cases a desk target date of our own. - Time in the sandbox is real. A dispute takes 3 to 4 minutes to appear in the list.
escalatereturns at once but the claim appears about 11 minutes later. The sandbox settle link appeared about half an hour after evidence was filed. So the desk only shows an action when PayPal lists it, and the video cuts the waits and says so. - PayPal rewrites
dispute_amountafter an accepted offer. Our first outcome screen said $0 kept. The desk now keeps the original amount. - Reasoning models that say nothing. On some prompts both text models spent their whole token budget on hidden reasoning and returned an empty answer. We measured which request option stops that for each model and use it for the writing tasks.
- Two copies of one HTTP library. The Agent Toolkit loads the CommonJS build of axios and our server bundle loaded the ES module build, so our logging saw none of the toolkit's calls in production. The drawer now logs both.
- Turbopack ran out of memory on the Scheduler bundle, so the app builds with webpack.
- A test run wiped the working desk, because the store resolved its folder at import time. The store now resolves it per call and the tests use their own folder.
Accomplishments that we're proud of
- A full, real loop in the sandbox: a buyer-opened dispute, evidence filed through the API with a PDF attached, PayPal's decision, the hold released, and the money counted, all shown with PayPal-Debug-Ids.
- The money decision is in code and tested. The model explains and writes, and every AI output is tagged with the model that produced it.
- The board is a working schedule, not a picture of one: deadlines, working hours, drag, resize, reflow, and missed work that is booked again.
- An honest demo: Replay is labeled, seeded shop records are labeled, the win estimate is labeled as an estimate, and the limitation is said out loud in the video.
What we learned
- Read
linksbefore every action. PayPal's allowed actions change with stage, status and time, and they are the only reliable guide. - Treat a webhook as a hint and PayPal as the record: re-read before showing or acting.
- Keep the model away from numbers. Rules decide, the model reads and writes.
- Small sellers do not need a dashboard. They need the next piece of work, on a calendar, with the evidence already gathered.
What's next
- Learn the evidence weights from resolved cases instead of fixed points.
- Connect real order systems and carriers for scans, signatures and photos.
- Card chargebacks and appeals on the same board.
- Sign-in per person, and a daily digest from Marlow.
Tools: which AI models and services were used and how
- Qwen/Qwen3.8-27B on W&B Inference: in the product, for explaining recommendations, drafting dispute responses, phrasing prevention cards and scheduling notes, and as the tool-calling agent.
- google/gemma-4-31B-it on W&B Inference: in the product, reading delivery and damage photos.
- zai-org/GLM-5.3-Flash on W&B Inference: in the product, the fallback text model.
- Claude Code: AI coding agent used to build the app, tests, docs and video pipeline from a written brief, with the APIMatic PayPal Context Plugin skills, working against the PayPal sandbox.
- ElevenLabs (
eleven_multilingual_v2, premade voices): the video narration and Marlow's pre-rendered voice lines. The hosted app never calls ElevenLabs. - APIMatic PayPal Context Plugin: its skills guided the PayPal integration (plan file and contract sheet, facts looked up rather than recalled, durable writes).
- Vercel AI SDK: model calls and tool calling.
PayPal products used
- Disputes API v1: list, show, provide evidence, provide supporting info, make offer, send message, accept claim, escalate, and the sandbox-only adjudicate.
- Orders API v2: create, capture, show, add tracking.
- Payments API v2: show captured payment.
- Transaction Search API.
- Webhooks:
CUSTOMER.DISPUTE.CREATED,UPDATED,RESOLVED, with signature verification. - PayPal JS SDK v6: checkout on the demo store.
- PayPal server SDK (
@paypal/paypal-server-sdk) and PayPal Agent Toolkit (@paypal/agent-toolkit). - PayPal sandbox, including the buyer's Resolution Center, which the seed drives to open real disputes.
Sponsor tools used
- Bryntum Scheduler (trial build): the triage board, which is the main screen of the product.
- APIMatic: the PayPal server SDK it generates, and the PayPal Context Plugin, used as described in the README.
Built With
- apimatic
- bryntum
- elevenlabs
- ffmpeg
- next.js
- paypal
- paypal-agent-toolkit
- paypal-disputes-api
- paypal-js-sdk
- paypal-orders-api
- paypal-server-sdk
- paypal-webhooks
- pdf-lib
- playwright
- react
- tailwindcss
- typescript
- vercel
- vercel-ai-sdk
- vercel-blob
- vitest
- weights-and-biases
- zod