## Overview

The **affiliate program** turns whoever refers a sale into a native entity with its own commission. An
affiliate can be **four things**, and the link is one of **identity** (who the partner is), never of
payment — the payee is always the affiliate record itself:

| The affiliate is | When to use it |
|---|---|
| **An agent** | Someone on the team who also refers sales from another book |
| **A contact** | A customer who became a partner and now refers others |
| **A company** | A partner agency, reseller or clinic — its contacts can inherit the link |
| **An external partner** | Someone the account does not know: only an email/code (e.g. a Hotmart affiliate) |

Each affiliate gets a unique **referral code** (public, made to be shared) and a separate **report
token** (private, rotatable).

The core is **dual attribution**: one paid order credits the **seller (owner)** in the user statement
**and** the **affiliate** — on the same commission ledger, without collision. The seller keeps earning
their points and commission, and the affiliate earns the referral commission, over the same sale, with
no double count.

## Prerequisites

- The **Sales & Gamification** module enabled on the account.
- The **`affiliate_program`** feature enabled on the account (dark-shipped, default **off**).
- The **`unified_revenue_ledger`** feature enabled — affiliate commission accrues at the moment the order
  is paid (the same axis as the unified ledger). Without it, there is no affiliate commission accrual.
- The **sales-management** permission (`sales_manage`) — or an admin — to manage affiliates.

## Step by step

1. **Enable** `affiliate_program` (and `unified_revenue_ledger`) on the account.
2. **Create an affiliate**: under **"This affiliate is"** pick whether they are an agent, a contact, a
   company or an external partner; then set the **commission** (percent, flat amount, or plan).
3. **Share the referral code/link** with the affiliate.
4. **Attribute the referral** through any of these: set **"Referred by"** on the contact, use the
   automation action **"Set contact affiliate"**, send `affiliate_id` on the order, turn on **company
   inheritance**, or let the reconciler match the sale's split.
5. **The paid sale credits** the seller **and** the affiliate automatically.
6. **The affiliate tracks** their performance via the portal (by token); the manager reads the report in
   the dashboard.

## Settings & options

### Affiliate fields

| Field | What it is |
|---|---|
| `name` | Affiliate name (required) |
| `user_id` / `contact_id` / `organization_id` | **Who the affiliate is** — an agent, a contact or a company. **Mutually exclusive**: filling more than one is refused |
| `inherit_to_org_contacts` | Company only: when on, that company's contacts inherit the affiliate on **new** orders |
| `email` / `external_ref` | Email and/or external code (Hotmart ucode). **Unique per account** — this is how the reconciler identifies the partner |
| `referral_code` | Referral code — auto-generated, unique per account, **public**, made to be shared |
| `portal_token` | The **private** credential for the affiliate report. Separate from the code and **rotatable** |
| `commission_percent` | **Commission (%)** — commission percent (0–100); blank when a plan drives it |
| `commission_amount` | **Fixed commission (R$)** — a flat amount paid per sale, instead of a percentage. Optional: leave it blank to use the percentage |
| `plan_id` | A commission plan that overrides both the percent and the flat amount |
| `status` | `active`, `paused` or `archived` — **only active accrues commission** |
| `metadata` | Free data (e.g. the preserved Hotmart affiliation) |

> **Number format:** the commission fields accept a comma **or** a dot as the decimal separator —
> `25.00` and `25,00` mean the same, and a thousands separator is optional (`1,250.50`). A value out
> of range (a percentage above 100, a negative amount) is refused at once, with the reason next to
> the field.

### How a sale is attributed to the affiliate

In a cascade, most explicit first. The first step that answers wins, and an affiliate already on the
order is never overwritten:

1. **`affiliate_id` sent with the order** — accepted by the CRM API, the public ingest and automations.
   The id is always checked against **this account's ACTIVE affiliates**: an id from another account is
   dropped.
2. **"Referred by" on the contact** — the person's durable referral.
3. **The affiliate of the contact's primary company** — only when that affiliate turned
   `inherit_to_org_contacts` on. It applies to the **primary** company only, and forward-only: turning
   the option on never re-credits past orders.
4. **A reconciled external split** — matches the split's `ucode`/email (Hotmart/Kiwify) to an existing
   affiliate, including by the email of the **linked contact or company**.
5. **No match → the split goes to the reconciliation queue** instead of vanishing.

### Splits without a registered affiliate

When the gateway reports a commission for someone the account has **not registered**, that split is
recorded in a visible queue — with the name, email/ucode, the reported amount and the originating order.
Before, this case simply disappeared inside the metadata: the only symptom was a commission that never
showed up.

Open **"Unmatched splits"** on the Affiliates screen and decide: **Register** (opens the form pre-filled
from the split) or **Dismiss**. The queue **never creates an affiliate on its own** — paying someone
based on an unverified name that arrived in a webhook is exactly the risk this confirmation prevents.

