# Creating products and prices

This guide explains how to create products and prices, and how to manage them after creation.

## Prerequisites

* You have a valid ODUS API secret key.
* You understand the difference between products and prices. If not, read [What are products and prices?](https://docs.odus.com/docs/guides/products/overview.md) first.

## Creating a product

A product is the starting point. You must create a product before you can attach any prices to it.

**Via the Dashboard:** Go to **Products → Products** and click **Add**. Fill in the name and, optionally, a description, a statement descriptor and a statement descriptor suffix.

**Via the API:** Send a [`POST /v2/products`](https://docs.odus.com/docs/api/core/v2/product-controller-create) request:

```
{

  "name": "Pro Plan",

  "description": "Full access to all Pro features",

  "statementDescriptor": "MYAPP PRO PLAN",

  "statementDescriptorSuffix": "PRO PLAN"

}
```

See the [`POST /v2/products`](https://docs.odus.com/docs/api/core/v2/product-controller-create) reference for the full parameter list.

The response includes the product `id`. You will need this ID when creating prices.

### Fulfillment settings

A product also carries what [Order Management System](https://docs.odus.com/docs/guides/order-management/.md) needs to ship it: **Shippable** (the product takes part in Order Management) and **SKU** (what the warehouse ships it under — a shippable product without one stays on its orders but never ships). **Category** is unrelated to fulfillment: it is sent as metadata to payment service providers, for example for VAT reporting.

See [What the SKU decides](https://docs.odus.com/docs/guides/order-management/how-orders-are-created.md#what-the-sku-decides) for what each setting changes on the resulting order, and how to keep one price out of fulfillment when an add-on shares its product with goods that ship.

## Attaching a recurring price

A recurring price charges the customer on a repeating schedule. `amount` is what each billing cycle charges, and `recurringSchedule` sets how often.

**Via the Dashboard:** Go to **Products → Prices** and click **Add**. Select the product, choose **Recurring** as the type, select the currencies, and set the interval and amount for each currency.

**Via the API:** Send a [`POST /v2/prices`](https://docs.odus.com/docs/api/core/v2/price-controller-create) request:

```
{

  "name": "Pro Plan — Monthly",

  "type": "recurring",

  "currency": "usd",

  "amount": 2999,

  "product": "prod_2QGNGy637hJ9MnD5cK7thAjSvPV",

  "recurringSchedule": {

    "intervalUnit": "month",

    "intervalCount": 1

  }

}
```

See the [`POST /v2/prices`](https://docs.odus.com/docs/api/core/v2/price-controller-create) reference for the full parameter list. `recurringSchedule` takes:

* `intervalUnit` — `minute`, `hour`, `day`, `week`, `month`, or `year`. Required.
* `intervalCount` — the number of units between charges. Required.
* `trial` — optional. A first cycle with its own `intervalUnit`, `intervalCount` and `amount`, charged before the regular `amount` takes effect.

A monthly price with a 7-day trial for $1.99

```
{

  "name": "Pro Plan — Monthly with trial",

  "type": "recurring",

  "currency": "usd",

  "amount": 2999,

  "product": "prod_2QGNGy637hJ9MnD5cK7thAjSvPV",

  "recurringSchedule": {

    "intervalUnit": "month",

    "intervalCount": 1,

    "trial": { "intervalUnit": "day", "intervalCount": 7, "amount": 199 }

  }

}
```

The text on the customer's bank statement comes from the product's `statementDescriptor` or `statementDescriptorSuffix`, not from the price. Which one a gateway uses is explained in [Statement descriptors](https://docs.odus.com/docs/guides/products/overview.md#statement-descriptors).

Moving from v1

`billingSchedule` is not part of v2. Replace it with `recurringSchedule`, and transform the value as well as the key: the two describe the schedule differently. Send one or the other, never both. A schedule whose first cycle differs from the rest maps to `trial`, as in the example above. A schedule that keeps changing after its first cycle — a different amount or interval on the second cycle or later — has no v2 equivalent.

tip

To offer the same plan in multiple currencies at once, use the Dashboard form. It lets you define amounts for several currencies in a single step, creating one price object per currency.

## Attaching a one-time price

A one-time price charges the customer a fixed amount exactly once.

**Via the Dashboard:** Go to **Products → Prices**, click **Add**, and select **One-time** as the type.

**Via the API:** Send a [`POST /v2/prices`](https://docs.odus.com/docs/api/core/v2/price-controller-create) request with `type: "one_time"` and an `amount`:

```
{

  "name": "Lifetime Access",

  "type": "one_time",

  "currency": "usd",

  "amount": 29900,

  "product": "prod_2QGNGy637hJ9MnD5cK7thAjSvPV"

}
```

One-time prices take no `recurringSchedule`.

## Selling a bundle of units

If a price represents several units of the same thing — a pack of four sessions, a case of twelve bottles — set `quantity` on the price. The `amount` still covers the whole pack, and ODUS splits it into a per-unit amount when the price is used:

```
{

  "name": "Session Pack",

  "type": "one_time",

  "currency": "usd",

  "amount": 14796,

  "quantity": 4,

  "product": "prod_2QGNGy637hJ9MnD5cK7thAjSvPV"

}
```

A payment referencing this price produces a line item of quantity `4` at `3699` each, so wallets and gateway order sheets show `4x Session Pack — $36.99` instead of `1x Session Pack — $147.96`. The customer is charged the same `147.96` either way.

`quantity` defaults to `1`, so existing prices are unaffected. Two further rules apply:

* The price `amount` (and the trial amount of a recurring price) must divide evenly by `quantity`, so each unit has a whole per-unit amount.
* A `quantity` sent on the line item multiplies the price quantity. Ordering `quantity: 2` of the pack above yields 8 units, charged `295.92`.

## Giving an item away for free

A price can have an `amount` of `0`. That is how you sell a free item alongside a paid one — a gift with purchase, a bundled sample, a no-cost add-on — instead of discounting the paid product and losing the extra from the order.

```
{

  "name": "Free Shaker Bottle",

  "type": "one_time",

  "currency": "usd",

  "amount": 0,

  "product": "prod_2QGNGy637hJ9MnD5cK7thAjSvPV"

}
```

Put the free price in the same cart as the paid one. The customer is charged the paid total, and both items appear on the payment, on the gateway's order sheet, and in Order Management, so the freebie is picked, packed and shipped like anything else.

A **recurring** price of `0` becomes an ordinary subscription that renews at no cost: every cycle produces a paid invoice and a succeeded payment, and the order is created as usual — the customer's card is simply never charged. Nothing zero-valued is ever sent to a payment provider.

note

Make a recurring item free by setting the **price** amount to `0`, not by overriding the amount on a line item. A subscription bills from its price, so a line-item override applies to the first charge only and the item would renew at full price. ODUS rejects that override rather than let it happen.

## Editing a price

You can update a price's name, active status, quantity, recurring schedule, and metadata after creation.

**Via the Dashboard:** Open the price from **Products → Prices** and edit the fields directly.

**Via the API:** Send a [`POST /v2/prices/{id}`](https://docs.odus.com/docs/api/core/v2/price-controller-update) request with the fields you want to change:

```
{

  "name": "Pro Plan — Monthly (Updated)"

}
```

note

The currency of a price cannot be changed after creation. If you need a price in a different currency, create a new price.

## Deleting a price

**Via the Dashboard:** Open the price from **Products → Prices**, click the actions menu, and select **Delete**.

**Via the API:** Send a [`POST /v2/prices/{id}/delete`](https://docs.odus.com/docs/api/core/v2/price-controller-delete) request. No request body is required.

warning

A price cannot be deleted if it has already been used to make a payment. If you no longer want customers to use a price, set `active` to `false` instead. Inactive prices are hidden in the Dashboard but remain accessible via the API.
