> For the complete documentation index, see [llms.txt](https://startbutton.gitbook.io/startbutton-product-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://startbutton.gitbook.io/startbutton-product-api/collections/subscriptions.md).

# Subscriptions

> Currently supports subscription plan creation for NGN, GHS, ZAR, and USD only.

| Header        | Value                                                                                                  |
| ------------- | ------------------------------------------------------------------------------------------------------ |
| Authorization | `Bearer SECRET_KEY` (see [Authentication](/startbutton-product-api/getting-started/authentication.md)) |
| Content-Type  | `application/json`                                                                                     |

See [Environments & Base URLs](/startbutton-product-api/getting-started/environments-and-base-urls.md) before making requests.

#### Create Subscription Plan

**Endpoint:** `POST {{baseUrl}}/subscription/api`

Sample request:

```json
{
    "name": "Free trial subscription 7",
    "description": "This is a Free trial Subscription Test",
    "frequency": "monthly",
    "currency": "NGN",
    "type": "fixed",
    "amount": 1000,
    "initialAmount": "500",
    "freeTrial": true,
    "freeTrialPeriod": 5,
    "endDate": "2025-06-30",
    "notificationSettings": {
        "freeTrial": { "enabled": true, "period": 3 }
    }
}
```

Sample response:

```json
{
    "success": true,
    "message": "Success",
    "data": {
        "subscription": {
            "name": "Free trial subscription 7",
            "description": "This is a Free trial Subscription Test",
            "amount": 10,
            "frequency": "monthly",
            "merchantId": "64xxxxxxxx",
            "link": "http:subscription/3935daxxx",
            "currency": "NGN",
            "code": "39xxxxxx",
            "status": "active",
            "deleted": false,
            "endDate": "2025-06-30T00:00:00.000Z",
            "type": "fixed",
            "notificationSettings": { "freeTrial": { "enabled": false, "period": 3 } },
            "_id": "67xxxxxxxxxxxxxxxx",
            "createdAt": "2025-04-02T06:11:42.501Z",
            "updatedAt": "2025-04-02T06:11:42.501Z",
            "__v": 0
        }
    }
}
```

#### Deactivate a Subscription Plan

Allows you to cancel or deactivate an active subscription plan.

**Endpoint:** `POST {{baseUrl}}/subscription/api/:planId`

| Path variable | Required? |
| ------------- | --------- |
| planId        | Yes       |

Sample request:

<pre class="language-json"><code class="lang-json">{ 
<strong>   "status": "canceled", 
</strong>   "reason": "completed" 
}
</code></pre>

Sample response:

```json
{
    "success": true,
    "message": "Success",
    "data": {
        "type": "fixed",
        "_id": "67xxxxxxxxxxxxx",
        "name": "Test",
        "description": "Testing subs",
        "amount": 500,
        "frequency": "monthly",
        "merchantId": "66xxxxxxxxxxxxx",
        "link": "http://pay.startbuttonsubscription/b7xxxxxx",
        "currency": "NGN",
        "code": "b7xxxxxx",
        "status": "canceled",
        "deleted": false,
        "numberOfPaymentsExpected": 5
    }
}
```

#### Get Subscribers

Retrieves details of all subscribers on a subscription plan, with optional status filtering.

**Endpoint:** `GET {{baseUrl}}/subscribers`

| Query param        | Required? | Description                             |
| ------------------ | --------- | --------------------------------------- |
| subscriptionPlanId | Yes       | The subscription plan ID                |
| status             | No        | `activated`, `completed`, or `canceled` |

> Note: if a plan wasn't created with an `endDate`, none is returned for it.

Sample response:

```json
{
    "_id": "609xxxxxxxxxxx",
    "subscriberId": {
        "email": "test@test.com",
        "nameOnCard": null,
        "deleted": false,
        "createdAt": "2025-03-07T01:28:47.314Z",
        "updatedAt": "2025-03-08T04:07:50.929Z",
        "id": "67xxxxxxxxxxxxxxx"
    }
}
```

#### Cancel Subscriber (merchant-facing)

Cancels a subscriber from a subscription plan, removing their access to a previously active plan. Retrieve the subscriber's ID via [Subscriptions](/startbutton-product-api/collections/subscriptions.md#get-subscribers) first.

**Endpoint:** `PATCH {{baseUrl}}/subscribers/:subscriberId/update-status`

| Path variable | Required? | Description         |
| ------------- | --------- | ------------------- |
| subscriberId  | Yes       | The subscriber's ID |

Sample payload:

```json
{
   "status": "canceled", 
   "reason": "this is the end"
 }
```

Sample response:

```json
{
    "success": true,
    "message": "success",
    "data": {
        "subscriber": {
            "_id": "678xxxxxxxxxxxxx",
            "subscriberId": "678xxxxxxxxxxxx",
            "planId": "678xxxxxxxxxxxxxxxxxxxx",
            "merchantId": "678xxxxxxxxxx",
            "frequency": "monthly",
            "reason": "this is the end"
        }
    }
}
```

#### Cancel Subscription (customer-facing)

Lets you integrate an "unsubscribe"/"cancel" function into your customer-facing UI, allowing a subscriber to opt out themselves. Retrieve the subscriber's ID via [Get Subscribers](#get-subscribers) first.

**Endpoint:** `POST {{baseUrl}}/subscribers/cancel-customer-initiated`

Sample payload:

```json
{
    "status": "canceled",
    "reason": "service no longer needed" 
}
```

Sample response (API):

```json
{
    "success": true,
    "message": "Subscription canceled successfully",
    "data": {
        "subscriber": {
            "_id": "69282ae11xxxxxxx",
            "subscriberId": "69282ae11bcxxxxx",
            "planId": "692823ec86cxxxxxx",
            "merchantId": "68bc35e39xxxxxxxx",
            "frequency": "monthly",
            "amount": 2000,
            "initialAmount": 0,
            "nextPaymentDate": "2025-12-27T10:41:37.711Z",
            "lastPaymentDate": "2025-11-27T10:41:37.711Z",
            "initialLastPaymentDate": "2025-12-27T10:41:37.711Z",
            "endDate": "2026-01-09T00:00:00.000Z",
            "numberOfPayments": 1,
            "status": "canceled",
            "retryCount": 0,
            "createdAt": "2025-11-27T10:41:37.723Z",
            "updatedAt": "2025-11-27T14:08:41.850Z",
            "__v": 0,
            "reason": "unimportant"
        },
        "cancellationOrigin": "CUSTOMER_SELF_SERVICE"
    }
}
```

Sample webhook event:

```json
{
  "event": "subscription.canceled.customer",
  "data": {
    "subscription": {
      "subscriptionId": "69282ae11bcxxxxxxx",
      "subscriptionPlanId": "692823ec86cedxxxxxx",
      "nameOfPlan": "testing sub",
      "subscriberEmail": "tester@yopmail.com",
      "subscriberName": "",
      "status": "canceled",
      "reason": "unimportant",
      "cancellationOrigin": "CUSTOMER_SELF_SERVICE",
      "source": "Customer-initiated cancellation via merchant UI.",
      "canceledAt": "2025-11-27T14:08:41.897Z"
    }
  }
}
```

#### Subscription FAQs

1. **How can we identify the subscription plan the user paid for, from the webhook response?** The payment code returned in the webhook response matches the code on the subscription link.
2. **If a subscription charge attempt fails, will it be retried in the next billing cycle?** Yes, until the number of expected payment cycles is completed, it retries in the next billing cycle.
