Skip to content

Refunds

An agent asks for a refund with a second signed mandate that points at the original order. The request goes through your guardrails like any order, can be held for review, and is refunded on the rail that took the original payment: Stripe, or Shopify in test mode. Sill never holds the money: Stripe returns it to the buyer. Every step is written to the signed audit log.

sequenceDiagram
    autonumber
    participant Agent
    participant Sill
    participant Team as Owner or Admin
    participant Rail as Stripe (or Shopify test mode)

    Agent->>Sill: Signed refund request for an earlier order
    Sill->>Sill: Verify signature, run your guardrails
    opt A rule holds it for review
        Sill-->>Agent: escalated
        Team->>Sill: Approve on Held orders
    end
    Sill->>Sill: Find the original order and its rail
    Sill->>Rail: Refund the original payment
    Rail-->>Sill: Succeeded or failed
    Sill->>Sill: Signed record of the refund

The agent never names the refund amount. Sill refunds the original charged total, or less if the agent’s signed cap is lower.

A refund mandate has intent.action set to request_refund and only these intent fields:

{
"signed": {
"mandate_id": "mnd_01K6HBK7MK753DH3YBX4NVCYTT",
"site_id": "01JDEMOSITE00000000000MAIN",
"agent_id": "agent_acme_shopper",
"issued_at": "2026-09-30T15:38:00.000Z",
"expires_at": "2026-09-30T15:38:30.000Z",
"nonce": "Q8sLm2Vx7Tb4Nc1Rp9Kd3w",
"replay_window_seconds": 30,
"principal": { "type": "human", "verification": "delegated" },
"intent": {
"action": "request_refund",
"merchant": "northwind-coffee.example",
"original_mandate_id": "mnd_01K6HXAVBQ8G8PYZKN9JXJEPTN",
"reason_code": "wrong_item",
"scope": "full",
"max_amount": 89.00,
"currency": "USD"
},
"protocol_context": { "protocol": "a2a", "version": "1.2" }
},
"envelope": {
"algorithm": "ed25519",
"key_id": "acme-2026-10",
"signature": "<86-character base64url ed25519 signature>"
}
}
FieldMeaning
original_mandate_idThe order being refunded. It must be an order on the same site that was approved and charged.
reason_codeOne of requested_by_customer, defective, not_received, wrong_item, other.
scope"full". A list of line items is accepted in the request but not refunded today; see Current limits.
max_amountThe most the agent may refund, in major units. It caps the refund; it does not set it.

Order fields such as sku, line_items, quoted_total or buyer are refused on a refund: the order details come from Sill’s own record of the original.

Whether a refund is held depends on your policy. The baseline policy (v1-default) never holds refunds. To review them, add Human review (HITL) on destructive actions (r07) with action Escalate under Rules, or load the Conservative / manual review template, which holds refunds over $50.

A held refund appears on Held orders with a headline such as Refund request · Wrong item · up to $89.00, and with the original order Sill found in its own records: the items, the settled total, a link to the charge in Stripe and the buyer’s details. Owners and Admins approve or reject; Reviewers can look but not decide. If you reject, or nobody decides within 24 hours, nothing is refunded.

Held refund request for a wrong item, up to $89.00, with the original three-item order and Approve and Reject buttons Check the original order Sill found before approving the refund.

Under Rules → AUTO-REFUND (Approve refunds under a cap automatically), Owners and Admins can skip review for small refunds:

  1. Turn on Auto-approve refunds under cap.
  2. Set MAXIMUM AUTO-APPROVE AMOUNT and save.

A refund is then approved without review only if it is at or under the cap and comes from the same agent that placed the original order. Larger refunds, and refunds from any other agent, are still held. The signed record of an auto-approved refund has no reviewer on it.

AUTO-REFUND on Rules: Auto-approve refunds under cap switched on with a maximum auto-approve amount of $25.00 Auto-refund approves small refunds from the agent that placed the order; everything else still waits for you.

Original paid onRefund runs onStatus
StripeStripe refund on your connected accountAvailable in test and live mode
ShopifyShopify refund on the storeTest mode only

WooCommerce stores. Orders on a WooCommerce site are paid on Stripe, so their refunds run on Stripe too. After Stripe confirms, Sill records the refund on the matching WooCommerce order, without asking any WooCommerce gateway to move money. This needs Read/Write REST API keys; with read-only keys the Stripe refund still happens but the WooCommerce order is not updated. A WooCommerce site without Stripe connected cannot take agent refunds.

Nothing is sent to the rail in these cases, and the refund’s record says why:

ReasonMeaning
Original not chargedThe original order is not on this site, was not approved, or was never charged.
Already executedThe original order already has a refund. Only one refund per order is possible.
Scope unsupportedThe request asked for specific line items. Send "scope": "full".
Rail disabledThe rail that took the original payment is not enabled for the site.
Rate limited by selfToo many refunds in a short time for this account. Sill retries automatically.

Sending the same refund mandate twice never refunds twice.

Sill also records what Stripe reports about orders it charged. A refund you issue in the Stripe dashboard is added to the original order with the refunded amount, and a dispute is added with its reason and amount. Responding to a dispute happens in your Stripe dashboard; Sill does not submit evidence for you.

Each refund request ends in one signed decision record (approved, escalated_approved, escalated_rejected or rejected). When the refund succeeds, a separate signed settlement record is added that links the refunded amount to that decision, the same way charges are recorded. Open the refund under Activity to see the original order and the amount refunded. See Audit envelope.

  • Refunds run on Stripe in test and live mode, and on Shopify in test mode only.
  • Only full refunds: requests for specific line items are refused.
  • One refund per order; a second refund request for the same order is refused. A refund is less than the original total only when the agent’s signed max_amount is lower.
  • Refunds never involve card numbers; Sill only works with Stripe’s charge and payment ids.

No. The refund is the original charged total, or the agent’s signed max_amount if that is lower. The agent cannot state what the original order cost.

Yes. The baseline policy does not hold refunds at all. If you add a review rule, Auto-refund can still approve small refunds from the agent that placed the order.

What if the original order was never charged?

Section titled “What if the original order was never charged?”

The refund is refused with “Original not charged”, and nothing is sent to Stripe.