# Create website of a web hosting package

> A new website (vHost) at a domain or subdomain of the package: a folder, a redirect, the website builder or an alias.

- Effect: Write - Changes the account. Agents ask first.
- Idempotent: no
- Stability: beta
- MCP tool: `manitu_webhosting_web_vhost_create` on https://mcp.manitu.de/mcp
- REST: `POST https://api.manitu.de/v1/webhosting/web/vhost/create`
- Needs: `service_webhosting`
- Page: /reference/webhosting/web/vhost/create/

**Changes the account. Agents say what will happen and wait for an explicit yes before calling it.**

## MCP tool

`manitu_webhosting_web_vhost_create`

### Description for the model

Creates a website (vHost) for a web hosting package of the manitu customer account this connection works in, by its site_id from manitu_webhosting_list, at one of the package's names - a domain or a subdomain for the web (fqdn_free_list of manitu_webhosting_web_vhost_list; a new subdomain first with manitu_webhosting_subdomain_create). type: website (shows a folder - by default /web for a domain, /web/<fqdn> for a subdomain, created if missing, with manitu's placeholder page unless website.setup_default_page is false: set it false when you write the website's own files right after (manitu_webhosting_web_file_write) - or redirects to a URL, see website), websitebuilder (made with manitu's website builder; the editor then opens with manitu_webhosting_web_vhost_websitebuilder_get) or alias (a further name of a website, alias.of required; by default it redirects there). Defaults as in the customer panel: Let's Encrypt certificate, HTTPS redirect, HSTS for a year, an alternative hostname. It takes up to an hour until it answers everywhere - DNS and browser caches may show the old state meanwhile; the name must point to manitu (DNS) for it and for the certificate. Refused with a conflict when the package allows no (more) websitebuilder (limit_reached) or cannot be changed now (not_configurable). Tell the customer the name, the type and what it will show, and ask for an explicit yes first.

### Arguments

- `site_id` (integer | string, required) - The site_id from manitu_webhosting_list - never guess one. (pattern `"^[1-9][0-9]*$"`; minimum `1`)
- `fqdn` (string, required) - The name, in full - a domain of the package or a subdomain for the web, e.g. www.example.de; Unicode or ASCII, any case. (minLength `3`; maxLength `253`)
- `type` (string, required) - website, websitebuilder or alias - set does not change it; between website and alias manitu_webhosting_web_vhost_convert does, a websitebuilder stays one. (one of `"website"`, `"websitebuilder"`, `"alias"`)
- `website` (object) - Only for type website: what it shows.
  - `website.target_dir` (string) - Show this folder, relative to the web root - for a new website its own folder in htdocs, website_folder_template.api of manitu_webhosting_web_structure_get (e.g. /htdocs/www.example.com/; the older layout: /web/www.example.com/). Default: htdocs itself for a domain, htdocs/<fqdn> for a subdomain - pass it instead. Not together with redirect_url. (minLength `1`; maxLength `255`)
  - `website.redirect_url` (string) - Instead of a folder: send every visitor to this URL, e.g. https://www.example.com/ - https:// is put in front when there is no scheme. (minLength `1`; maxLength `255`)
  - `website.create_target_dir` (boolean) - Create target_dir if it is not there (default true); false: it must be there.
  - `website.allow_wordpress_xmlrpc` (boolean) - Make WordPress' XML-RPC interface reachable (default false) - only if the customer needs it: a frequent target of brute force attacks that manitu's firewall cannot block. Tell him so.
  - `website.setup_default_page` (boolean) - Put manitu's placeholder page into an empty target_dir (default true). false when the website's own files follow right after (manitu_webhosting_web_file_write) - nothing to replace then.
- `alias` (object) - Only for type alias.
  - `alias.of` (string) - The website (or websitebuilder) it belongs to, by fqdn from manitu_webhosting_web_vhost_list - required. Not an alias. (minLength `3`; maxLength `253`)
  - `alias.redirect_to_parent` (boolean) - Redirect visitors to the website's name (HTTP 301), default true; false: show the same under the alias' own name.
