# Summarize Open PayPal Disputes

Yes. An agent reads open PayPal disputes and writes disputes.md with the amount, reason, deadline and evidence requested.

[Run this on Rush](https://cloud.getrush.ai/run/dispute-report/paypal/).

## What the agent does

This run has no repository. PayPal enters through the connection in Rush's connector catalog: official MCP server, version 1.8.0 in that catalog, remote URL https://mcp.paypal.com/mcp, OAuth. PayPal's own docs separate sandbox and production. Sandbox streamable HTTP is https://mcp.sandbox.paypal.com/http and production is https://mcp.paypal.com/http. The catalog URL is the production host. Connect with POST /me/connections, type mcp, the URL you mean to read, auth mode oauth, and complete authorize_url in the console as the person who created the key. Name that connection on the session. The run gets no other connection, and a token is never returned by the API.

The PayPal agent toolkit lists three dispute tools: list_disputes (a summary of open disputes), get_dispute (the detail of one dispute) and accept_dispute_claim. The prompt allows the first two and forbids the third, and it also forbids any other write: no create_refund, no send_invoice, no cancel_subscription. The agent calls list_disputes, then get_dispute for each id in that summary. Detail fields are copied from the get_dispute payload: amount, reason, status, the response deadline if the payload has one, and the evidence the case is asking for. A field the payload does not contain is written as not returned. The related transaction is taken from that same payload, and list_transactions is used only when the dispute detail names a transaction id that list_disputes did not already include.

Order is by response deadline, soonest first. A dispute with no deadline sorts last and is labeled, so a missing date cannot hide at the top or the bottom by accident. Each dispute is its own section in disputes.md: id, amount and currency as returned, reason, status, deadline, transaction id, evidence requested, and the tool call that supplied the section. The agent does not accept a claim, escalate a case, or post evidence. Reading is the whole job.

If list_disputes returns no rows, the file says there are no open disputes and stops. It does not call get_dispute with a guessed id, and it does not list closed disputes to fill the page. The PayPal toolkit's invoice and subscription tools are loaded on a connection that uses the full tool set; they are out of scope here, which the transcript makes checkable.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Use the PayPal connection to list open disputes with list_disputes, then get_dispute for each. Write disputes.md with one section per dispute: amount, reason, status, the response deadline, the related transaction and what evidence is requested, ordered by deadline. If a field is absent, write that it was not returned. If a deadline is missing, sort that dispute last. Read only. Do not call accept_dispute_claim, create_refund, send_invoice, or any other tool that changes the account.",
  "connections": [
    "paypal"
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

disputes.md is a session artifact. Its download url is on the session object, expires in an hour, and is replaced when the session is read again. The webhook's result field is the closing summary (how many open disputes, which deadline is soonest), capped at 16 KiB, so the per-dispute sections live in the file. A merchant with a long case list still gets every section, because the artifact is the file itself, not the truncated result.

Review is a comparison of one section to one get_dispute result in the transcript. call_id joins the tool_use to the tool_result. The reviewer checks the amount and the deadline against that JSON, checks that accept_dispute_claim does not appear, and checks the sort: soonest deadline first, missing deadlines last. Evidence text is quoted from the payload, not paraphrased into a document the seller does not actually have to upload.

A person responds in PayPal. The file is the queue. After they upload evidence, a follow-up on the same session can re-read list_disputes; the sandbox is still parked with the previous file, and the new turn writes an updated disputes.md. That follow-up is a new message, POST /o/{org}/sessions/{id}/messages, sent only once status has left running, or the API answers 409 TURN_ACTIVE.

## Run it on every weekday morning

Your server POSTs this session each weekday morning. The Idempotency-Key is the calendar date in the merchant's zone, so a duplicate cron tick returns the run already started instead of opening a second read of the same dispute list. Use a new key the next day; a completed run keeps its key.

The API key's webhook_url receives run.completed with session_url. Signature check first (Standard Webhooks, the whsec_ secret returned once when the URL was set). Then download disputes.md and route it to whoever answers cases. run.failed means no file; do not treat a missing webhook as an empty dispute list. After the third retry (2, 4 and 6 minutes) an undelivered event is dropped, and session_url is how you catch up.

## Why run it on Rush?

Open disputes have deadlines, and the toolkit that can list them can also accept a claim. On a laptop those tools sit next to a PayPal access token. On this run the prompt names the two read tools and names accept_dispute_claim as forbidden, the sandbox has no other copy of the account, and the connection is the only one the key run is given. Sandbox versus production is which URL you connected, which is a choice made before the run, not a flag inside the prompt.

The record is the pair of list_disputes and each get_dispute, stored as transcript events. When a section looks wrong, the payload is still there. You can run the same morning job for more than one PayPal connection by starting more than one session, up to the key's max_concurrent of 4, with 429 past that. Sessions do not share a dispute list.

## Frequently asked questions

### Can the agent accept the dispute or upload evidence?

Not on this request. accept_dispute_claim is the toolkit's write for a dispute, and the prompt forbids it along with refunds and invoice sends. The file tells a person what evidence was requested. Uploading that evidence stays in the PayPal resolution center, or in a later run whose prompt says to write.

### How do I point this at the PayPal sandbox?

PayPal documents the sandbox host as https://mcp.sandbox.paypal.com and the production host as https://mcp.paypal.com. The catalog entry is https://mcp.paypal.com/mcp. Create the connection against the sandbox URL, finish the OAuth sign-in, and name that connection. A production name and a sandbox name should not be the same, or the call is 422 CONNECTION_AMBIGUOUS.

### What if the deadline field has a different name in the payload?

The agent copies the deadline from whatever field get_dispute returns and writes the field name in the section. It does not rename a created-date into a deadline. If no field looks like a response deadline, the section says the deadline was not returned and that dispute sorts last.

### Does an empty list mean the run failed?

No. Zero open disputes is a completed run whose file says so. run.failed is a different status on the session and on the webhook. An empty file with no sentence about the list is incomplete; the prompt asks for that sentence.
