Content

What the PayPal API does on a refund versus a payout

A PayPal refund reverses one capture. A payout sends new money. Sandbox and live use different hosts, and a missing PayPal-Request-Id can duplicate the call.

EngineeringOct 30, 2026

Key takeaways

  • -In this article we explore the PayPal API for agents, and the difference between a refund and a payout.
  • -A refund reverses one capture. A payout sends new money from the PayPal balance to an email, phone, or PayPal ID.
  • -Sandbox calls use api-m.sandbox.paypal.com. Live calls use api-m.paypal.com. The token has to match the host.
  • -PayPal-Request-Id stops a retry from duplicating a POST on APIs that store the header. Omit the header and PayPal duplicates the request.

Support asks the agent to refund order 1048. In the PayPal sandbox the capture flips to refunded and the test buyer balance moves. The same sentence, pointed at live, calls Payouts instead. A new payment leaves the business balance. Capture 1048 is still settled. The customer now has the original charge and an extra payout.

This post separates those two PayPal calls, shows how the sandbox host diverges from live, and shows the header that stops a retry from doing the work twice.

Two calls that both look like "give the money back"

A refund belongs to a capture you already took. PayPal's payments API refunds that capture. The amount can be the full capture or less. The original payment is the thing that changes. The same split shows up on cards in how to connect Stripe to Claude Code: you name the original charge, you do not start a second payout.

A payout is a new payment. PayPal's Payouts overview sends money to an email, a phone number, or a PayPal ID, in a batch. The recipient claims it in PayPal or, for US dollars, Venmo. Nothing about that call looks up a prior capture. If the agent uses a payout to "undo" a charge, the charge remains and a second movement of money starts.

RefundPayout
What movesThe capture you nameA new payment from your balance
Who receives itThe payer on that captureThe email, phone, or PayPal ID you pass
Live accessThe payments product you already useYou request Payouts access. PayPal emails a decision
FundingThe captured paymentYour PayPal balance, including fees

Live Payouts also want a confirmed identity, a confirmed email, and a linked bank. You can build against sandbox accounts while that decision is pending. A sandbox success does not mean the live account has Payouts turned on.

The PayPal catalog page is the method list. After swy get, copy the id from swy list methods. A prompt that says "refund" will pick whichever of those ids you left enabled.

swy search paypal
swy get paypal
swy list methods

The sandbox host and the live host

Sandbox calls go to api-m.sandbox.paypal.com. Live calls go to api-m.paypal.com. The access token is minted for one of those. A sandbox token against the live host fails. A live token against the sandbox host fails. The agent has to carry the host that matches the token.

PayPal sandbox buyers are sandbox accounts. A payout to a sandbox email proves the batch shape. It does not prove a live recipient can claim the money, and it does not prove your live balance can fund the batch. Venmo payouts are US dollars only, and the notification path wants a US mobile number. A sandbox script that uses a Venmo-style phone will not teach you the live country rules.

Swytchcode records its own mode once, in tooling.json, when you run swy init. That value does not flip PayPal from sandbox to live. Point the method at the host the token belongs to.

There is no .env file in this project. Swytchcode keeps credentials in its own local store and reads them when a call runs. swy auth connect is how the PayPal credential gets into that store. The model should not see the access token.

PayPal-Request-Id is the retry control

PayPal's idempotency reference (updated August 11, 2026) says you send PayPal-Request-Id on POST calls for APIs that support the header. PayPal stores that id. A retry with the same id returns the latest status of the earlier request. The capture example on that page is explicit: the first call captured the payment, the retry with the same id did not capture it again.

Omit the header and PayPal duplicates the request. That sentence is the one to put in the runbook. A model that generates a fresh id on every attempt is omitting the previous id. PayPal treats the fresh id as a new request.

A few limits sit on the same page. The value should be unique per request and per call type. Authorize and capture do not share an id. PayPal recommends a UUID, and the value has a 38 character limit. Two in-flight requests with the same id can end with the second one failed, because PayPal processes the first. The page also says not every API stores the header. Read the reference for the method you enabled. If Payouts does not list the header, a retry can open a second batch. Hold that method for a person until you have checked.

Policy as code is where you reject a payout amount you will not send, and where you keep the refund method and the payout method from being equally easy for the model to pick.

Enable the refund method for the capture case. Leave Payouts off until access is granted on the live account and the request id behavior is confirmed for that endpoint. Match the host to the token before either call runs.

FAQ

Does a PayPal payout undo the original charge?

No. A payout creates a new payment from your balance to an email, phone, or PayPal ID. The refund call is the one that targets a capture. If both run, the customer can receive a payout while the charge still stands.

Can I test Payouts before PayPal approves live access?

Yes, in sandbox. Live Payouts need the access request, a confirmed identity, email, and bank, and enough balance for the batch and fees. Sandbox success does not grant the live product.

What happens if the agent retries a refund with a new PayPal-Request-Id?

PayPal treats a new id as a new request on APIs that store the header. Reuse the id from the first attempt. If you drop the header entirely, PayPal's own guide says the request is duplicated.

Does Swytchcode sandbox mode switch PayPal to the sandbox host?

No. Swytchcode mode is stored in tooling.json at swy init. PayPal sandbox is the host api-m.sandbox.paypal.com and a sandbox token. You set those on the PayPal side.

More content