# POST /api/v1/services/{service}/actions/upgrade

> Hold a service upgrade for confirmation

- Group: services
- Tier: W
- Required scope: write:billing + write:services
- Docs: https://api.inleed.com/reference/services/upgrade-service

## Description

Validates the target type against the live upgrade options, then returns `{status:"confirmation_required", confirmationUrl, …}`. It charges nothing; on approval an unpaid proforma order is created and the plan changes only after it is paid.

## Path parameters

- `service` — string (required)

## Body

- `input` — string (required). A domain, email address, website URL, or Inleed service id — for example example.se, info@example.se or 42976. Resolved to the owning account automatically, and the resolved target is echoed back in the response.
- `service_type_id` — integer [default: 0]. The target plan's service-type id. Get it from get_upgrade_options → options[].serviceTypeId.
- `attempt_key` — string. Idempotency key for this intent. Keep it stable across retries so a timed-out retry cannot buy the same thing twice.

## Request

```bash
curl -X POST "https://mcp.inleed.com/api/v1/services/42976/actions/upgrade" \
  -H "Authorization: Bearer inl_live_…" \
  -H "Content-Type: application/json" \
  -d '{"input":"example.se","service_type_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, service_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/services/{service}/actions/upgrade — https://api.inleed.com/reference/services/get-upgrade-options
- DELETE /api/v1/services/{service}/actions/upgrade — https://api.inleed.com/reference/services/cancel-scheduled-upgrade
- GET /api/v1/services — https://api.inleed.com/reference/services/list-services
- GET /api/v1/services/{service} — https://api.inleed.com/reference/services/get-service

