---
title: Cable TV
description: Subscribe to DStv, GOtv, and Startimes
---

Renew cable TV subscriptions for DStv, GOtv, and Startimes.

## Supported Providers

| Provider    | Description      |
| ----------- | ---------------- |
| `DSTV`      | MultiChoice DStv |
| `GOTV`      | MultiChoice GOtv |
| `STARTIMES` | StarTimes        |

## Purchase Flow

Cable TV purchases require a **two-step process**:

1. **Verify** - Validate the smart card/decoder number
2. **Purchase** - Make the subscription payment

## Step 1: List Products

List available packages for a provider:

```bash
curl -X GET \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  "https://my.rizpay.app/api/partners/v1/products/cabletv?provider=GOTV"
```

Response:

```json
{
  "status": { "code": 200, "message": "Success" },
  "data": [
    {
      "id": "prd_7640",
      "type": "cable_tv",
      "attributes": {
        "display_name": "GOtv Smallie (Monthly)",
        "service": "GOTV",
        "package": "GOtv Smallie (Monthly)",
        "price": {
          "amount": "1896.00",
          "currency": "NGN",
          "basis": "fixed"
        }
      }
    },
    {
      "id": "prd_7806",
      "type": "cable_tv",
      "attributes": {
        "display_name": "GOtv Smallie - monthly N1900",
        "service": "GOTV",
        "package": "GOtv Smallie - monthly N1900",
        "price": {
          "amount": "1877.20",
          "currency": "NGN",
          "basis": "fixed"
        }
      }
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_pages": 6,
    "total_count": 103
  }
}
```

Product ids are numeric with a `prd_` prefix (e.g. `prd_7640`). Use the
`id` from your own response in the purchase request.

### The `price` block

Cable TV packages are catalog-priced. The `fixed` price is what RizPay
will bill you for that subscription. Add your margin on top before
charging your end-user.

## Step 2: Verify Decoder

**Required before purchase.** Validates the decoder and returns customer details.

```bash
curl -X POST \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_7640",
    "smart_number": "1234567890"
  }' \
  https://my.rizpay.app/api/partners/v1/purchases/verify
```

Response:

```json
{
  "status": { "code": 200, "message": "Verification successful" },
  "data": {
    "verified": true,
    "product_id": "prd_7640",
    "product_type": "cable_tv",
    "price": {
      "amount": "1896.00",
      "currency": "NGN",
      "basis": "fixed"
    },
    "customer": {
      "smart_number": "1234567890",
      "customer_name": "JOHN DOE",
      "current_bouquet": "GOtv Jolli",
      "due_date": "2024-01-20"
    }
  }
}
```

The `price` block on verify is the fixed subscription cost the partner
will be billed if they go through with the purchase.

### Verification Errors

If the smart card or decoder number cannot be validated, verify returns a
`400` with `error.code` set to `VALIDATION_ERROR` and a message describing
the problem. If the provider itself is unavailable, purchases for that
product return `PRODUCT_UNAVAILABLE`.

| Error                 | Meaning                                         |
| --------------------- | ----------------------------------------------- |
| `VALIDATION_ERROR`    | Smart card/decoder number could not be verified |
| `PRODUCT_UNAVAILABLE` | Provider service is down                        |

## Step 3: Make Purchase

After verification, make the subscription payment:

```bash
curl -X POST \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_7640",
    "smart_number": "1234567890",
    "amount": "1896.00",
    "service": "GOTV",
    "phone_number": "08012345678",
    "external_reference": "1736234400E5F6G7"
  }' \
  https://my.rizpay.app/api/partners/v1/purchases
```

Include the `service` matching the package you selected (for example
`GOTV`, `DSTV`, or `STARTIMES`).

Response:

```json
{
  "status": { "code": 201, "message": "Purchase created successfully" },
  "data": {
    "id": "txn_abc123",
    "type": "transaction",
    "attributes": {
      "amount": "1896.0",
      "currency": "NGN",
      "status": "pending",
      "category": "purchase",
      "description": "Purchase of GOtv Smallie (Monthly)",
      "reference": "cable0order0001abcd",
      "external_reference": "1736234400E5F6G7",
      "product_type": "cable_tv",
      "phone_number": "08012345678",
      "meter_number": null,
      "price": {
        "product_amount": "1896.00",
        "fee_amount": "0.00",
        "total_debit": "1896.00",
        "currency": "NGN",
        "basis": "fixed"
      },
      "created_at": "2026-05-18T10:30:00+01:00",
      "updated_at": "2026-05-18T10:30:00+01:00"
    }
  }
}
```

