> ## Documentation Index
> Fetch the complete documentation index at: https://docs.server.express/llms.txt
> Use this file to discover all available pages before exploring further.

# Reselling

> Read live dedicated, cloud and shared hosting stock at your own rate, then place real orders from your own system. One catalogue call, three order calls, and the same token that manages your servers.

If you sell hosting to your own customers, you shouldn't have to log in to our panel to do it. This part of the API lets you read what's in stock at your price and order it from your own system.

Two things make it a reseller API rather than a product feed: **every price comes back twice**, and **an order is a real order**.

## Your rate

Ask us for a reseller discount and we'll put it on your account as a single percentage off list. It applies to everything you buy, dedicated and cloud, through the API or the panel. It's also captured on each service when you order, so renewals stay at the rate you bought at. If your discount changes later, nothing that's already running gets re-priced.

In the catalogue, every price is an object, not a number:

```json theme={null}
{ "listMinor": 15000, "netMinor": 13500, "discountBps": 1000 }
```

`listMinor` is what the storefront charges, and `netMinor` is what we charge you. The difference is your margin. `discountBps` is your discount in basis points, so `1000` is 10%. All amounts are integers in minor units, so `15000` is £150.00.

## The catalogue

```bash theme={null}
curl https://my.server.express/api/v1/reseller/catalogue \
  -H "Authorization: Bearer $SE_TOKEN"
```

Needs `catalogue:read`. It returns all three products in one response, as `dedicated`, `cloud` and `hosting`, plus a `meta` block with the currency, your discount as a percentage, and `priceUnit: "minor"`.

Dedicated rows have a `price` and a `setup` fee, and a stock object worth reading carefully:

```json theme={null}
{
  "slug": "xeon2-64-sto",
  "cpu": "2x Intel Xeon E5-2680V4",
  "price": { "listMinor": 15000, "netMinor": 13500, "discountBps": 1000 },
  "stock": { "total": 12, "racked": 11, "slots": 1 },
  "instant": true,
  "leadTime": null
}
```

* `racked` is how many machines are sitting in a rack right now.
* `slots` is hardware we've committed to build but haven't racked yet. You can order it today, and it's delivered within `leadTime`.
* `total` is the two added together, which is what you can sell right now.

Use the split when you quote a customer. Selling a slot as if it ships in minutes is the one mistake worth designing against. That's why the numbers come separately rather than as one figure you have to trust.

`instant: true` means a paid order provisions itself without anyone on our side. Cloud plans are always instant.

Pass `?currency=USD` to price cloud and hosting in dollars. If we've set a price for that currency, you get it. Otherwise the figure is converted and `priceSource` says `converted`. Quote those knowing the exchange rate moves.

Hosting rows carry `orderable`. If it's `false`, the plan isn't fully set up on our side and an order will be refused, so don't quote it.

## Ordering

Every order needs `orders:place`.

> [!WARNING]
>
> This spends money. An order reserves a machine, creates the service, and raises an invoice against your account at your rate.

### Dedicated

```bash theme={null}
curl -X POST https://my.server.express/api/v1/reseller/orders/dedicated \
  -H "Authorization: Bearer $SE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "planSlug": "xeon2-64-sto", "hostname": "customer-01" }'
```

`planSlug` and `hostname` are required. You can also pass `profileId` (the OS to install), `rootPassword` and `sshKeys`.

### Cloud

```bash theme={null}
curl -X POST https://my.server.express/api/v1/reseller/orders/cloud \
  -H "Authorization: Bearer $SE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "planId": "vds-4", "hostname": "customer-02", "location": "sto", "os": "ubuntu-24-04" }'
```

`planId` is the cloud row's `slug` from the catalogue, and `hostname` is required. `location`, `os`, `app` and `appInputs` are optional.

### Shared hosting

```bash theme={null}
curl -X POST https://my.server.express/api/v1/reseller/orders/hosting \
  -H "Authorization: Bearer $SE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "planId": "grow", "domain": "customer-site.com", "location": "sto" }'
```

This one takes a `domain` instead of a hostname, and you can only have one subscription per domain. If we already host the domain, you get a `409` before any money changes hands.

### The response

All three answer `201` with the same shape:

```json theme={null}
{
  "success": true,
  "data": {
    "serviceId": "cm4k...",
    "invoice": { "id": "cm4n...", "number": "INV-1042", "subtotal": 13500, "total": 16200, "currency": "GBP" },
    "price": { "list": 15000, "net": 13500, "discountBps": 1000 },
    "fulfilment": { "instant": true, "provisional": false, "leadTime": null }
  }
}
```

> [!NOTE]
>
> Order responses use `list` and `net` in `price`. The catalogue uses `listMinor` and `netMinor`. Both are minor units. The names just differ.

`invoice.total` includes tax, and `subtotal` doesn't.

Nothing is provisioned until the invoice is paid. You can pay it with [`invoices:pay`](https://docs.server.express/guides/billing-and-tickets#paying) or from the panel. Once it's paid, the machine builds itself. If `provisional` came back `true`, we build it by hand, and you have a lead time to quote.

### When an order is refused

| Status | Why |
| - | - |
| `400` | A required field is missing or invalid. |
| `409` | The last machine in that plan sold between your catalogue call and your order, an add-on is no longer available, or the domain is already hosted. No invoice is created. |
| `428` | Your account doesn't have a billing address yet. The response lists what's `missing`. Add it in the client area once and orders will go through. |

If you get a `409` on stock, read the catalogue again rather than retrying blind.

## Managing what you've sold

There's nothing reseller-specific here, because there doesn't need to be. Everything you order lands in your account as an ordinary service. The [servers guide](https://docs.server.express/guides/servers.md) already covers listing, rebooting, rescuing, reinstalling and cancelling them with the token you're holding, and [billing](https://docs.server.express/guides/billing-and-tickets.md) covers the invoices.

## What we don't do

We don't white-label the panel, and we don't bill your customers for you. Your customer is your customer. You own the relationship, the pricing and the support, and we own the hardware and the network underneath. If you need us to talk to them directly, that's a conversation rather than an API call. Get in touch through the [client area](https://my.server.express).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.