### Dual attribution without collision

The commission ledger distinguishes the **payee type** (seller vs. affiliate). A paid order writes two
rows — the seller's and the affiliate's — without mixing. A seller's statement **never** sums the
affiliate rows.

### Affiliate commission

Commission is resolved **per sale**, in this order of precedence — most accurate first:

1. **The amount reported by the source** — when the sale came from **Hotmart** or **Kiwify**, the
   platform itself reports how much it actually paid **that** affiliate. That value is authoritative and
   goes into the ledger as-is, so the statement never diverges from what the affiliate really received.
2. **The commission plan** — when the affiliate has one.
3. **Fixed commission (R$)** — the flat amount set on the affiliate.
4. **Commission (%)** — the percentage over the paid order amount.

Why the source wins: on an external affiliate program the platform has **already computed and paid** the
split, so applying our own percentage on top would produce a number that disagrees with reality.

An **external** affiliate gets commission and the portal, but **no** gamification points (points require
a user).

### The affiliate statement

An affiliate has their **own statement**, with the same cycle as a rep's: **accrued → approved → paid**.
It is closed per period **and per currency** — a statement is a payable document and you pay it in a
single currency, so BRL and USD accruals become separate statements rather than one total that does not
exist.

An affiliate statement and a rep statement are **independent records**, even when their identifying
numbers happen to coincide. In the statements list, the payee-type filter separates the two ledgers.

### Affiliate portal

A **public**, read-only page opened by the **report token** — no session and no `account_id`. It shows
only the affiliate's own performance: attributed orders (paginated, with a period filter), revenue and
commission **grouped by currency**, and the closed statements — **no contact PII**. An invalid or rotated
token, or a feature-off account, returns 404.

**The token is not the referral code.** The code is public — it goes on links and material — and stays
valid forever; the token is the private credential for the financial report. Use **Rotate** on the
affiliate record to invalidate every report link already shared, immediately: no referral stops working,
because the code does not change.

> **Affiliates created before this version** start with the token **equal to their public referral
> code** — that is how no link already handed out broke during the migration. While that is true, anyone
> who knows the code can open the report, and the record shows the warning *"this link is still the
> public code"*. **Rotate the token** on those affiliates to issue a genuinely private link.

### Archive, restore and permanent deletion

The default list shows current affiliates; use the **status filter** to review active, paused or archived
partners. **Archive** stops new attribution and commission but keeps every existing referral, order and
statement, and **Restore** makes the partner active again. **Delete permanently** is shown only for an
archived affiliate and succeeds only when it has no referral, order, reconciliation or financial history;
the confirmation is explicit and the action cannot be undone.

## Use cases

- Materialize a **Hotmart affiliate** from the split preserved on the sale (reconciled by ucode/email).
- Register an **internal agent** as an affiliate who refers sales from another portfolio.
- Share a **referral link** to capture trackable referrals.
- The affiliate opens the **portal** and tracks their accrued commission in near real time.

## Tips, limits & best practices

- An **external** affiliate earns no gamification points — only commission + the portal.
- **Only active affiliates** accrue; a paused/archived affiliate accrues nothing.
- **Paying** the affiliate out (Pix/transfer) is out of scope in v1 — the module does accrual + report +
  portal.
- The `referral_code` is **public** — share it freely. What opens the financial report is the **report
  token**, which is private and can be rotated at any time.
- **Company inheritance** is opt-in per affiliate and forward-only — turning it on re-credits nothing
  from the past.
- When **merging contacts**, the mergee's referral is adopted by the base contact when it has none; a
  base that already had a referral keeps its own.
- A refund also **reverses** the affiliate commission, on the order source.

## Troubleshooting

- **Affiliate not credited**: `unified_revenue_ledger` may be off, the order may have no attributed
  affiliate, or the affiliate is not **active**. Check all three.
- **Portal returns 404**: wrong/stale token, or the `affiliate_program` feature is off on the account.
- **Hotmart affiliate did not match**: the split went to **"Unmatched splits"**. Open the queue and use
  **Register** — the form arrives pre-filled with the exact email/ucode the gateway sent.
- **Commission shows under "unspecified" currency**: those are accruals that predate the per-currency
  split. Their real currency is unknown and is not invented; new accruals carry the order's currency.
- **Permanent deletion was refused**: the affiliate still has referral, order, reconciliation or financial
  history. Keep it archived; preserved history is intentional.

## See also

- [Unified revenue ledger: counting each sale once](/hc/ajuda/articles/sales-gamification-unified-revenue-ledger-en)
- [Sales dashboards and reports](/hc/ajuda/articles/sales-gamification-paineis-e-relatorios-de-vendas-en)
- [Sales and Gamification overview](/hc/ajuda/articles/sales-gamification-overview-en)