# Coupons

> Create, retrieve, update, delete, and list discount coupons.

A coupon is a discount code that customers can redeem at checkout to reduce the amount they are
charged. Coupons support percentage-based and fixed-amount discounts, and can be configured with
usage limits and duration rules.

> **Illustrative content.** Hand-authored to demonstrate the Standard/Advanced pattern; the production
> page will be generated from the VINR OpenAPI spec (roadmap item #1). Field names are representative.

## The coupon object

- **id** `string` — Unique identifier for the coupon, e.g. `cpn_5Hx1pR`.
- **name** `string` — Human-readable name or code that customers enter at checkout, e.g. `SUMMER20`.
- **percent\_off** `number` — Percentage discount applied when this coupon is redeemed. Mutually exclusive with `amount_off`.
- **amount\_off** `integer` — Fixed discount amount in the smallest currency unit. Mutually exclusive with `percent_off`.
- **currency** `string` — Three-letter [ISO currency code](/docs/payments/payment-methods), required when `amount_off` is
  set, e.g. `USD`.
- **duration** `enum` — One of `once` (applied to the first invoice only), `repeating` (applied to recurring invoices
  for a set number of months), or `forever` (applied to all invoices).
- **times\_redeemed** `integer` — Total number of times this coupon has been redeemed.
- **max\_redemptions** `integer` — Maximum number of times this coupon can be redeemed. `null` means unlimited.
- **valid** `boolean` — `true` if the coupon can still be redeemed (`times_redeemed` has not reached `max_redemptions`
  and it has not been deleted).
- **created** `integer` — Unix timestamp when this coupon was created.

## Create a coupon

Provide either `percent_off` or `amount_off` (with `currency`). Set `max_redemptions` to cap total
usage.

`POST /v1/coupons`

```bash
curl -X POST https://api.vinr.com/v1/coupons \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d name=SUMMER20 \
-d percent_off=20 \
-d duration=once \
-d max_redemptions=500
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const coupon = await vinr.coupons.create({
name: 'SUMMER20',
percent_off: 20,
duration: 'once',
max_redemptions: 500,
});
```

```python
import vinr

coupon = vinr.Coupon.create(
  name="SUMMER20",
  percent_off=20,
  duration="once",
  max_redemptions=500,
)
```

```ruby
coupon = Vinr::Coupon.create(
name: 'SUMMER20',
percent_off: 20,
duration: 'once',
max_redemptions: 500,
)
```

```json
{
"id": "cpn_5Hx1pR",
"name": "SUMMER20",
"percent_off": 20,
"amount_off": null,
"currency": null,
"duration": "once",
"times_redeemed": 0,
"max_redemptions": 500,
"valid": true,
"created": 1716300000
}
```

## Retrieve a coupon

Fetch a coupon by its ID.

`GET /v1/coupons/{id}`

```bash
curl https://api.vinr.com/v1/coupons/cpn_5Hx1pR \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const coupon = await vinr.coupons.retrieve('cpn_5Hx1pR');
```

```python
import vinr

coupon = vinr.Coupon.retrieve("cpn_5Hx1pR")
```

```ruby
coupon = Vinr::Coupon.retrieve('cpn_5Hx1pR')
```

```json
{
"id": "cpn_5Hx1pR",
"name": "SUMMER20",
"percent_off": 20,
"amount_off": null,
"currency": null,
"duration": "once",
"times_redeemed": 37,
"max_redemptions": 500,
"valid": true,
"created": 1716300000
}
```

## Update a coupon

Update the coupon's display name or raise the redemption cap. Discount values and duration are
immutable after creation.

| Parameter         | Type    | Description                                     |
| ----------------- | ------- | ----------------------------------------------- |
| `name`            | string  | New human-readable name or code for the coupon. |
| `max_redemptions` | integer | Raise (not lower) the maximum redemption limit. |

`POST /v1/coupons/{id}`

```bash
curl -X POST https://api.vinr.com/v1/coupons/cpn_5Hx1pR \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d max_redemptions=1000
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const coupon = await vinr.coupons.update('cpn_5Hx1pR', {
max_redemptions: 1000,
});
```

```python
import vinr

coupon = vinr.Coupon.modify(
  "cpn_5Hx1pR",
  max_redemptions=1000,
)
```

```ruby
coupon = Vinr::Coupon.update(
'cpn_5Hx1pR',
max_redemptions: 1000,
)
```

```json
{
"id": "cpn_5Hx1pR",
"name": "SUMMER20",
"percent_off": 20,
"amount_off": null,
"currency": null,
"duration": "once",
"times_redeemed": 37,
"max_redemptions": 1000,
"valid": true,
"created": 1716300000
}
```

## Delete a coupon

Permanently deletes a coupon. It can no longer be redeemed. Existing redemptions are not affected.

`DELETE /v1/coupons/{id}`

```bash
curl -X DELETE https://api.vinr.com/v1/coupons/cpn_5Hx1pR \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const deleted = await vinr.coupons.delete('cpn_5Hx1pR');
```

```python
import vinr

deleted = vinr.Coupon.delete("cpn_5Hx1pR")
```

```ruby
deleted = Vinr::Coupon.delete('cpn_5Hx1pR')
```

```json
{
"id": "cpn_5Hx1pR",
"deleted": true
}
```

## List coupons

Returns a paginated list of coupons, newest first.

| Parameter | Type    | Description                                           |
| --------- | ------- | ----------------------------------------------------- |
| `limit`   | integer | Number of results to return. Default `10`, max `100`. |

`GET /v1/coupons`

```bash
curl "https://api.vinr.com/v1/coupons?limit=10" \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const coupons = await vinr.coupons.list({ limit: 10 });
```

```python
import vinr

coupons = vinr.Coupon.list(limit=10)
```

```ruby
coupons = Vinr::Coupon.list(limit: 10)
```

```json
{
"object": "list",
"data": [
  {
    "id": "cpn_5Hx1pR",
    "name": "SUMMER20",
    "percent_off": 20,
    "duration": "once",
    "times_redeemed": 37,
    "max_redemptions": 1000,
    "valid": true,
    "created": 1716300000
  }
],
"has_more": false
}
```

## Related events

`coupon.created`, `coupon.updated`, and `coupon.deleted`. See [Events](/docs/api-reference/events).
