---
title: Subscriptions - Controller
description: List and retrieve `Subscription` models.
---

To implement the `Subscriptions` controller, you need to implement 2 API endpoints, we will use these endpoints to fetch subscriptions from your system.

## Prerequisites
::grid{cols="2"}
    ::card-baseline{title="Subscription Model" to="/integrations/models/subscription"}
    Subscription to a product or service.

    ::flex{class="mt-4"} 
      :badge{label="Required" color="green"}
    ::
    ::
    ::card-baseline{title="Prices - Controller" to="/integrations/controllers/prices"}
    You must implement a `Prices` controller first.

    ::flex{class="mt-4"} 
      :badge{label="Required" color="green"}
    ::
    ::
    ::card-baseline{title="Coupons - Controller" to="/integrations/controllers/coupons"}
    If you have subscription-level discounts, you may need to implement a `Coupons` controller first.

    ::flex{class="mt-4"} 
      :badge{label="Optional"}
      :badge{label="Discount Offer"}
    ::
    ::
::

## SDK

If you are using the SDK, you can implement the `Subscriptions` controller by following the code example below. You don't need to get into the details of the API endpoints, the SDK will take care of that for you.

::code-group
```typescript [Typescript]
import { Integrator } from '@churnkey/sdk'
import { Context } from '../Context'
import { Subscription } from '../models/Subscription'
import { Prices } from './Prices'

export const Subscriptions = Integrator.Subscriptions.config({
    ctx: Context,
    Prices: Prices,
    async retrieve(ctx, options) {
        const yourSubscription = await ctx.db.findSubscription(options.customerId, options.id)
        return new Subscription(yourSubscription)
    },
    async list(ctx, options) {
        const yourSubscriptions = await ctx.db.listSubscriptions({
            customerId: options.customerId,
            limit: options.limit,
            offset: options.cursor // the value you passed as `next` below
        })
        return {
            data: yourSubscriptions.map(subscription => new Subscription(subscription)),
            // pass the next cursor if there are more items
            next: yourSubscriptions.length === options.limit ? offset + limit : undefined
        }
    }
})
```
::

## Endpoints

###  Retrieve :badge{label="Required" color="green"}

`GET /churnkey/customers/:customerId/subscriptions/:id`

This endpoint fetches `Subscription` by its `id`. Usually, implementation will include finding a subscription in your database and mapping it to the [Subscription model](/integrations/models/subscription).

::collapsible{name="response"}
    ::tabs
        ::div{label="200"}
        Must return `Subscription` model. See [Subscription model documentation](/integrations/models/subscription).
        ::
        ::div{label="Error"}
        See [Error Responses](/integrations/general#error-responses).
        ::
    ::
::

::collapsible{name="code example"}
    ::code-group
    ```typescript [Typescript Express]
    import { Subscription } from '../models/Subscription'

    app.get('/churnkey/customers/:customerId/subscriptions/:id', async (req, res) => {
        const subscription = await db.findSubscriptionById(req.params.id)
        if (!subscription) {
            return res.status(404).send({ code: 404, message: 'Subscription not found' })
        }
        res.send(new Subscription(subscription))
    })
    ```
    ::
::

### List :badge{label="Optional"}
`GET /churnkey/customers/:customerId/subscriptions`

This endpoint fetches a list of subscriptions from your database. You should find subscriptions in your database (with pagination), map them to the `Subscription` model and return a paginated list.

[Learn more about pagination](/integrations/general#pagination).

::collapsible{name="query parameters"}
  :field-schema{schema="/types/pagination-query.type"}
::
::collapsible{name="response"}
  :field-schema{schema="/types/pagination-response.type"}
::

::collapsible{name="code example"}
    ::code-group
    ```typescript [Typescript Express]
    import { Subscription } from '../models/Subscription'

    app.get('/churnkey/customers/:customerId/subscriptions', async (req, res) => {
        const limit = Number.parseInt(req.query.limit)
        const offset = Number.parseInt(req.query.cursor) 
        const subscriptions = await db.findSubscriptions({ 
            limit, offset, 
            customerId: req.params.customerId 
        })
        res.send({
            data: subscriptions.map(c => new Subscription(c)),
            next: subscriptions.length === limit ? offset + limit : undefined
        })
    })
    ```
    ::
::