### The `price` breakdown

Same shape as the other product types. `basis` is `fixed` for cable TV.

## Successful Purchase

Poll the transaction (or use webhooks) until `status` reaches
`successful`. The completed purchase uses the same nested shape as the
create response, with `status` updated:

```json
{
  "status": { "code": 200, "message": "Purchase details retrieved" },
  "data": {
    "id": "txn_abc123",
    "type": "transaction",
    "attributes": {
      "amount": "1896.0",
      "currency": "NGN",
      "status": "successful",
      "category": "purchase",
      "description": "Purchase of GOtv Smallie (Monthly)",
      "reference": "cable0order0001abcd",
      "external_reference": "1736234400E5F6G7",
      "product_type": "cable_tv",
      "phone_number": "08012345678",
      "meter_number": null,
      "price": {
        "product_amount": "1896.00",
        "fee_amount": "0.00",
        "total_debit": "1896.00",
        "currency": "NGN",
        "basis": "fixed"
      },
      "created_at": "2026-05-18T10:30:00+01:00",
      "updated_at": "2026-05-18T10:30:05+01:00"
    }
  }
}
```

The subscription is activated automatically. No token or manual action
required. There is no separate completion timestamp: use `updated_at`.

## Complete Example

```javascript
// Generate external reference: 10-digit timestamp + 6 alphanumeric
function generateReference() {
  const timestamp = Math.floor(Date.now() / 1000);
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let suffix = "";
  for (let i = 0; i < 6; i++) {
    suffix += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return `${timestamp}${suffix}`;
}

async function subscribeCableTV(smartNumber, packageId, phoneNumber) {
  const API_KEY = "sk_live_your_secret_key";
  const BASE_URL = "https://my.rizpay.app/api/partners/v1";

  // Step 1: Find the package
  const productsRes = await fetch(
    `${BASE_URL}/products/cabletv?provider=GOTV`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const products = await productsRes.json();
  const product = products.data.find((p) => p.id === packageId);

  if (!product) {
    throw new Error("Package not found");
  }

  // Step 2: Verify decoder
  const verifyRes = await fetch(`${BASE_URL}/purchases/verify`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      product_id: product.id,
      smart_number: smartNumber,
    }),
  });

  const verification = await verifyRes.json();
  if (!verification.data.verified) {
    throw new Error("Invalid decoder number");
  }

  // Show customer details for confirmation
  console.log(
    `Subscribing ${verification.data.customer.customer_name} to ${product.attributes.package}`
  );

  // Step 3: Make purchase
  const purchaseRes = await fetch(`${BASE_URL}/purchases`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      product_id: product.id,
      smart_number: smartNumber,
      amount: product.attributes.price.amount,
      service: product.attributes.service,
      phone_number: phoneNumber,
      external_reference: generateReference(),
    }),
  });

  return await purchaseRes.json();
}
```

## Package Changes

Customers can:

- **Upgrade** - Subscribe to a higher package
- **Downgrade** - Subscribe to a lower package (applies at renewal)
- **Renew** - Extend their current package

The verification response shows the current package, helping you guide customers.

## DStv Packages

| Package           | Typical Price |
| ----------------- | ------------- |
| DStv Premium      | ~24,500       |
| DStv Compact Plus | ~16,600       |
| DStv Compact      | ~10,500       |
| DStv Confam       | ~6,200        |
| DStv Yanga        | ~3,500        |
| DStv Padi         | ~2,500        |

## GOtv Packages

| Package      | Typical Price |
| ------------ | ------------- |
| GOtv Supa+   | ~9,600        |
| GOtv Supa    | ~6,400        |
| GOtv Max     | ~7,200        |
| GOtv Jolli   | ~4,850        |
| GOtv Jinja   | ~2,700        |
| GOtv Smallie | ~1,575        |

_Prices may vary. Always check the products endpoint for current pricing._

## Required Scope

Requires the `purchase_cable_tv` scope on your API key.

## Next Steps

- [Electricity](/docs/products/electricity) - Pay electricity bills
- [Webhooks](/docs/webhooks/overview) - Get notified when subscription activates