### Charge and provision an activation

`POST /api/v1/users/{id}/activation`

Prices, charges and provisions in one operation. Funds are reserved first, then the plan is applied, and both halves are keyed off your request_id, so a retry after a crash re-runs neither the charge nor the grant.

- Authentication: manager session (JWT) or API token
- Permission: any one of `prm_users_activate`, `prm_users_extend`
- Rate limit bucket: `t_mutate`
- Idempotent on `request_id`: retrying with the same id returns the original result

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Subscriber id. |
| `request_id` | body | string | yes | Idempotency key, up to 255 characters, no colon or pipe. Reuse the same one on every retry of one intent. |
| `money_collected` | body | boolean | no | Defaults to true. |
| `card_code` | body | string | no | Required when method is card. The voucher must be in the caller's subtree. |
| `issue_invoice` | body | boolean | no | Also record an invoice document. Skipped on a replay so a retry never double-issues. |

#### Request

```json
{
  "profile_id": 7,
  "operation": "activate",
  "method": "manager_balance",
  "units": 1,
  "money_collected": true,
  "request_id": "0f3b9d4e-9a41-4c83-9b1e-2b6a0f1d88c2"
}
```

#### Response — 200 OK

```json
{
  "data": {
    "quote": { "profile_id": 7, "required_amount": 171.00, "new_expiration": "2026-10-14 00:00:00" },
    "activation": {
      "UserID": 4711,
      "ProfileID": 7,
      "NewSubscriptionEnd": "2026-10-14T00:00:00Z",
      "BytesRemaining": 107374182400,
      "SecondsRemaining": -1,
      "PointsAwarded": 10,
      "QuotaCarried": false,
      "Replay": false
    },
    "manager_balance": 4029.00,
    "replay": false
  }
}
```

#### Errors

| Code | Status | When |
| --- | --- | --- |
| `ERR_VALIDATION` | 400 | request_id missing, too long, or in a reserved namespace |
| `ERR_CONFLICT` | 409 | the request_id is already bound to an activation of a different subscriber |
| `ERR_FORBIDDEN` | 403 | the body's operation needs a permission the caller does not hold |

#### Note

The nested activation object is serialised with Go field names (UserID, NewSubscriptionEnd) and RFC3339 timestamps, unlike every other object on this API. Everything around it uses snake_case and yyyy-MM-dd HH:mm:ss. Do not write a parser that assumes one convention.

