# Referrals

Referrals endpoints record which invitation link brought an install, and give you the report behind the dashboard's **Referrals** view. Read [Referrals](https://warplink.app/docs/guides/referrals) for the full path from link to reward. The MCP server has the same operations as `claim_referral`, `list_referrals`, `get_referral`, `resend_referral_webhook` and `delete_referral`.

## Authentication and Permissions

Reading needs an API key with the `referrals:read` scope. Claiming, resending and deleting need `referrals:write`, which includes `referrals:read`. Resending also needs a key whose creator is an owner or admin.

`POST /v1/referrals/claims` is the one referral route an SDK key can call. It needs the `attribution:write` scope an SDK key carries, and it is limited to 60 requests a minute per key per client IP address. Every other referral route refuses an SDK key with `403 SDK_KEY_ROUTE_FORBIDDEN`.

## Claim a Referral

POST /referrals/claims: Claim a referral

Send `installer_id`, your own id for the new user, with one piece of evidence: an `install_id` from the SDK's attribution result, a `recovery_token`, or a `link_id`. The first valid claim for an app and installer id wins. Every outcome is a `200` with a `status` of `claimed`, `flagged`, `ignored` or `none`, and `none` records nothing. Send an `Idempotency-Key` to repeat a call safely.

An exact claim from an installer that holds an estimate upgrades the referral and returns `updated: true`. A `link_id` for a link that is not a referral link answers `409 LINK_NOT_REFERRAL`. A `503 RECOVERY_TOKEN_PENDING` carries a `Retry-After` header: send the same claim again after that many seconds.

```bash
curl -X POST https://api.warplink.app/v1/referrals/claims \
  -H "Authorization: Bearer wl_live_YOUR_API_KEY" \
  -H "Idempotency-Key: signup-8f21" \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "YOUR_APP_ID",
    "installer_id": "d1c2f9a0-7b43-4f0e-a6d5-3c2b8e1f7a90",
    "install_id": "INSTALL_ID_FROM_THE_APP"
  }'
```

## List Referrals

GET /referrals: List referrals

Referrals come newest claim first. `status` is `claimed`, `delivered`, `retrying`, `failed`, `flagged` or `duplicate`: `flagged` and `duplicate` are the referral's own state, and the rest follow its latest webhook delivery. `match.exact` and `evidence_class` say how sure the match is. Page with `pagination.next_cursor` and send the same filters with it. `format=csv` returns one file of up to 10,000 rows and refuses a cursor.

## Get a Referral

GET /referrals/{id}: Get a referral

The response adds the referral's claims, its webhook events with the payloads we sent, and every delivery attempt.

## Resend a Referral's Events

POST /referrals/{id}/resend: Resend a referral's webhook events

Each endpoint receives its newest event again with the same event id, so a receiver can drop the repeat. Add `endpoint_id` to resend to one endpoint. An event still in flight, or finished more than 7 days ago, comes back in `skipped`.

## Delete a Referral

DELETE /referrals/{id}: Delete a referral

Deleting erases the referral with its claims, webhook events and delivery attempts. It cannot be undone.
