# Referrals API

> Read the referral program, its numbers, a subscriber's link and referrals, and the earned rewards with an API token. Mark a reward as fulfilled from your own system.

Source: https://sendbroadcast.net/docs/plugins-referrals-api

The official Referrals plugin has an API. Use it to show a subscriber their referral link on your own site, or to send rewards from your shop system. For the plugin itself, see [Referrals](https://sendbroadcast.net/docs/plugins-referrals).

## Before you start

1. Install the Referrals plugin and turn it on in the channel.
2. Open the API tokens page and make a token for that channel.
3. Give the token the permissions below.
4. Write `broadcast.referrals/*` in the token's **Plugin endpoints** field.

| Endpoint | Method | Token permission |
|---|---|---|
| `program` | GET | Subscribers read |
| `stats` | GET | Subscribers read |
| `subscriber` | GET | Subscribers read |
| `fulfillment` | GET | Subscribers read |
| `fulfill` | POST | Subscribers write |

All addresses start with `https://your-broadcast-server/api/plugins/broadcast.referrals/`. Send the token in the `Authorization` header. The data belongs to the channel of the token.

## The program

```bash
curl https://your-broadcast-server/api/plugins/broadcast.referrals/program \
  -H "Authorization: Bearer YOUR_TOKEN"
```

The answer has the configuration and the rewards:

```json
{
  "enabled": true,
  "description": "Score a discount",
  "template": "upcoming_and_program",
  "rewards": [
    {
      "id": "1",
      "name": "Sticker pack",
      "type": "physical",
      "referrals_needed": 2,
      "description": "",
      "disclaimer": "",
      "image_url": "",
      "tag": "referral-sticker",
      "auto_fulfill": false,
      "template_id": null,
      "email_after_review": false
    },
    {
      "id": "2",
      "name": "10% off",
      "type": "promo_code",
      "referrals_needed": 5,
      "description": "A discount code.",
      "disclaimer": "",
      "image_url": "",
      "tag": "",
      "auto_fulfill": true,
      "template_id": 279,
      "email_after_review": true,
      "promo_codes_total": 2,
      "promo_codes_left": 1
    }
  ]
}
```

| Field | Meaning |
|---|---|
| `enabled` | `false` when the program is off. Each merge tag of the plugin is then empty |
| `template` | The template of the email block: `default`, `upcoming_milestone`, `reward_program` or `upcoming_and_program` |
| `type` | `physical`, `digital` or `promo_code` |
| `referrals_needed` | The milestone of the reward |
| `template_id` | The email template of the milestone email, or `null` |
| `promo_codes_total`, `promo_codes_left` | Only on a `promo_code` reward: the size of the pool and the codes that are not given yet |

## The numbers

```bash
curl https://your-broadcast-server/api/plugins/broadcast.referrals/stats \
  -H "Authorization: Bearer YOUR_TOKEN"
```

```json
{
  "subscribers_with_referrals": 8,
  "total_referred": 21,
  "referrals_per_subscriber": 2.63,
  "pending_referrals": 2
}
```

A pending referral is a person who signed up through a link and is not confirmed.

## One subscriber

Give `id` or `email`.

```bash
curl "https://your-broadcast-server/api/plugins/broadcast.referrals/subscriber?email=ada@example.com" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

```json
{
  "subscriber_id": 3141695,
  "email": "ada@example.com",
  "referral_code": "r1vc5b",
  "referral_link": "https://example.com/join?ref=r1vc5b",
  "referrals": 5,
  "pending_referrals": 0,
  "referred": [
    { "id": 3141781, "email": "ben@example.com", "status": "counted", "at": "2026-11-12T02:31:44.046Z" }
  ],
  "rewards": [
    {
      "key": "earned:8205549236885:3141695:2",
      "subscriber_id": 3141695,
      "email": "ada@example.com",
      "reward_id": "2",
      "reward_name": "10% off",
      "required": 5,
      "status": "fulfilled",
      "promo_code": "LIVE-1",
      "earned_at": "2026-11-12T02:32:43.114Z"
    }
  ]
}
```

| Field | Meaning |
|---|---|
| `referral_link` | The signup page address with the code. `null` when the signup page address is not set |
| `referrals` | The referrals that count |
| `referred` | The people whom the subscriber referred. `status` is `counted` or `pending` |
| `rewards` | The rewards that the subscriber earned |

| Status | Code | When |
|---|---|---|
| 422 | `invalid` | No `id` and no `email` |
| 404 | `not_found` | No subscriber with this id or email in the channel |

## Earned rewards

```bash
curl "https://your-broadcast-server/api/plugins/broadcast.referrals/fulfillment?status=pending" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

| Parameter | Rule |
|---|---|
| `status` | Optional. `pending`, `fulfilled` or `ignored` |
| `email` | Optional. Rows whose subscriber email has this text |
| `page` | Optional. The first page is `0`. A page has 25 rows |

```json
{
  "rows": [
    {
      "key": "earned:8205549236885:3141695:2",
      "subscriber_id": 3141695,
      "email": "ada@example.com",
      "reward_id": "2",
      "reward_name": "10% off",
      "required": 5,
      "status": "pending",
      "promo_code": "",
      "earned_at": "2026-11-12T02:32:43.114Z"
    }
  ],
  "matched": 1,
  "page": 0,
  "pages": 1
}
```

The rows are newest first. `matched` is the number of rows of all pages. The list reads the newest 1,000 earned rewards.

A `status` that is not in the list gets `422 invalid`.

## Mark a reward

Use the `key` of a row to set its status, for example after your shop sent the reward.

```bash
curl -X POST https://your-broadcast-server/api/plugins/broadcast.referrals/fulfill \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "key": "earned:8205549236885:3141695:2", "status": "fulfilled" }'
```

The answer is `200` with the row and its new status.

| Status | Code | When |
|---|---|---|
| 422 | `invalid` | `status` is not `pending`, `fulfilled` or `ignored` |
| 404 | `not_found` | No earned reward has this `key` |

## Errors

An error answer has this shape:

```json
{ "error": { "code": "invalid", "message": "Give id or email." } }
```
