# Affiliates

An affiliate refers customers to a rental and earns a commission on what they book. The affiliate never sells: the booking keeps the channel it came through, and the affiliate earns beside it. A booking made on a reseller's channel never pays an affiliate.

There are two sides to it in the API.

## Sending the click back

This part is for every booking engine, with no extra scope.

An affiliate's link is `https://mllw.is/a/<code>`. It records the click and sends the visitor to the rental's website with `?mref=<click id>` in the address. The click id is a UUID of 36 characters. Keep the `mref` for the visitor's session, and send it on the booking:

```json
{
  "carTypeId": "…",
  "pickupAt": "2027-06-01T10:00",
  "returnAt": "2027-06-04T10:00",
  "customer": { "firstName": "Anna", "lastName": "Jónsdóttir" },
  "mref": "019a1f2e-7c4b-7d21-9a3e-5b8c0d4f6e12"
}
```

When your site knows the affiliate but has no click, send the affiliate's code as `affiliate` instead. An unknown or expired `mref`, and a code outside the program, are ignored and do not refuse the booking. An `mref` over 64 characters fails the field check and answers `422` with `invalid`. Send it as it came.

One booking pays one affiliate. The rental decides who, in this order: a coupon tied to an affiliate, then a click inside the program's window, then a code, then an earlier referral of the same customer where the program has lifetime referrals on, then a person's pick at the desk.

## Reading the program

These paths need a key made with the affiliate right, which gives `affiliate.read` and `affiliate.write`. A rental with no affiliate program answers `404`.

```
GET  /rentals/{slug}/affiliates?status=
GET  /rentals/{slug}/affiliates/{id}
POST /rentals/{slug}/affiliates
GET  /rentals/{slug}/commissions?status=&affiliateId=&limit=
POST /rentals/{slug}/commissions/{bookingId}/approve
POST /rentals/{slug}/commissions/{bookingId}/reject
```

An **affiliate** carries its code, its link on `mllw.is`, and what it has brought all time: clicks, bookings, `pending` (earned on bookings not yet approved) and `balance` (approved and not yet paid).

**Adding an affiliate** makes one that is active at once, as when a person adds one on the Affiliates screen. An affiliate with an email gets the welcome email. An email the organization already has is the same person. The code is made from the name when you leave it out. A code in use answers `409` with `code_taken`, and an email already in the program `409` with `member`.

## Commissions

A **commission** belongs to one booking. It moves through these statuses:

| Status     | When                                                                                             |
| ---------- | ------------------------------------------------------------------------------------------------ |
| `pending`  | The booking is made. The commission is priced again with every change.                           |
| `due`      | The car came back. The approval wait starts, 14 days unless the rental says otherwise.           |
| `approved` | The approval wait is over, and the hourly tick or a person approved it.                          |
| `paid`     | It went out in a payout.                                                                         |
| `void`     | The booking was cancelled or a no-show, or the commission was rejected. `voidReason` says which. |
| `reversed` | A chargeback came after approval.                                                                |

`flags` says what looks wrong. A flagged commission waits for a person, and the tick never approves it:

| Flag         | What it means                                                              |
| ------------ | -------------------------------------------------------------------------- |
| `self`       | The affiliate shares an email, a phone or a kennitala with the customer.   |
| `quick`      | The booking came less than a minute after the click.                       |
| `flood`      | More than 20 clicks from one address for this affiliate in the day before. |
| `chargeback` | The booking had a chargeback.                                              |

`approve` works on a `due` commission whose approval wait has passed. `reject` works on a `pending`, `due` or `approved` commission, and makes it `void` with the reason `rejected`. A `paid`, `void` or `reversed` commission answers `409` with `not_open`. `approve` answers `409` with `not_due` when the commission is not in a state for it.

## Webhooks

An endpoint for every channel hears about referrals, commissions and affiliates. A channel's own endpoint never does. [Webhooks](/webhooks) lists the events.
