# Add capacity to a service

> Buy extra ports, databases, mailboxes, storage or automatic backups for a service you have, remove them, and price any order before you place it.

Source: https://www.coritan.com/docs/billing/add-ons/

A *capacity add-on* raises one limit of a service you already have, such as the number of ports on a Container Apps server, or turns on its automatic backups. Each add-on is a service of its own that renews with the service it is on, on the same date and billing cycle. You can remove it at any time. The **Plan and add-ons** card on a Container Apps server's **Settings** tab lists its add-ons, with **Add…** for each one you can add ([Plan and add-ons](/docs/managed-containers/settings/#plan-and-add-ons)). Once [account plans open on your account](/docs/billing/account-plans/#plans-open-in-stages), a Cloud Compute instance, a mail service and an Object Storage service have the same card, and Home offers the add-on that raises a limit you are close to ([Home](/docs/get-started/dashboard/#home)). Otherwise these steps use the API.

The same API can also [price an order before you place it](#price-an-order-before-you-place-it), with its add-ons and promo code.

## What you can add

| Add-on | `kind` | Goes on | One unit adds |
| --- | --- | --- | --- |
| Extra Port | `container_ports` | A Container Apps server | 1 port slot |
| Extra Database | `container_databases` | A Container Apps server whose plan limits databases | 1 database slot |
| Extra Mailbox | `mail_extra_mailboxes` | The Mail Hosting service your plan includes | 1 mailbox |
| Extra Object Storage 250 GB | `object_storage_extra` | The Object Storage service your plan includes | 250 GB |

Extra Port, Extra Database and Extra Mailbox take a `quantity`. A service takes at most 20 units of each kind, counting all its add-ons. Extra Object Storage 250 GB comes one add-on at a time, up to 20 on one service.

Automatic backups are add-ons too. Each service takes one, with no `quantity`:

| Add-on | `kind` | Goes on | What it does |
| --- | --- | --- | --- |
| Automatic Server Backups | `container_auto_backups` | A Container Apps server, when your plan does not include automatic backups | Takes a snapshot of the server every day and keeps the newest 7 ([Automatic backups](/docs/managed-containers/snapshots/#automatic-backups)) |
| Weekly Instance Backups or Daily Instance Backups | `vps_auto_backups` | A Cloud Compute instance | Backs up the disk every week and keeps the newest 4, or every day and keeps the newest 7 ([Automatic backups](/docs/cloud-compute/backups/#automatic-backups)) |

The instance add-ons cost a share of the instance's price. Once [account plans open on your account](/docs/billing/account-plans/#plans-open-in-stages), the Business plan pays for them on up to three instances and the Enterprise plan on every instance. On an instance your plan covers, the list shows the add-on with `included_by_plan` set to `true` and `price.text` set to `Included with your plan`.

More websites come from a websites pack, which goes on your account rather than on a service. Order it on its own, as [Order a service](/docs/get-started/order-a-service/#with-the-api) describes. [`GET /products/?product_group=addons`](/docs/api/reference/client/catalog/#op-get-api-v1-products) lists it with the other add-ons.

Extra Backup Slots is not on sale yet, so a server's list leaves it out. To keep copies of a server, [take snapshots](/docs/managed-containers/snapshots/) by hand or on a [schedule](/docs/managed-containers/schedules/), or add automatic backups ([Snapshots and backups compared](/docs/snapshots/snapshots-and-backups/)).

## 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.
- The service must be `active` and not set to end. `service_ref` is its service ID, or the UUID of the server behind it.
- For extra mailboxes or storage, set up the included service first ([Set up the services your plan includes](/docs/billing/included-services/)), and use its `id` as `service_ref`.
- Adding an add-on charges the rest of the service's current period. Coritan takes the charge from your credit balance first ([Add credit to your balance](/docs/billing/add-credit/)), and you pay what is left on the invoice.
- A team member working in your account needs the `technical` or `admin` role to add or remove an add-on. Any role can list them.

## See what a service can take

[`GET /services/{service_ref}/addons`](/docs/api/reference/client/services/#op-get-api-v1-services-service-ref-addons) lists the add-ons a service has and the ones it can take:

```bash
curl https://api.coritan.com/api/v1/services/2210/addons \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

This answer for a server is shortened to two add-ons, and its prices may differ from today's:

```json
{
  "parent": {
    "id": 2210,
    "product_name": "CX2",
    "module_name": "container",
    "status": "active",
    "billing_cycle": "monthly",
    "amount": "3.99",
    "next_due_date": "2026-10-14T00:00:00Z"
  },
  "attached": [],
  "available": [
    {
      "product": {"id": 88, "slug": "addon-server-ports", "name": "Extra Port", "description": "One more port on one Container Apps server."},
      "kind": "container_ports",
      "label": "extra ports",
      "adds": "+1 port",
      "unit": 1,
      "unit_label": "port",
      "fits": ["container"],
      "price": {"mode": "per_unit", "amount": "0.50", "cycle": "monthly", "setup_fee": "0.00", "percent": null, "text": "$0.50/mo each"},
      "max_quantity": 20,
      "addable": true,
      "included_by_plan": false,
      "reason_unavailable": null
    },
    {
      "product": {"id": 89, "slug": "addon-server-databases", "name": "Extra Database", "description": "One more database on one Container Apps server."},
      "kind": "container_databases",
      "label": "extra databases",
      "adds": "+1 database",
      "unit": 1,
      "unit_label": "database",
      "fits": ["container"],
      "price": {"mode": "per_unit", "amount": "0.50", "cycle": "monthly", "setup_fee": "0.00", "percent": null, "text": "$0.50/mo each"},
      "max_quantity": 20,
      "addable": true,
      "included_by_plan": false,
      "reason_unavailable": null
    }
  ]
}
```

`parent`
: The service, with the billing cycle and the date that every add-on on it renews on.

`attached`
: The add-ons the service has that have not ended, each as [`GET /services/{service_ref}`](/docs/api/reference/client/services/#op-get-api-v1-services-service-ref) returns a service, plus an `addon` block. A capacity add-on has `addon.type` set to `capacity`, with its `quantity`, what it `adds`, whether you can remove it now (`removable`) and, once you remove it at the end of the term, the date it ends (`ends_at`). A product bought with the service, such as a floating IP, has `addon.type` set to `product`, and you cancel it on its own ([Cancel a service](/docs/billing/cancel-a-service/)).

`available`
: Every add-on for this kind of service, priced on its billing cycle. `price.amount` is for one unit when `price.mode` is `per_unit`, and for the whole add-on when it is `fixed`. `max_quantity` is the most one request can add now. When `addable` is `false`, `reason_unavailable` says why ([Troubleshooting](#troubleshooting)).

## Add an add-on

Send [`POST /services/{service_ref}/addons`](/docs/api/reference/client/services/#op-post-api-v1-services-service-ref-addons) with an add-on from `available`:

```bash
curl -X POST https://api.coritan.com/api/v1/services/2210/addons \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"product_id": 88, "quantity": 3}'
```

`product_id`
: The add-on's `product.id` from `available`.

`quantity`
: Optional, `1` when left out. How many units to add, up to the add-on's `max_quantity`. An add-on sold one at a time takes only `1`.

`billing_cycle`
: Optional. The add-on renews on the service's cycle, so leave it out or send that cycle.

`promo_code`
: Optional. A promo code for the add-on. A code it cannot use refuses the request ([Use a promo code](/docs/billing/promo-codes/#troubleshooting)).

The first invoice charges the rest of the service's current period: the add-on's price for the whole days left before the service renews, plus any setup fee. The day in progress counts as used. This server renews on Oct 14, 2026, with 17 of its 30 days left, so 3 extra ports at $0.50/mo each cost $0.85 now. The answer is `201`, shortened here:

```json
{
  "service": {
    "id": 2231,
    "product_name": "Extra Port",
    "module_name": "addon",
    "status": "pending",
    "billing_cycle": "monthly",
    "amount": 1.5,
    "config": {"quantity": 3, "addon_of_service_id": 2210, "renews_at": "2026-10-14T00:00:00"},
    "addon": {"type": "capacity", "kind": "container_ports", "label": "extra ports", "quantity": 3, "adds": "+3 ports", "removable": true, "ends_at": null, "included_by_plan": false}
  },
  "invoice_id": 5301,
  "requires_payment": true,
  "charge": "0.85",
  "discount": "0.00",
  "amount_due": "0.85",
  "renews_at": "2026-10-14T00:00:00Z",
  "renewal_amount": "1.50",
  "billing_cycle": "monthly",
  "message": "Pay the invoice to apply the add-on."
}
```

`service`
: The add-on. Its `id` is the `addon_ref` you use to remove it.

`charge`, `discount` and `amount_due`
: The first invoice, what a promo code took off it, and what is left to pay after your credit.

`renews_at` and `renewal_amount`
: When the add-on renews with the service, and what it costs each cycle from then on.

The invoice has a line such as `Extra Port, +3 ports (service #2231), to October 14, 2026`. When `requires_payment` is `true`, pay `invoice_id` as [Pay an invoice](/docs/billing/invoices/#with-the-api) shows. `message` says what happened:

| `message` | Meaning |
| --- | --- |
| `Pay the invoice to apply the add-on.` | Part of the invoice is still to pay. |
| `Paid from your credit balance. The add-on applies in a moment.` | Your credit paid the invoice. |
| `Your promo code covered the charge. The add-on applies in a moment.` | The code took off the whole charge. |
| `Nothing is due before the next renewal. The add-on applies in a moment.` | Less than a day is left before the service renews, so there was nothing to charge. |

## Result

Once the invoice is paid, the add-on's `status` becomes `active` and the limit goes up:

- Extra ports and databases raise the server's **Port slots** and **Database slots**. In the dashboard, go to **Container Apps**, open the server, then the **Settings** tab. The **Resources** card shows both.
- Extra mailboxes and storage raise `mailboxes` and `object_storage_gb` in your plan's limits, and Coritan resizes the included service to match ([Read your limits and usage](/docs/billing/account-plans/#read-your-limits-and-usage)).
- Automatic backups start on the server or the instance, as [Automatic backups](/docs/managed-containers/snapshots/#automatic-backups) and [How automatic backups run](/docs/cloud-compute/backups/#how-automatic-backups-run) describe.

The add-on renews with the service at `renewal_amount`, on an invoice of its own.

## Remove an add-on

Send [`DELETE /services/{service_ref}/addons/{addon_ref}`](/docs/api/reference/client/services/#op-delete-api-v1-services-service-ref-addons-addon-ref), where `addon_ref` is the add-on's service ID. By default the add-on stays until the service renews, and nothing more is charged for it:

```bash
curl -X DELETE https://api.coritan.com/api/v1/services/2210/addons/2231 \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
{
  "service_id": 2231,
  "when": "end_of_term",
  "status": "active",
  "termination_date": "2026-10-14T00:00:00Z",
  "message": "The add-on ends on October 14, 2026, when this server renews. It stays until then."
}
```

To remove it at once, add `?when=now` to the address. The answer's `status` is then `pending_termination`, and its `message` is `Add-on removed. Its limit comes off the server in a moment.`

> [!WARNING]
> Removing an add-on with `when=now` refunds nothing for the rest of the period you paid for.

When the limit comes off, Coritan deletes nothing. A server with more ports or databases than its slots keeps them, but you cannot add more until it is back under the limit. Extra mailboxes or storage that you use cannot be removed: delete what would be over the limit first.

An add-on whose invoice you have not paid ends at once, whichever `when` you send, and Coritan cancels its invoice. The `message` is then `Add-on removed. It had not been applied yet.`

A service's capacity add-ons end when the service does. When you [cancel it](/docs/billing/cancel-a-service/#what-ends-with-the-service), they end on the same date, or at once when you cancel immediately, and Coritan cancels their unpaid invoices. When a service ends for any other reason, such as an unpaid invoice, its add-ons end with it.

## Buy add-ons with a new server

Extra ports and databases can also go in the order that creates a server. Put each one in the order's `addons`, as [Add-ons in the order](/docs/get-started/order-a-service/#add-ons-in-the-order) describes, with its `product_id` and a `quantity` of up to 20:

```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": 12,
    "pricing_id": 34,
    "hostname": "survival-smp",
    "config": {"location": "fra", "name": "survival-smp", "specialization_slug": "minecraft-paper"},
    "addons": [{"product_id": 88, "quantity": 3}]
  }'
```

- [`GET /products/?product_group=addons`](/docs/api/reference/client/catalog/#op-get-api-v1-products) lists the add-on products. Each one's `addon` block has its `kind` from [What you can add](#what-you-can-add).
- Leave out `pricing_id` and `config`. The add-on takes the server's billing cycle.
- List each add-on once. One service holds its whole quantity.
- The first invoice charges a whole billing cycle of the add-on, because the server starts its first cycle with it. A promo code in the order takes nothing off add-ons.
- When the order cannot take an add-on, it refuses the whole order and creates nothing.

A capacity add-on needs the service it goes on, so never order one on its own.

## Price an order before you place it

[`POST /checkout/quote`](/docs/api/reference/client/checkout/#op-post-api-v1-checkout-quote) takes the body of an order and answers what it would cost, without placing it. It works for any order, with or without add-ons and a promo code:

```bash
curl -X POST https://api.coritan.com/api/v1/checkout/quote \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": 12,
    "pricing_id": 34,
    "hostname": "survival-smp",
    "config": {"location": "fra", "name": "survival-smp", "specialization_slug": "minecraft-paper"},
    "addons": [{"product_id": 88, "quantity": 3}],
    "promo_code": "SPRING25"
  }'
```

This code gives 25% off the first 3 invoices:

```json
{
  "lines": [
    {"label": "CX2", "amount": "3.99", "cycle": "monthly", "kind": "recurring"},
    {"label": "Extra Port, +3 ports", "amount": "1.50", "cycle": "monthly", "kind": "addon"}
  ],
  "subtotal": "5.49",
  "discount": "1.00",
  "due_now": "4.49",
  "requires_payment": true,
  "currency": "USD",
  "renews": [
    {"label": "CX2", "amount": "2.99", "cycle": "monthly"},
    {"label": "Extra Port, +3 ports", "amount": "1.50", "cycle": "monthly"}
  ],
  "promo": {
    "valid": true,
    "code": "SPRING25",
    "message": "SPRING25 applied: 25% off the first 3 invoices.",
    "reason": null,
    "summary": "25% off the first 3 invoices",
    "duration": "repeating",
    "cycles": 3
  }
}
```

`lines`
: The lines of the order's first invoice. `kind` is `recurring` for the product you order, `setup` for its setup fee, and `addon` for anything bought with it. Each floating IP or Shield Custom Profile that your [account plan](/docs/billing/account-plans/#what-each-plan-includes) would pay for has its own line, with an `amount` of `0.00` and a `label` that adds `, included with your plan` to the product's name, such as `IPv4 Address, included with your plan`. This holds when it is the order itself and when it is an add-on. Coritan waives its setup fee, so the quote has no setup fee line for it.

`discount` and `due_now`
: What the promo code takes off the first invoice, and what is left to pay before the order starts. When you place the order, Coritan takes that from your credit first ([How the first payment works](/docs/get-started/order-a-service/#how-the-first-payment-works)). When nothing is due first, because the order costs nothing or your account is billed in arrears, `due_now` is `0.00` and `requires_payment` is `false`.

`renews`
: What each renewal charges. When the code also covers renewals, the product's line shows the price after its discount. The code covers as many invoices as `promo.cycles` says, the first one included.

`promo`
: `null` when the order has no `promo_code`. A code the order cannot use does not refuse the quote: `valid` is `false`, and `reason` is one of the words under [Use a promo code](/docs/billing/promo-codes/#troubleshooting).

Each code the quote refuses counts as one check towards the limit on [`POST /billing/promo/validate`](/docs/api/reference/client/promotions/#op-post-api-v1-billing-promo-validate), which is 30 checks in ten minutes. Once your account reaches it, `reason` is `rate_limited` for every code. Wait a few minutes, then quote again. A code the quote accepts counts nothing.

The quote refuses what the order would refuse, with the same status and message ([Troubleshooting](#troubleshooting) and [Order a service](/docs/get-started/order-a-service/#with-the-api)). It leaves out only the checks made as an order is placed: those on an order that costs $0, the same order sent twice, and a floating IP order's `idempotency_key`. A quote holds nothing for you, and the order checks everything again.

## Troubleshooting

When a service cannot take an add-on, adding it answers `422` with `{"detail": {"errors": ["<message>"]}}`. The list shows the same message as the add-on's `reason_unavailable`, and an order or a quote gives it when the new server cannot take the add-on:

| Message | Cause |
| --- | --- |
| `Add-ons go on an active server, and this server is suspended.` | The service is not `active`. Add the add-on once it is. |
| `This server is set to end, so it takes no new add-ons.` | You cancelled the service at the end of its term. |
| `Extra Port goes on a Container Apps server.` | The add-on is for another kind of service. Choose one from this service's `available` list. |
| `Extra Mailbox goes on the email your plan includes.` | Extra mailboxes and storage go only on an included service, so no order can take them either. |
| `This server's plan already has unlimited databases.` | The plan sets no limit to raise. |
| `This server already has the most extra ports one server takes.` | The service has 20 units of that kind. |
| `Extra Port has no price that renews every week, as this server does.` | The add-on is not sold on the service's billing cycle. |
| `Extra Backup Slots is not on sale yet.` | Extra Backup Slots cannot be added yet. [Take snapshots](/docs/managed-containers/snapshots/) instead, or add automatic backups. |
| `This server already has automatic backups.` | The server or instance has an automatic backups add-on already. |
| `This instance has weekly automatic backups. Remove them first to switch to daily.` | An instance takes one of the two. Remove the one it has, then add the other once the first ends. |
| `Your Pro plan includes automatic backups on every server.` | Your plan already takes a server's automatic backups, so it needs no add-on. |
| `Websites Pack goes on your account rather than on one service. Order it on its own.` | Order a websites pack with `POST /services/order`. |

Adding an add-on can also answer `422` for what the request asks:

| Message | Cause |
| --- | --- |
| `This server takes 3 more ports. Set quantity to a number from 1 to 3.` | `quantity` is more than the service has room for. |
| `Extra Object Storage 250 GB is sold one at a time. Set quantity to 1.` | That add-on takes no `quantity` above `1`. Add another one to get more. |
| `Extra Port renews with this server, every month. Leave billing_cycle out or set it to monthly.` | `billing_cycle` is not the service's cycle. |

An order or a quote can also answer `422` with one of these:

| Message | Cause |
| --- | --- |
| `Extra Port goes on a Container Apps server. Add it to that service, or to the order that creates the service.` | The order is for the add-on alone. |
| `List Extra Port once and set its quantity to the number you want.` | `addons` names the same add-on twice. |
| `Extra Port renews with CX2, so it takes the price for the same billing cycle. Leave pricing_id out.` | The entry has a `pricing_id` for another cycle. |
| `Extra Port takes no config. Leave config out.` | The entry has a `config`. |

Other answers when you add an add-on:

`404` with `Service not found`, or `403` with `Access denied`
: No service has that `service_ref`, or it belongs to another account.

`404` with `There is no product with id 99. Choose an add-on from this service's list.`
: `product_id` is wrong. Take it from `available`.

`422` with `promo` beside `errors`
: The promo code cannot be used on this add-on. `promo` is one of the `reason` words in [Use a promo code](/docs/billing/promo-codes/#troubleshooting). Send the request again without `promo_code` to pay the full price.

`429` with `"error": "rate_limited"`
: Your account added or removed add-ons 20 times in an hour. `retry_after_seconds` and the `Retry-After` header give the length of the window.

Removing an add-on can answer with one of these. A `422` holds its message in `{"detail": {"errors": [...]}}`, and the others hold it in `detail`:

| Status | Message | Cause |
| --- | --- | --- |
| `404` | `This server has no add-on 2231.` | `addon_ref` is not an add-on of this service. Take the `id` from `attached`. |
| `422` | `IPv4 Address is a service of its own. Cancel it from its own page.` | A product bought with the service ends when you [cancel it](/docs/billing/cancel-a-service/). |
| `409` | `This add-on has already been removed.` | The add-on has ended, or is ending now. |
| `409` | `This add-on is being applied. Remove it in a moment.` | Its invoice was just paid, and Coritan is applying it. |
| `409` | `This add-on already ends on October 14, 2026. Remove it now with when=now.` | You removed it at the end of the term already. |
| `409` | `You have 12 mailboxes, and your plan allows 10 without this add-on. Delete 2 first, then remove it.` | The mailboxes you have need the add-on. |
| `409` | `You store 260 GB, and your plan allows 250 GB without this add-on. Delete 10 GB of files first, then remove it.` | The files you store need the add-on. |

## Related

- [Order a service](/docs/get-started/order-a-service/)
- [Use a promo code](/docs/billing/promo-codes/)
- [Cancel a service](/docs/billing/cancel-a-service/)
- [How account plans work](/docs/billing/account-plans/)

## API

- `GET /api/v1/services/{service_ref}/addons`: The add-ons on one of your services, and the ones you can add (https://www.coritan.com/docs/api/reference/client/services/#op-get-api-v1-services-service-ref-addons)
- `POST /api/v1/services/{service_ref}/addons`: Add a capacity add-on to one of your active services (https://www.coritan.com/docs/api/reference/client/services/#op-post-api-v1-services-service-ref-addons)
- `DELETE /api/v1/services/{service_ref}/addons/{addon_ref}`: Remove a capacity add-on from one of your services (https://www.coritan.com/docs/api/reference/client/services/#op-delete-api-v1-services-service-ref-addons-addon-ref)
- `POST /api/v1/checkout/quote`: What an order would cost, without placing it (https://www.coritan.com/docs/api/reference/client/checkout/#op-post-api-v1-checkout-quote)
