---
title: Prices - Controller
description: List and retrieve `Price` models.
---

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

## Prerequisites
::grid{cols="2"}
    ::card-baseline{title="Price Model" to="/integrations/models/price"}
    A price for a product or service.
    <br/><br/> :badge{label="Required" color="green"}
    ::
    ::card-baseline{title="Products - Controller" to="/integrations/controllers/products"}
    If you chose to implement prices with products, you must implement a `Products` controller first.
    <br/><br/> :badge{label="Optional"}
    ::
::

## SDK

If you are using the SDK, you can implement the `Prices` 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 { Price } from '../models/Price'
// import { Products } from './Products'

export const Prices = Integrator.Prices.config({
    ctx: Context,
    type: Integrator.Price.Type.Standalone,
    // type: Integrator.Price.Type.Product,
    // Products: Products, 
    async retrieve(ctx, options) {
        const yourPrice = await ctx.db.findPrice(options.id)
        return new Price(yourPrice)
    },
    async list(ctx, options) {
        const yourPrices = await ctx.db.listPrices({
            limit: options.limit,
            offset: options.cursor // the value you pass as `next` below
        })
        return {
            data: yourPrices.map(price => new Price(price)),
            // pass the next cursor if there are more items
            next: yourPrices.length === options.limit ? offset + limit : undefined
        }
    }
})
```
::


## Endpoints

### Retrieve :badge{label="Required" color="green"}
`GET /churnkey/prices/:id`

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


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

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

    app.get('/churnkey/prices/:id', async (req, res) => {
        const price = await db.findPriceById(req.params.id)
        if (!price) {
            return res.status(404).send({ code: 404, message: 'Price not found' })
        }
        res.send(new Price(price))
    })
    ```
    ::
::

### List :badge{label="Required" color="green"}
`GET /churnkey/prices`

This endpoint fetches a list of prices from your database. You should find prices in your database (with pagination), map them to the `Price` 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 { Price } from '../models/Price'

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


