# Referrals

Track the referrer -> referred contact -> opportunity chain. Includes workspace-defined category picklist, a leaderboard endpoint, a public token-based submission form, and an automation action (attribute_referral) for pipeline-driven attribution. Every write to the referrals table fires the referral_attributed automation trigger (see GET /schemas/triggers/referral_attributed). Attribution is also cached on the opportunity: crm_deals.primary_referrer_contact_id and crm_deals.primary_referrer_category are maintained by a Postgres trigger and surface in GET /opportunities/:id (including the expand=referrer expansion).

**Base URL:** `https://api.trustpager.com/functions/v1/api/v1`

## Endpoints

### GET /referrals

List referrals for the workspace. Filter by status, referrer_contact_id, referred_contact_id, or category. Returns the full referral chain including category and notes.

**Scopes:** `referrals:read` — [full detail](./referrals/get-referrals.md)

### GET /referrals/:id

Get a single referral by UUID.

**Scopes:** `referrals:read` — [full detail](./referrals/get-referrals-id.md)

### POST /referrals

Manually log a referral (verbal/ad-hoc). source defaults to "manual". For form-driven flows use POST /referrals/request. For automation-driven attribution configure the attribute_referral automation action.

**Scopes:** `referrals:write` — [full detail](./referrals/post-referrals.md)

### PATCH /referrals/:id

Update a referral. Writable fields: referred_contact_id, referred_deal_id, status, category, notes. Setting status="converted" stamps converted_at but does NOT send the thank-you email -- use POST /referrals/:id/convert for the full flow.

**Scopes:** `referrals:write` — [full detail](./referrals/patch-referrals-id.md)

### DELETE /referrals/:id

Delete a referral row. The linked contact and opportunity are NOT deleted -- only the referral relationship row is removed.

**Scopes:** `referrals:delete` — [full detail](./referrals/delete-referrals-id.md)

### POST /referrals/:id/convert

Mark a referral as converted (referred deal closed Won) AND send the branded thank-you email to the referrer. Stamps converted_at. Prefer this over PATCH /referrals/:id when transitioning to converted -- it triggers the email side-effect. Response includes thank_you_sent boolean.

**Scopes:** `referrals:write` — [full detail](./referrals/post-referrals-id-convert.md)

### POST /referrals/request

Send a tracked referral-request email to a known contact. The recipient lands on a public page and submits a friend's details -- the platform auto-creates a contact + opportunity + referral row on submit. Returns request_id, token, and public_url.

**Scopes:** `referrals:write` — [full detail](./referrals/post-referrals-request.md)

### GET /referrals/requests

List referral request lifecycle rows (sent -> viewed -> submitted -> expired). Filter by status or contact_id. Useful for "who has been asked but not yet submitted".

**Scopes:** `referrals:read` — [full detail](./referrals/get-referrals-requests.md)

### GET /referrals/leaderboard

Top referrers ranked by converted_referrals desc, then total_referrals desc. Returns up to limit entries with contact details, total_referrals, converted_referrals, and conversion_rate.

**Scopes:** `referrals:read` — [full detail](./referrals/get-referrals-leaderboard.md)
