---
id: "brand/tracking/payment-flow"
type: "doc"
url: "https://affitor.com/docs/brand/tracking/payment-flow"
---
# Payment Flow

> End-to-end flow from affiliate click to attributed revenue and payout operations, covering server-side tracking and Stripe integration paths

Understand how attribution moves from click → signup → sale in the current public Affitor model.

---

## End-to-End Flow

<Mermaid chart={`sequenceDiagram
  participant P as Partner
  participant C as Customer
  participant Y as Your site
  participant A as Affitor
  P->>C: Shares referral link (?aff=CODE)
  C->>Y: Visits — the SDK stores the click
  C->>Y: Signs up — lead event with the aff code
  C->>Y: Pays (Stripe checkout)
  Y->>A: Stripe webhook / S2S sale event
  A->>A: Attributes the sale, creates the commission
  A->>P: Commission appears (pending, then approved)
`} />

### 1. Partner shares a referral link

A partner promotes your product with a referral URL such as:

```text
https://yoursite.com?aff=PARTNER123
```

### 2. Customer lands on your site

The tracker detects `?aff=` and creates the click/customer relationship.

**What happens:**
- Click is recorded
- `affitor_click_id` is stored in a first-party cookie
- Visit is linked to the correct partner/program

### 3. Customer signs up

After account creation succeeds, you send your internal customer ID to Affitor.

**Browser helper example:**

```javascript
if (window.affitor) {
  await window.affitor.signup('user_123', 'customer@example.com');
}
```

**What matters here:**
- Your internal identifier is stored for future matching
- Reuse that same identifier as:
  - `customer_key` in Server-side tracking — your backend calls POST /api/v1/track/sale
  - `affitor_customer_key` in Stripe metadata

### 4. Customer pays

You then choose one supported sale-tracking path: server-side tracking vs Stripe integration.

#### Path A — Server-side tracking

Your backend calls POST /api/v1/track/sale when payment succeeds.

```json
{
  "transaction_id": "txn_123",
  "customer_key": "user_123",
  "amount_cents": 10000,
  "currency": "USD"
}
```

#### Path B — Stripe integration

You keep charging in your own Stripe account and attach Affitor metadata.

```javascript
metadata: {
  program_id: 'YOUR_PROGRAM_ID',
  affitor_click_id: clickId,
  affitor_customer_key: currentUser.id,
}
```

For subscriptions, also include the same fields in `subscription_data.metadata`.

### 5. Affitor attributes the sale

Affitor resolves the customer/partner relationship using any combination of:
- click ID
- customer email matching
- Stripe customer ID
- customer key

### 6. Commission and platform records are created

When attribution succeeds, Affitor records the sale and creates the commission flow. Commissions then wait out the program's hold period, are approved into the partner's balance, and are paid out when the partner requests a withdrawal.

---

## Invoice billing in Plain Language

In the current public invoice billing model:

1. **You** collect payment from the customer in your own Stripe account
2. **Affitor** attributes the conversion using Stripe metadata + webhook events
3. **Affitor** bills through its invoice workflow for validated partner commission + platform fee obligations
4. **Affitor** continues partner payouts through its payout operations

:::note

Affitor is not the merchant of record for your sales: customer payments stay in your Stripe account. Your weekly invoice (approved partner commissions plus the platform fee) is paid to Affitor LLC, and Affitor pays partners when they withdraw.

:::

---

## One-Time vs Subscription Revenue

### One-time payments

For one-time Stripe Checkout payments, attribution starts from checkout session metadata and the associated webhook flow.

### Subscriptions

For subscriptions, the initial and recurring commission flow depends on invoice processing.

Recurring setups must therefore include:
- `metadata`
- `subscription_data.metadata`

If only the initial checkout metadata is present, renewals may not attribute correctly.

---

## Common Validation Points

| Check | Why it matters |
|------|----------------|
| `customerKey` used at signup | links later payments back to the same internal user |
| `transaction_id` unique (server-side tracking) | prevents duplicate sale records |
| `program_id` in Stripe metadata | routes the event to the correct program |
| `subscription_data.metadata` set | keeps renewals attributable |
| click tracked first | gives Affitor the strongest attribution signal |

---

## Example Timeline

| Day | Event |
|-----|-------|
| 0 | customer clicks affiliate link |
| 0 | tracker stores `affitor_click_id` |
| 2 | customer signs up and you send `customerKey` |
| 7 | customer pays |
| 7 | sale is attributed via server-side tracking or Stripe integration |
| 7+ | commission enters the hold period, then is approved into the partner balance |

---

## Next Steps

- [Payment Tracking](/docs/brand/tracking/payment-tracking-stripe/)
- [3-Step Integration Guide](/docs/brand/tracking/quickstart-integration/)
- [Testing Integration](/docs/brand/tracking/testing-integration/)
