Partners

Create partners, link them to your own user ids, provision them idempotently, archive or delete them, and walk the referral graph.

Embed
Preview of the card
<a href="https://referalli.com/docs/partners"><img src="https://referalli.com/docs/_api/public/orgs/07f432f4-34b9-46a7-aaad-c0e395d2e4f9/spaces/2bf4f614-3630-4fbf-85f9-5ecafa6b7d97/pages/ceaaae6a-4cfc-4f25-8a16-3b74a3c6533c/social-card.svg?v=3e7ae33eec8b" alt="Partners" width="600" height="315"></a>

A partner is someone who earns commissions in your org. You can invite partners one at a time, or provision them from your own user base, for example when every customer can refer others.

Create a partner

curl -X POST https://referalli.com/v1/partners \
  -H "Authorization: Bearer $KEY" \
  -H "content-type: application/json" \
  -d '{"email": "dana@example.com", "displayName": "Dana", "externalRef": "usr_8812"}'
{
  "id": "ptr_01JB...",
  "email": "dana@example.com",
  "displayName": "Dana",
  "externalRef": "usr_8812",
  "status": "active",
  "tags": [],
  "notes": "",
  "createdAt": "2026-10-21T12:00:00.000Z"
}

Field

Required

Description

email

yes

Unique within your org, ignoring case.

displayName

no

Shown in the dashboard and the partner portal.

externalRef

no

Your own id for this partner, such as your user id. 1 to 256 characters, unique within your org.

tags, notes

no

For your own bookkeeping.

upsert

no

true returns the existing partner instead of failing (below).

Unknown fields are rejected with 400 and a message naming them, such as unknown field(s): externalRefx, so a typo can't be silently ignored. A second partner with the same email or externalRef returns 409.

Provision idempotently with upsert

With "upsert": true, the call returns the partner that already has this email or externalRef (status 200) and creates one only if neither matches. That makes provisioning thousands of users one safe, repeatable call each.

  • If the existing partner has no externalRef yet, the one you send is saved on it.

  • If email and externalRef belong to two different partners, or the partner found by email already has a different externalRef, the call returns 409.

  • Other fields (displayName, tags, notes) are only used when creating; use PATCH to change an existing partner.

Find partners

GET /v1/partners lists partners. Filters:

Query

Matches

email

That email, ignoring case.

externalRef

That external id.

status

active, suspended, banned or archived.

includeArchived=true

Also return archived partners, which are hidden by default.

GET /v1/partners/{id} returns one partner. Partners in the GraphQL API also carry externalRef.

Update a partner

PATCH /v1/partners/{id} changes displayName, status, tags, notes or externalRef (send null to clear it). Unknown fields return 400.

Status

Meaning

active

Earns and is paid.

suspended

Still earns, but payouts are held until you reactivate them.

banned

Earns nothing new and is never paid while banned.

archived

Retired: hidden from lists, earns nothing new and is never paid, like banned. Set it back to active to restore them.

See Commission rules for exactly what each status does to money.

Delete a partner

DELETE /v1/partners/{id} removes a partner that never did anything, together with their enrollments, links, coupons and payout profile. It needs the owner or admin role.

A partner with any history (clicks, referrals, commission lines, payouts, deals, fraud cases, contracts, or recruits of their own) can't be deleted, because the ledger and audit trail must stay intact. The call then returns 409 with partner has activity; archive it instead (status "archived").

Referral graph

In programs where customers are partners too, a referred customer can go on to refer others. GET /v1/programs/{id}/graph?root={partnerId}&depth=5 returns that tree.

A referred customer continues the tree when their customerRef equals another partner's externalRef. depth is 1 to 5 partner levels (default 5); with depth=1 you get the root and the customers it referred.

{
  "partnerId": "ptr_root",
  "displayName": "Root",
  "email": "root@example.com",
  "externalRef": "usr_root",
  "status": "active",
  "commission": [{ "currency": "usd", "amountMinor": 1000 }],
  "referrals": [
    {
      "referralId": "ref_...",
      "customerRef": "usr_mid",
      "status": "active",
      "matchedVia": "coupon",
      "ts": "2026-10-21T12:00:00.000Z",
      "revenue": [{ "currency": "usd", "amountMinor": 10000 }],
      "commission": [{ "currency": "usd", "amountMinor": 1000 }],
      "partner": {
        "partnerId": "ptr_mid",
        "commission": [{ "currency": "usd", "amountMinor": 400 }],
        "referrals": [{ "customerRef": "cus_leaf", "partner": null, "...": "..." }]
      }
    }
  ],
  "depth": 5,
  "truncated": false
}
  • A partner node's commission is the net commission that partner earned in this program (earned lines plus reversals and adjustments), per currency, in minor units.

  • A referral's revenue is the gross of that customer's payments; its commission is what the referring partner earned from that customer.

  • Voided referrals are left out. Each partner appears at most once, so a cycle can't repeat.

  • The walk stops after 5,000 referrals and sets truncated: true.

  • An unknown program or root partner returns 404; a depth outside 1 to 5 returns 400.

Updated