- `https` (object) - Not for an alias (it has its website's). Change HSTS only if the customer knows what it means: browsers keep using HTTPS only for max_age seconds, even if the certificate is gone.
  - `https.redirect` (boolean) - Send http:// visitors to https:// (default true).
  - `https.hsts` (object) - Default: active, max_age 31536000 (a year), include_subdomains, no preload.
    - `https.hsts.active` (boolean)
    - `https.hsts.max_age` (integer) - Seconds, 300 (5 minutes) to 63072000 (2 years). (minimum `300`; maximum `63072000`)
    - `https.hsts.include_subdomains` (boolean)
    - `https.hsts.preload` (boolean) - Usually not recommended - needs max_age of at least 31536000 and include_subdomains.
- `alternative_hostname` (object) - Not for an alias: a second name under vhost.manitu.de that shows the same.
  - `alternative_hostname.active` (boolean) - Default true. Switched off and on again, it gets a new name.
  - `alternative_hostname.noindex` (boolean) - Ask search engines not to index it under this name (default false).
- `certificate` (string) - letsencrypt (free, added and renewed by manitu; the default) or none (rarely wanted). Let's Encrypt needs the domain at manitu (not while a transfer is pending - then the default is none) and an active website; it is usually there within an hour. A custom certificate is uploaded in the customer panel - here it is only kept. (one of `"letsencrypt"`, `"none"`)
- `status` (string) - inactive: switch it off - the files are kept, visitors get when_inactive; no Let's Encrypt certificate is renewed meanwhile. Default active. (one of `"active"`, `"inactive"`)
- `when_inactive` (object) - What visitors get while it is inactive (default: response hide).
  - `when_inactive.response` (string) - http_status_403, http_status_404, http_status_503 (tells search engines to come back), hide (as if there were no website) or page (one of manitu's, see page). (one of `"http_status_403"`, `"http_status_404"`, `"http_status_503"`, `"hide"`, `"page"`)
  - `when_inactive.page` (string) - For response page: disabled, underconstruction or maintenance (default disabled). The customer's duties (imprint, privacy information) stay his. (one of `"disabled"`, `"underconstruction"`, `"maintenance"`)
- `description` (string | null) - The customer's description, for his own overview. Left out: unchanged (set) or none (create); null or empty: none. (maxLength `1024`)

### Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "manitu_webhosting_web_vhost_create",
    "arguments": {
      "site_id": 12345,
      "fqdn": "example.com",
      "type": "website"
    }
  }
}
```

## REST

`POST https://api.manitu.de/v1/webhosting/web/vhost/create`

### Authentication

One of `X-API-Key`, `Authorization: Bearer …` - never more than one in a request.

### Request body

JSON; unknown fields are refused.

- `site_id` (integer | string, required) - The site_id from manitu_webhosting_list - never guess one. (pattern `"^[1-9][0-9]*$"`; minimum `1`)
- `fqdn` (string, required) - The name, in full - a domain of the package or a subdomain for the web, e.g. www.example.de; Unicode or ASCII, any case. (minLength `3`; maxLength `253`)
- `type` (string, required) - website, websitebuilder or alias - set does not change it; between website and alias manitu_webhosting_web_vhost_convert does, a websitebuilder stays one. (one of `"website"`, `"websitebuilder"`, `"alias"`)
- `website` (object) - Only for type website: what it shows.
  - `website.target_dir` (string) - Show this folder, relative to the web root - for a new website its own folder in htdocs, website_folder_template.api of manitu_webhosting_web_structure_get (e.g. /htdocs/www.example.com/; the older layout: /web/www.example.com/). Default: htdocs itself for a domain, htdocs/<fqdn> for a subdomain - pass it instead. Not together with redirect_url. (minLength `1`; maxLength `255`)
  - `website.redirect_url` (string) - Instead of a folder: send every visitor to this URL, e.g. https://www.example.com/ - https:// is put in front when there is no scheme. (minLength `1`; maxLength `255`)
  - `website.create_target_dir` (boolean) - Create target_dir if it is not there (default true); false: it must be there.
  - `website.allow_wordpress_xmlrpc` (boolean) - Make WordPress' XML-RPC interface reachable (default false) - only if the customer needs it: a frequent target of brute force attacks that manitu's firewall cannot block. Tell him so.
  - `website.setup_default_page` (boolean) - Put manitu's placeholder page into an empty target_dir (default true). false when the website's own files follow right after (manitu_webhosting_web_file_write) - nothing to replace then.
