# Refund a customer

URL: /systems/finance/refund-a-customer · Id: `guide:refund-a-customer`

> Say "refund this order" and get all or part of the payment back on their card, with the books reversed and your refund Limit checked.

Give a customer back all or part of what they paid, on the card they paid with. Your books record the refund in the same step, and any refund over your refund [Limit](/business/nouns/limit) waits for your yes.

Needs: [Take a payment](/systems/finance/take-a-payment)

**Before real money moves**

- Who says yes: Your agent, within a standing [Mandate](/business/nouns/mandate) and its [Limit](/business/nouns/limit). Past the Limit, it waits for your [Approval](/business/nouns/approval).
- You leave the chat: Never: it all happens in the chat.

## What you get
- 1 refund to the card they paid with, all or part of the payment (Order)
- 1 the refund posted to your books (Entry)
- 1 Approval from you first, for any refund over your refund Limit (Approval)

## Your agent does
**For agents**

- Guide: `guide:refund-a-customer`, status `live`. Page: [/systems/finance/refund-a-customer.md](/systems/finance/refund-a-customer.md).
- Approval: none inside the standing Mandate and its Limit. Past the Limit, the call waits `pending` for the founder’s Approval.
- Leaves the chat: never.
- Needs first: [Take a payment](/systems/finance/take-a-payment).
- Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own.

| Step | Verb | Inputs (type, required, this guide’s value) | Returns |
| --- | --- | --- | --- |
| 1 | [`Order.refund`](/business/nouns/order/refund) (`verb:Order.refund`) | `order` Order (an id), required: the `$id` of the first Order `Order.list` returns for `where: customer = Harbor`; `amount` money: example `{"amount":49,"currency":"USD"}`; `reason` text, required: example `"Setup call did not happen."` | `order` Order |

Returns: the last call answers with `order` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`:

```json
{
  "api": "https://api.sb/leaseline.app",
  "order": {
    "$id": "https://api.sb/leaseline.app/orders/order_1",
    "$type": "Order",
    "status": "refunded"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Order.refund",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/leaseline.app/actions/action_1"
  }
}
```

Next: offer “Refund their last invoice instead”, or “Ask me before any refund over $250”.

Calls: `Order.refund`

Ask:

```text
Refund a customer.
Refund this order.
Give Harbor their money back.
```

API:

```bash
# Look up the Order: Order.list
ORDER=$(curl "https://api.sb/leaseline.app/orders?where=customer%20%3D%20Harbor&limit=1" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" | jq -r '.orders[0]["$id"] | split("/") | last')

# Order.refund
curl -X POST https://api.sb/leaseline.app/orders/$ORDER/refund \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Setup call did not happen.","amount":{"amount":49,"currency":"USD"}}'
```

SDK:

```ts
import { $ } from 'startup-builder'

const [order] = await $.Order.list({ where: 'customer = Harbor', limit: 1 })
await $.Order.refund({ order: order.$id, reason: 'Setup call did not happen.', amount: { amount: 49, currency: 'USD' } })
```

CLI:

```bash
ORDER=$(npx startup-builder do Order.list --json '{"where":"customer = Harbor","limit":1}' | jq -r '.orders[0]["$id"] | split("/") | last')
npx startup-builder do Order.refund --json '{"order":"'"$ORDER"'","reason":"Setup call did not happen.","amount":{"amount":49,"currency":"USD"}}'
```

MCP:

```json
{
  "name": "do",
  "arguments": {
    "code": "const [order] = await $.Order.list({ where: 'customer = Harbor', limit: 1 })\nreturn await $.Order.refund({ order: order.$id, reason: 'Setup call did not happen.', amount: { amount: 49, currency: 'USD' } })"
  }
}
```

## Change it
- Refund their last invoice instead.
- Ask me before any refund over $250.
- Refund the whole order.

## Under the hood
- Systems: [Billing](/systems/billing), [Ledger](/systems/ledger)
- Nouns: [Order](/business/nouns/order), [Invoice](/business/nouns/invoice), [Entry](/business/nouns/entry), [Limit](/business/nouns/limit), [Approval](/business/nouns/approval)
- Events: [`Order.refunded`](/business/events/Order.refunded)
- Stripe objects: `Refund`

A one-time purchase is refunded with [`Order.refund`](/business/nouns/order/refund); a subscription charge is an [Invoice](/business/nouns/invoice), refunded with [`Invoice.refund`](/business/nouns/invoice/refund). Either posts the reversing [Entries](/business/nouns/entry).