# Use a promo code

> Take a promo code's discount off an order, check a code before you order, and see which invoices the discount covers.

Source: https://www.coritan.com/docs/billing/promo-codes/

A *promo code* takes money off a service you order. You add the code when you place the order, and the discount shows as its own line on the invoice. Codes are not case sensitive, and spaces in them are ignored.

In the dashboard, the dialog that orders an account plan takes a promo code in **Promo code**, and **Apply** checks it before you order ([Order Pro or Business](/docs/billing/change-account-plan/#order-pro-or-business)). The order pages for other services have no field for a promo code, so you use one on them through the API: check it with `POST /billing/promo/validate`, then send it with the order.

## What a code gives you

Each code takes off one of these:

Percent off
: A share of the price of the product you order, and of its setup fee.

Amount off
: A fixed amount, taken off the price and then off the setup fee. It never takes off more than they cost.

And it covers one of these:

The first invoice
: The code discounts the order's first invoice only.

A number of invoices
: The code discounts that many invoices in a row. The first invoice counts as one, so `10% off the first 3 invoices` also discounts the next two renewals.

Every invoice
: The code discounts every invoice of the service for as long as you keep it.

A code can also have limits: the products it covers, a start and an end date, a number of uses in all, a number of uses per account (usually one), or your first order only. Products you add to the order, such as floating IPs or a DDoS Shield profile, are charged in full.

Once an order has a code, the discount carries on over every invoice the code covers, even if Coritan later switches the code off or its end date passes. When Coritan sets up an order without a first payment, as it can for a postpaid account, the discount starts on the service's first invoice. If an order's first invoice is cancelled before you pay it, the code counts as unused again.

## Before you begin

- Get an access token for the API. [Make your first API request](/docs/get-started/first-steps-with-the-api/) shows how.
- Find the `product_id` and `pricing_id` of what you want to order. [Order a service](/docs/get-started/order-a-service/#with-the-api) shows where they are.

## Check a code

[`POST /billing/promo/validate`](/docs/api/reference/client/promotions/#op-post-api-v1-billing-promo-validate) says whether your account can use a code and what it takes off a product. It does not use the code:

```bash
curl -X POST https://api.coritan.com/api/v1/billing/promo/validate \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"code": "spring25", "product_id": 7, "pricing_id": 21}'
```

`code`
: The code, in any case.

`product_id` and `pricing_id`
: Optional. The product and the plan you are about to order. Without `pricing_id`, the answer prices the product's cheapest plan. Without `product_id`, the answer only says whether your account can use the code.

This code gives 25% off the first 3 invoices, and plan `21` costs $12.00:

```json
{
  "valid": true,
  "code": "SPRING25",
  "message": "SPRING25 applied: 25% off the first 3 invoices.",
  "reason": null,
  "description": "Spring sale",
  "discount_preview": {
    "summary": "25% off the first 3 invoices",
    "kind": "percent",
    "amount": "25",
    "currency": "USD",
    "duration": "repeating",
    "cycles": 3,
    "product_id": 7,
    "pricing_id": 21,
    "price": "12.00",
    "discount": "3.00",
    "renewal_discount": "3.00"
  }
}
```

`valid`
: Whether your account can use the code on this product. A code you cannot use also answers `200`, with `"valid": false`, a `reason` and a `message` ([Troubleshooting](#troubleshooting)).

`discount` and `renewal_discount`
: What the code takes off the first invoice, and off each renewal it covers. `renewal_discount` is `0.00` for a code that covers the first invoice only.

`cycles`
: How many invoices the code discounts, the first one included. It is `null` for a code that covers every invoice.

`kind`, `amount` and `duration`
: `percent` or `fixed`; the percentage or the amount; and `once`, `repeating` or `forever`.

The order checks the code again, so a code can still be refused if its last use goes to someone else in between.

## Order with the code

Add `promo_code` to the order. Everything else in [`POST /services/order`](/docs/api/reference/client/services/#op-post-api-v1-services-order) stays as [Order a service](/docs/get-started/order-a-service/#with-the-api) describes:

```bash
curl -X POST https://api.coritan.com/api/v1/services/order \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": 7,
    "pricing_id": 21,
    "hostname": "web-1.example.com",
    "config": {"location": "fra", "template_id": 4, "hostname": "web-1.example.com"},
    "promo_code": "SPRING25"
  }'
```

When the order cannot use the code, Coritan refuses the whole order with `422` and creates nothing:

```json
{
  "detail": {
    "errors": ["That code has been used up."],
    "promo": "exhausted"
  }
}
```

`promo` is one of the `reason` words under [Troubleshooting](#troubleshooting). To order at the full price, send the order again without `promo_code`.

## Result

The order's first invoice has a line for the discount, such as `Promo code SPRING25: 25% off the first 3 invoices`, with a negative amount, and its total is lower by that amount. Coritan takes the rest from your credit first, as for any order ([How the first payment works](/docs/get-started/order-a-service/#how-the-first-payment-works)). When the code covers the whole invoice, the invoice is paid at once and the service starts setting up.

Each renewal the code covers has the same line. Open an invoice to see its lines ([Read an invoice](/docs/billing/invoices/#read-an-invoice)).

## Troubleshooting

A check or an order that cannot use a code gives one of these reasons:

| `reason` | Message | Cause |
| --- | --- | --- |
| `unknown` | `That code does not exist. Check the spelling.` | No code has that name. |
| `inactive` | `That code is no longer active.` | Coritan switched the code off. |
| `not_yet` | `That code is not valid yet.` | The code's start date has not come yet. |
| `expired` | `That code has expired.` | The code's end date has passed. |
| `exhausted` | `That code has been used up.` | The code has reached its number of uses. |
| `already_used` | `You have already used that code.` | Your account has used the code as many times as it allows. |
| `first_order` | `That code is only for your first order.` | Your account has already paid an invoice or has a paid service. |
| `wrong_product` | `That code does not apply to this order.` | The code covers other products. |
| `nothing_off` | `That code takes nothing off this order.` | The product costs nothing, or the code's amount is in another currency. |

`429` with `Too many promo code checks. Try again in a few minutes.`
: Your account checked 30 codes in ten minutes. Wait a few minutes, then check again.

`404` with `Product not found` or `Pricing tier not found`
: No product has that `product_id`, or the product has no active plan (with that `pricing_id`, when you sent one).

`422` with `Send product_id with pricing_id.`
: The check had a `pricing_id` without its `product_id`. Send both, or neither.

## Related

- [Order a service](/docs/get-started/order-a-service/)
- [Choose or change your account plan](/docs/billing/change-account-plan/)
- [Pay an invoice](/docs/billing/invoices/)
- [Earn credit with referrals](/docs/account/referrals/)

## API

- `POST /api/v1/billing/promo/validate`: Check a promo code before ordering, without using it (https://www.coritan.com/docs/api/reference/client/promotions/#op-post-api-v1-billing-promo-validate)
