---
title: Apply Coupon
description: Apply a coupon to a subscription.
---

Required for :badge{label="Apply Discount Offer"} to work.

To implement the `Apply Coupon` action, you need to implement an endpoint and define `features`

## Prerequisites
::grid{cols="2"}
    ::card-baseline{title="Subscriptions - Controller" to="/integrations/controllers/subscriptions"}
      You must implement a `Subscriptions` controller first.
      ::flex{class="mt-4"}
        :badge{label="Required" color="green"}
      ::
    ::
    ::card-baseline{title="Coupons - Controller" to="/integrations/controllers/coupons"}
      You must implement a `Coupons` controller first.
      ::flex{class="mt-4"}
        :badge{label="Required" color="green"}
      ::
    ::
    ::card-baseline{title="Cancel - Action" to="/integrations/actions/cancel"}
      Coupon application is a part of the Cancel Flow. You must implement the `Cancel` action first.
      ::flex{class="mt-4"}
        :badge{label="Required" color="green"}
      ::
    ::
::

## SDK
If you are using the SDK, you can implement the `Apply Coupon` action 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 { Subscriptions } from '../controllers/Subscriptions'
import { Coupons } from '../controllers/Coupons'

export const ApplyCoupon = Integrator.ApplyCoupon.config({
    Subscriptions: Subscriptions,
    Coupons: Coupons,
    features: {
        enabled: true
    },
    async handle(ctx, options) {
        const subscription = await this.subscriptions.retrieve({
            customerId: options.customerId,
            id: options.subscriptionId
        })

        const coupon = await this.coupons.retrieve({
            id: options.coupon
        })

        await ctx.db.applyCoupon({ subscription, coupon })
    }
})
```
::

## Endpoints

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

`POST /churnkey/actions/subscription/apply-coupon`

This endpoint applies coupon to a subscription. You should find the subscription by `customerId` and `subscriptionId` and apply coupon to it.

Options for this action, provided in the request body.

::collapsible{name="request body"}
  :field-schema{schema="/types/actions/apply-coupon/request.type.json"}
::

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

::collapsible{name="code example"}
  ::code-group
  ```typescript [Typescript Express]
    app.post('/churnkey/actions/subscription/apply-coupon', async (req, res) => {
        const subscription = await db.findSubscription(req.body.customerId, req.body.subscriptionId)
        const coupon = await db.findCoupon(req.body.id)

        await db.applyCoupon({subscription, coupon})
        res.send()
    })
  ```
  ::
::

## Features :badge{label="required" color="green"}

Features define which behavior is supported for the `Apply Coupon` action. Depending on the features you enabled, requests body will have different options.

::collapsible{name="schema"}
  :field-schema{schema="/types/actions/apply-coupon/features.type.json"}
::
::collapsible{name="code example"}
  ::code-group
  ```typescript [Typescript]
  export interface Features {
    enabled: boolean
  }

  export const features: Features = {
    enabled: true,
  }
  ```
::