- `alias` (object) - Only for type alias.
  - `alias.of` (string) - The website (or websitebuilder) it belongs to, by fqdn from manitu_webhosting_web_vhost_list - required. Not an alias. (minLength `3`; maxLength `253`)
  - `alias.redirect_to_parent` (boolean) - Redirect visitors to the website's name (HTTP 301), default true; false: show the same under the alias' own name.
- `https` (object) - Not for an alias (it has its website's). Change HSTS only if the customer knows what it means: browsers keep using HTTPS only for max_age seconds, even if the certificate is gone.
  - `https.redirect` (boolean) - Send http:// visitors to https:// (default true).
  - `https.hsts` (object) - Default: active, max_age 31536000 (a year), include_subdomains, no preload.
    - `https.hsts.active` (boolean)
    - `https.hsts.max_age` (integer) - Seconds, 300 (5 minutes) to 63072000 (2 years). (minimum `300`; maximum `63072000`)
    - `https.hsts.include_subdomains` (boolean)
    - `https.hsts.preload` (boolean) - Usually not recommended - needs max_age of at least 31536000 and include_subdomains.
- `alternative_hostname` (object) - Not for an alias: a second name under vhost.manitu.de that shows the same.
  - `alternative_hostname.active` (boolean) - Default true. Switched off and on again, it gets a new name.
  - `alternative_hostname.noindex` (boolean) - Ask search engines not to index it under this name (default false).
- `certificate` (string) - letsencrypt (free, added and renewed by manitu; the default) or none (rarely wanted). Let's Encrypt needs the domain at manitu (not while a transfer is pending - then the default is none) and an active website; it is usually there within an hour. A custom certificate is uploaded in the customer panel - here it is only kept. (one of `"letsencrypt"`, `"none"`)
- `status` (string) - inactive: switch it off - the files are kept, visitors get when_inactive; no Let's Encrypt certificate is renewed meanwhile. Default active. (one of `"active"`, `"inactive"`)
- `when_inactive` (object) - What visitors get while it is inactive (default: response hide).
  - `when_inactive.response` (string) - http_status_403, http_status_404, http_status_503 (tells search engines to come back), hide (as if there were no website) or page (one of manitu's, see page). (one of `"http_status_403"`, `"http_status_404"`, `"http_status_503"`, `"hide"`, `"page"`)
  - `when_inactive.page` (string) - For response page: disabled, underconstruction or maintenance (default disabled). The customer's duties (imprint, privacy information) stay his. (one of `"disabled"`, `"underconstruction"`, `"maintenance"`)
- `description` (string | null) - The customer's description, for his own overview. Left out: unchanged (set) or none (create); null or empty: none. (maxLength `1024`)

### Response

In `data`; the rest of the body as on every call.

- `fqdn` (string, required) - The name, e.g. www.example.de - a domain or subdomain of the package; what the other tools take. Unicode for an internationalized domain.
- `fqdn_ascii` (string, required) - The same name as DNS has it (xn--... for an internationalized domain).
- `type` (string, required) - website (the customer's files from a folder, or a redirect to a URL), websitebuilder (made with manitu's website builder) or alias (a further name of a website - see alias). (one of `"website"`, `"websitebuilder"`, `"alias"`)
- `status` (string, required) - inactive: switched off, the files are kept - visitors get when_inactive. (one of `"active"`, `"inactive"`)
- `when_inactive` (object, required) - What visitors get while it is inactive.
  - `when_inactive.response` (string, required) - An HTTP status (403, 404, 503 - 503 tells search engines to come back), hide (as if there were no website) or page (a page of manitu's, see page). (one of `"http_status_403"`, `"http_status_404"`, `"http_status_503"`, `"hide"`, `"page"`)
  - `when_inactive.page` (string | null, required) - Which page, for response page: disabled, underconstruction or maintenance. (one of `"disabled"`, `"underconstruction"`, `"maintenance"`, `null`)
- `website` (object | null, required) - For type website, else null.
  - `website.target_dir` (string | null, required) - The folder shown, relative to the web root, e.g. /htdocs/www.example.com/ (the older layout: /web/...) - see manitu_webhosting_web_structure_get; null when it redirects.
  - `website.redirect_url` (string | null, required) - The URL every visitor is sent to - null when it shows a folder.
  - `website.allow_wordpress_xmlrpc` (boolean, required) - WordPress' XML-RPC interface reachable - off by default, a frequent target of brute force attacks that manitu's firewall cannot block.
- `websitebuilder` (object | null, required) - For type websitebuilder, else null. The editor opens with manitu_webhosting_web_vhost_websitebuilder_get.
  - `websitebuilder.target_dir` (string, required) - The folder manitu set for it - not to be changed.
- `alias` (object | null, required) - For type alias, else null. An alias shows what its website shows, with its HTTPS settings; status, certificate and description are its own.
  - `alias.of` (string | null, required) - The website it belongs to (fqdn) - null only for an old alias that lost it.
  - `alias.redirect_to_parent` (boolean, required) - Visitors are redirected to the website's name (HTTP 301); false: the alias shows the same under its own name.
- `https` (object | null, required) - For a website or websitebuilder; null for an alias (its website's apply).
  - `https.redirect` (boolean, required) - Visitors coming with http:// are sent to https://.
  - `https.hsts` (object, required) - HSTS (Strict-Transport-Security): browsers remember to use only HTTPS.
    - `https.hsts.active` (boolean, required)
    - `https.hsts.max_age` (integer, required) - How long browsers remember it, in seconds.
    - `https.hsts.include_subdomains` (boolean, required)
    - `https.hsts.preload` (boolean, required)
- `alternative_hostname` (object | null, required) - A second name under vhost.manitu.de that shows the same - e.g. before a domain transfer or while DNS is not there yet. Null for an alias.
  - `alternative_hostname.active` (boolean, required)
  - `alternative_hostname.fqdn` (string | null, required) - The name, e.g. 1a2b3c4d.vhost.manitu.de - null while not active. A new one each time it is switched on.
  - `alternative_hostname.noindex` (boolean, required) - Search engines are asked not to index it under this name.
- `alias_list` (array of string | null, required) - Its aliases (fqdn) - null for an alias.
- `certificate` (object | null, required) - Its SSL certificate - null if none.
  - `certificate.type` (string, required) - (one of `"letsencrypt"`, `"custom"`)
  - `certificate.status` (string, required) - pending: asked for, usually issued within an hour; error: could not be issued - often the name does not point to manitu yet. (one of `"active"`, `"pending"`, `"error"`, `"expired"`)
  - `certificate.expires_at` (string | null, required) - When it runs out (the same as manitu_webhosting_web_certificate_get) - Let's Encrypt renews in time; null while pending. (format `date-time`)
- `description` (string | null, required) - What the customer wrote about it (his description), null if nothing - not its name or user name.
- `created_at` (string | null, required) - (format `date-time`)

### Statuses

- `200` Success.
- `400` The request does not match the declared input schema.
- `401` No credential was presented, or it was not recognised.
- `403` The credential is not permitted to use this operation.
- `500` The server failed. Nothing about the request was wrong. Whether a change took effect is not known - check before trying it again.
- `503` The channel this operation forwards through is unavailable.

### Example

```sh
curl -X POST 'https://api.manitu.de/v1/webhosting/web/vhost/create' \
  -H 'X-API-Key: $API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"site_id":12345,"fqdn":"example.com","type":"website"}'
```

## Example result

```json
{
  "fqdn": "example.com",
  "fqdn_ascii": "string",
  "type": "website",
  "status": "active",
  "when_inactive": {
    "response": "http_status_403",
    "page": "disabled"
  },
  "website": {
    "target_dir": "/web",
    "redirect_url": "https://www.example.com/",
    "allow_wordpress_xmlrpc": true
  },
  "websitebuilder": {
    "target_dir": "/web"
  },
  "alias": {
    "of": "string",
    "redirect_to_parent": true
  },
  "https": {
    "redirect": true,
    "hsts": {
      "active": true,
      "max_age": 1,
      "include_subdomains": true,
      "preload": true
    }
  },
  "alternative_hostname": {
    "active": true,
    "fqdn": "example.com",
    "noindex": true
  },
  "alias_list": [
    "string"
  ],
  "certificate": {
    "type": "letsencrypt",
    "status": "active",
    "expires_at": "2026-10-23T12:00:00+02:00"
  },
  "description": "Example",
  "created_at": "2026-10-23T12:00:00+02:00"
}
```
