> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rankly.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Premium Plans

> How Rankly premium purchases, plan types, and billing state work.

Premium is the part of Rankly that lets users pay for bot or server upgrades with the platform's credit system.

## What premium covers

* Bot premium tiers
* Server premium tiers
* Weekly, monthly, and lifetime durations
* Gifted purchases
* Order history and transaction tracking
* Premium lifecycle webhooks for purchases, renewals, expirations, and revocations

## How a purchase works

<Steps>
  <Step title="Choose a target">
    Premium can be attached to a bot or a server, depending on what the product offers.
  </Step>

  <Step title="Choose a tier">
    Tiers define the price, duration, and plan type that will be charged.
  </Step>

  <Step title="Confirm the credit balance">
    Rankly checks the purchaser's available credits before the order is created.
  </Step>

  <Step title="Store the resulting state">
    Keep your own internal record of the plan, the expiry, and whether the purchase was gifted.
  </Step>
</Steps>

## Premium webhooks

For bot premium plans, Rankly sends signed webhook events to your configured premium webhook URL.

### Headers

* `X-Webhook-Signature`: HMAC SHA-256 signature of the exact JSON body
* `Content-Type`: `application/json`

### Signature verification (Node.js)

```javascript theme={null}
import crypto from 'crypto';

function verifyRanklySignature(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected, 'utf8'),
    Buffer.from(signatureHeader || '', 'utf8')
  );
}
```

Use the raw request body for verification before parsing or mutating payload fields.

## Plan types

| Plan type | Meaning                                    |
| --------- | ------------------------------------------ |
| Weekly    | Renew or expire on a 7-day cycle.          |
| Monthly   | Renew or expire on a 30-day cycle.         |
| Lifetime  | Stays active until it is manually revoked. |

## Event types you can receive

| Event                  | Meaning                                                | Common reason                             |
| ---------------------- | ------------------------------------------------------ | ----------------------------------------- |
| `premium_purchase`     | A premium order was created successfully.              | New checkout completed                    |
| `subscription.renewed` | A recurring plan was renewed.                          | Auto-renew succeeded                      |
| `subscription.expired` | A recurring plan was ended.                            | Past due, invalid buyer, tier unavailable |
| `subscription.revoked` | A plan was revoked and should be disabled immediately. | Chargeback/dispute                        |

## Webhook payload examples

### `premium_purchase`

```json theme={null}
{
  "event": "premium_purchase",
  "purchaseId": "682f4d8e8c4a93b75ad69f90",
  "orderId": "682f4d8e8c4a93b75ad69f90",
  "timestamp": "2026-05-24T12:00:00.000Z",
  "buyer": {
    "userId": "123456789012345678",
    "username": "Skyline"
  },
  "recipient": null,
  "isGift": false,
  "giftedBy": null,
  "tier": {
    "id": "pro-monthly",
    "name": "Pro Monthly",
    "duration": "monthly",
    "planType": "user"
  },
  "serverId": null
}
```

### `subscription.renewed`

```json theme={null}
{
  "event": "subscription.renewed",
  "orderId": "682f4d8e8c4a93b75ad69f90",
  "purchaseId": "682f4d8e8c4a93b75ad69f90",
  "timestamp": "2026-05-24T13:00:00.000Z",
  "buyer": {
    "userId": "123456789012345678",
    "username": "Skyline"
  },
  "recipient": null,
  "isGift": false,
  "vendor": {
    "type": "bot",
    "id": "987654321098765432"
  },
  "tier": {
    "id": "pro-monthly",
    "name": "Pro Monthly",
    "duration": "monthly",
    "planType": "user"
  },
  "autoRenew": true,
  "status": "active",
  "currentPeriodEnd": "2026-06-24T13:00:00.000Z"
}
```

### `subscription.expired`

```json theme={null}
{
  "event": "subscription.expired",
  "orderId": "682f4d8e8c4a93b75ad69f90",
  "purchaseId": "682f4d8e8c4a93b75ad69f90",
  "timestamp": "2026-05-24T14:00:00.000Z",
  "buyer": {
    "userId": "123456789012345678",
    "username": "Skyline"
  },
  "recipient": null,
  "isGift": false,
  "vendor": {
    "type": "bot",
    "id": "987654321098765432"
  },
  "tier": {
    "id": "pro-monthly",
    "name": "Pro Monthly",
    "duration": "monthly",
    "planType": "user"
  },
  "autoRenew": true,
  "status": "past_due",
  "currentPeriodEnd": "2026-05-24T14:00:00.000Z",
  "reason": "past_due"
}
```

### `subscription.revoked`

```json theme={null}
{
  "event": "subscription.revoked",
  "orderId": "682f4d8e8c4a93b75ad69f90",
  "purchaseId": "682f4d8e8c4a93b75ad69f90",
  "timestamp": "2026-05-24T15:00:00.000Z",
  "buyer": {
    "userId": "123456789012345678",
    "username": "Skyline"
  },
  "recipient": null,
  "isGift": false,
  "vendor": {
    "type": "bot",
    "id": "987654321098765432"
  },
  "tier": {
    "id": "pro-monthly",
    "name": "Pro Monthly",
    "duration": "monthly",
    "planType": "user"
  },
  "autoRenew": true,
  "status": "revoked",
  "currentPeriodEnd": "2026-06-24T13:00:00.000Z",
  "reason": "chargeback_dispute"
}
```

## What could happen in production

* A user buys premium now: you get `premium_purchase`, then grant features immediately.
* The subscription renews a month later: you get `subscription.renewed`, and just extend access.
* Auto-renew fails: you get `subscription.expired`, and you should remove paid features.
* A chargeback happens after purchase: you get `subscription.revoked`, and you should disable access right away.
* A gift purchase is made: `isGift` is true and `recipient` is populated, so entitlement should be applied to the recipient.

## What to expect in your app

* A premium purchase becomes an order in Rankly's billing flow.
* The purchaser and recipient can be different users when the plan is gifted.
* The dashboard should always show the current status, not just the original purchase date.
* If you need to reflect the current plan in your bot, refresh your own cached state after checkout.

## Handler checklist

* Verify `X-Webhook-Signature` before processing.
* Deduplicate by `orderId` plus `event`.
* Make state transitions idempotent.
* Treat `subscription.revoked` as highest priority for entitlement removal.
* Return `2xx` quickly, then do heavy work async.

## Helpful implementation notes

* Keep tier IDs stable once users rely on them.
* Show the user what they are paying for before they confirm the purchase.
* Make expired plans obvious in the UI.
* Treat a billing failure as a recoverable state, not a fatal error.

## Related docs

<CardGroup cols={2}>
  <Card title="Credits" href="/servers/credits">
    See how premium purchases interact with balances.
  </Card>

  <Card title="Bot API Integration" href="/bots/api-integration">
    Pull plan state into your bot commands or dashboard.
  </Card>
</CardGroup>
