# POST /api/v1/orders

> Hold a store order for confirmation

- Group: products
- Tier: W
- Required scope: write:billing + write:orders
- Docs: https://api.inleed.com/reference/products/create-order

## Description

Validates and prices the cart, then returns `{status:"confirmation_required", confirmationUrl, …}`. It creates no order and charges nothing — show the human the `confirmationUrl`; they approve in the Inleed client area, and a proforma invoice with a payment link is created. The order provisions only once that invoice is paid.

## Body

- `items` — object[] (required). The cart to order: the same items you priced with preview_order. At least one, at most 50.
  - `service_plan_id` — integer (required). The catalogue plan id to buy — a plan's servicePlanId from list_products or get_product.
  - `quantity` — integer. How many of this plan (1–99). Defaults to 1.
  - `domain` — string. The domain this line is for, where the product needs one, like example.com.
  - `addons` — object[]. Addon services ordered together with this line — exactly the addons you previewed.
    - `service_plan_id` — integer (required). The addon plan id — an options[].servicePlanId from get_addon_suggestions for this line's plan.
    - `quantity` — integer. How many of this addon (bounds come from get_addon_suggestions). Defaults to 1.
  - `config` — object. Per-product provisioning options — the same config you previewed. A key the product cannot use is refused.
    - `php_version` — string. Hosting lines only: the PHP version to provision with, e.g. 8.3.
    - `preinstall` — string. Hosting lines only: preinstall an application, e.g. wordpress.
    - `hostname` — string. VPS/dedicated lines only: the server hostname.
    - `operative_system` — string. VPS/dedicated lines only: the OS template name from list_vps_templates.
- `billing_address_id` — integer. Which billing profile to invoice. Omit to use the account default.
- `attempt_key` — string. Idempotency key for this intent. Keep it stable across retries so a timed-out retry cannot buy the same thing twice. Up to 128 characters.

## Request

```bash
curl -X POST "https://mcp.inleed.com/api/v1/orders" \
  -H "Authorization: Bearer inl_live_…" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"service_plan_id":1,"quantity":1,"domain":"example.se","addons":[{"service_plan_id":1,"quantity":1}],"config":{"php_version":"8.3","preinstall":"example.se","hostname":"example.se","operative_system":"example.se"}}],"billing_address_id":1,"attempt_key":"example.se"}'
```

## Response · 200

```json
{
  "status": "active",
  "pendingActionId": "example.se",
  "confirmationUrl": "https://mcp.inleed.com/…",
  "expiresAt": "2026-08-30T09:12:44.000Z",
  "preview": []
}
```

## Errors

- **400**  — codes: invalid_request
- **401** No token was presented, or the token is revoked, expired or unknown. — codes: unauthorized, token_expired, token_revoked
- **403** The token lacks a required scope, or this account does not own the resource. — codes: insufficient_scope, not_owned
- **404** No such resource for this account. — codes: not_found
- **422** Validation error — codes: validation_failed
- **429** The rate limit for this token is exhausted. See `Retry-After`. — codes: rate_limited
- **500** Something went wrong on our side. The failure is logged against `requestId`. — codes: internal_error

## Related

- GET /api/v1/orders — https://api.inleed.com/reference/products/list-orders
- GET /api/v1/orders/{order} — https://api.inleed.com/reference/products/get-order
- GET /api/v1/orders/pending — https://api.inleed.com/reference/products/list-pending-orders
- GET /api/v1/orders/addon-suggestions — https://api.inleed.com/reference/products/get-addon-suggestions

