> ## Documentation Index
> Fetch the complete documentation index at: https://docs.affixo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Moving referrals and correcting sales

> Give a customer to another affiliate, fix one sale that went to the wrong person, and what your webhooks see when commissions change hands.

Sometimes a sale lands with the wrong affiliate. Affixo gives you two tools,
and they do different things:

| | Move a referral | Correct a sale |
| - | - | - |
| What moves | A customer, and optionally their unpaid history | One sale and its unpaid commission |
| Future payments | Credit the new affiliate | Unchanged |
| Dashboard | **Referrals**, then **Move to another affiliate** | The sale's **Edit** |
| API | `POST /v1/referrals/move` | `PATCH /v1/conversions/{id}` with `affiliate_id` |

Both follow the same rules in the dashboard and the API. **Paid commissions
never move.** They stay with the affiliate who was paid. And no money moves
either way: payouts still pay only confirmed commissions, through your own
payout method.

## Moving a referral

Use this when a customer belongs to someone else, for example an affiliate who
referred them by phone, or a customer who should follow an affiliate to a new
account. You choose one of two modes:

* **From now on only** (`mode: "forward"`). The customer's future payments
  credit the new affiliate. Every existing commission stays where it is. It
  needs the customer's email or Stripe customer id on record, so Affixo has
  something to match their future payments by.
* **Include history** (`mode: "history"`). Also moves the customer's unpaid
  commissions (pending, confirmed or held) to the new affiliate, at the
  amounts they were earned at. It's refused while any of those commissions is
  in a payout run that hasn't been paid. Remove them from the run first.

The new affiliate must be active (not suspended, banned, archived or left) and
the same kind of data as the customer: test affiliates take test customers,
live affiliates take live ones.

### Preview first

`POST /v1/referrals/move/preview` shows exactly what a move would do, the same
numbers the dashboard's Move dialog shows: how many commissions would move and
their totals, how many are paid and stay put, whether any are in a payout run,
and whether "from now on" is possible. Nothing changes.

```bash theme={null}
curl https://go.affixo.dev/v1/referrals/move/preview \
  -H "Authorization: Bearer sa_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "conversion_id": "<any of their sales>", "to_affiliate_id": "<new affiliate>" }'
```

Name the customer with `referral_id`, or with `conversion_id` for any of their
sales. The preview needs the `read` scope.

### Make the move

```bash theme={null}
curl https://go.affixo.dev/v1/referrals/move \
  -H "Authorization: Bearer sa_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "conversion_id": "<any of their sales>",
    "to_affiliate_id": "<new affiliate>",
    "mode": "history"
  }'
```

The move needs the `write` scope and a REST API key. A token minted for an AI
assistant through the [MCP server](https://docs.affixo.dev/mcp-server.md) can preview a move but gets
`403` if it tries to make one.

A refused move changes nothing and tells you why: `409 move_refused` (a
commission in a payout run, no email or Stripe customer id for "from now on",
or the customer already belongs to that affiliate) or `422
affiliate_not_eligible` (the new affiliate can't take them). See
[Errors and limits](https://docs.affixo.dev/errors-and-limits.md).

## Correcting one sale

Use this when a single sale was credited to the wrong affiliate, or to no one.

```bash theme={null}
curl -X PATCH https://go.affixo.dev/v1/conversions/<sale id> \
  -H "Authorization: Bearer sa_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "affiliate_id": "<new affiliate>" }'
```

The sale's unpaid commission moves with it, at the amount it was earned at.
The correction is refused, and nothing changes, when:

* a commission on the sale is already paid, or is in a payout run,
* the sale is one payment of a subscription (move the referral instead, so
  the renewals follow),
* the customer belongs to another affiliate, or was moved to one,
* the new affiliate can't take it.

You can send `status` in the same call. The two are applied together: if
either can't be applied, neither is. Setting `status` to `refunded`,
`reversed` or `chargeback` reverses the whole sale and claws back its
commission. There's no partial refund through the API.

Like a move, a correction needs a REST API key. MCP connector tokens get
`403`.

## What your webhooks see

Each commission that changes hands fires
[`commission.reassigned`](https://docs.affixo.dev/webhooks), one event per
commission. Its `amount` and `status` are unchanged. `source` tells you which
tool did it:

| `source` | From | `reassignment_id` |
| - | - | - |
| `move` | Moving a referral with its history | The move's id |
| `correction` | Correcting one sale | `null` |

`from_affiliate_id` is who held the commission before and `affiliate_id` is who
holds it now. If the affiliates have parents through
[sub-affiliates](https://docs.affixo.dev/sub-affiliates.md), the parent's share follows the new
affiliate; the [webhooks guide](https://docs.affixo.dev/webhooks.md) covers each
case.

A move "from now on only" moves no existing commission, so it sends nothing
until the customer's next payment arrives. That payment is then credited to
the new affiliate as a normal `conversion.created`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.