diff --git a/api/mailinabox.yml b/api/mailinabox.yml
new file mode 100644
index 00000000..71526c98
--- /dev/null
+++ b/api/mailinabox.yml
@@ -0,0 +1,1714 @@
+openapi: 3.0.3
+info:
+  title: Mail-in-a-Box
+  description: 'Mail-in-a-Box API HTTP specification.'
+  contact:
+    name: Richard Willis
+    url: https://github.com/badsyntax
+    email: willis.rh@gmail.com
+  license:
+    name: MIT
+    url: https://badsyntax.mit-license.org/
+  version: '0.46.0'
+externalDocs:
+  description: Find out more about Mail-in-a-box
+  url: https://mailinabox.email/
+servers:
+  - url: https://{host}/admin
+    variables:
+      host:
+        default: box.example.com
+        description: The API hostname
+security:
+  - basicAuth: []
+tags:
+  - name: User
+    description: Endpoints related to user authentication.
+  - name: System
+    description: |
+      System operations, which include system status checks, new version checks
+      and reboot status.
+  - name: SSL
+    description: |
+      TLS (SSL) Certificates operations, which include checking certificate status
+      and installing custom certificates.
+  - name: DNS
+    description: |
+      DNS operations, which include adding custom records, adding a secondary nameserver and viewing all DNS records.
+  - name: Mail Users
+    description: |
+      Mail Users operations, which include getting all users and adding/updating/removing users.
+  - name: Mail Aliases
+    description: |
+      Mail Aliases operations, which include getting all aliases and adding/updating/removing aliases.
+  - name: Web
+    description: |
+      Static web hosting operations, which include getting domain information and updating domain root directories.
+paths:
+  /me:
+    get:
+      tags:
+        - User
+      description: |
+        Get user information, used for user authentication.
+
+        Authenticate a user by supplying the auth token as a base64 encoded string in
+        format `email:password` using basic authentication headers.
+
+        If successful, a long-lived `api_key` is returned which can be used for subsequent
+        requests to the API.
+      operationId: getMe
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/MeResponse'
+              examples:
+                invalid:
+                  value:
+                    reason: Incorrect username or password
+                    status: invalid
+                ok:
+                  value:
+                    api_key: 1a2b3c4d5e6f7g8h9i0j
+                    email: user@example.com
+                    privileges:
+                      - admin
+                    status: ok
+  /system/status:
+    post:
+      tags:
+        - System
+      description: |
+        Retrieve system status. Returns an array of statuses which can include headings.
+      operationId: getSystemStatus
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SystemStatusResponse'
+              example:
+                - type: heading
+                  text: System
+                  extra: []
+                - type: warning
+                  text: This domain's DNSSEC DS record is not set
+                  extra:
+                    - monospace: false
+                      text: 'Digest Type: 2 / SHA-25'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /system/privacy:
+    get:
+      tags:
+        - System
+      description: |
+        Retrieve new-version check status.
+
+        Response:
+
+          - `true`: Private, new-version checks will not be performed
+          - `false`: Not private, new-version checks will be performed
+      operationId: getSystemPrivacyStatus
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SystemPrivacyStatusResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+    post:
+      tags:
+        - System
+      description: |
+        Update new-version check status.
+
+        Request:
+
+          - `value: private`: Disable new version checks
+          - `value: off`: Enable new version checks
+      operationId: updateSystemPrivacy
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/SystemPrivacyUpdateRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/SystemPrivacyUpdateResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /system/reboot:
+    get:
+      tags:
+        - System
+      description: |
+        Retrieve reboot status.
+
+        Response:
+
+          - `true`: A reboot is required
+          - `false`: A reboot is not required
+      operationId: getSystemRebootStatus
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SystemRebootStatusResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /system/backup/status:
+    get:
+      tags:
+        - System
+      description: |
+        Retrieve backup status.
+
+        If the list of backups is empty, this implies no backups have been made yet.
+      operationId: getSystemBackupStatus
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SystemBackupStatusResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /system/backup/config:
+    get:
+      tags:
+        - System
+      description: Retrieve backup config.
+      operationId: getSystemBackupConfig
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SystemBackupConfigResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+    post:
+      tags:
+        - System
+      description: |
+        Update backup config.
+      operationId: updateSystemBackupConfig
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/SystemBackupConfigUpdateRequest'
+            examples:
+              s3:
+                summary: S3 backup
+                value:
+                  target: s3://s3.eu-central-1.amazonaws.com/box-example-com
+                  targetUser: ACCESS_KEY
+                  targetPassword: SECRET_ACCESS_KEY
+                  minAge: 3
+              local:
+                summary: Local backup
+                value:
+                  target: local
+                  targetUser: ''
+                  targetPassword: ''
+                  minAge: 3
+              rsync:
+                summary: Rsync backup
+                value:
+                  target: rsync://username@box.example.com//backups/box.example.com
+                  targetUser: ''
+                  targetPassword: ''
+                  minAge: 3
+              off:
+                summary: Disable backups
+                value:
+                  target: 'off'
+                  targetUser: ''
+                  targetPassword: ''
+                  minAge: 0
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/SystemBackupConfigUpdateResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /ssl/status:
+    get:
+      tags:
+        - SSL
+      description: Retrieve SSL status for all domains.
+      operationId: getSSLStatus
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SSLStatusResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /ssl/csr/{domain}:
+    post:
+      tags:
+        - SSL
+      description: |
+        Generate a Certificate Signing Request (CSR) for a domain & country code.
+      operationId: generateSSLCSR
+      parameters:
+        - in: path
+          name: domain
+          schema:
+            $ref: '#/components/schemas/Hostname'
+          required: true
+          description: Domain to generate CSR for
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/SSLCSRGenerateRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/SSLCSRGenerateResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /ssl/install:
+    post:
+      tags:
+        - SSL
+      description: |
+        Install a custom certificate. The chain certificate is optional.
+      operationId: installSSLCertificate
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/SSLCertificateInstallRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/SSLCertificateInstallResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /dns/secondary-nameserver:
+    get:
+      tags:
+        - DNS
+      description: Retrieve secondary nameservers.
+      operationId: getDnsSecondaryNameserver
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/DNSSecondaryNameserverResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+    post:
+      tags:
+        - DNS
+      description: Add secondary nameservers.
+      operationId: addDnsSecondaryNameserver
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/DNSSecondaryNameserverAddRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/DNSSecondaryNameserverAddResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: Could not resolve the IP address of badhostname
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /dns/zones:
+    get:
+      tags:
+        - DNS
+      description: Retrieve DNS zones.
+      operationId: getDnsZones
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/DNSZonesResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /dns/custom:
+    get:
+      tags:
+        - DNS
+      description: Retrieve custom DNS records.
+      operationId: getDnsCustomRecords
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/DNSCustomResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /dns/custom/{domain}/{type}:
+    parameters:
+      - in: path
+        name: domain
+        schema:
+          $ref: '#/components/schemas/Hostname'
+        required: true
+        description: DNS record domain
+      - in: path
+        name: type
+        schema:
+          $ref: '#/components/schemas/DNSRecordType'
+        required: true
+        description: Record type
+    post:
+      tags:
+        - DNS
+      description: Add a custom DNS record.
+      operationId: addDnsCustomRecord
+      requestBody:
+        $ref: '#/components/requestBodies/DNSCustomRecordRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/DNSCustomRecordAddResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: "'badhostname' does not appear to be an IPv4 or IPv6 address"
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+    delete:
+      tags:
+        - DNS
+      description: Remove a custom DNS record.
+      operationId: removeDnsCustomRecord
+      requestBody:
+        $ref: '#/components/requestBodies/DNSCustomRecordRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/DNSCustomRecordRemoveResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: badhostname is not a domain name or a subdomain of a domain name managed by this box
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /dns/dump:
+    get:
+      tags:
+        - DNS
+      description: Retrieve all DNS records.
+      operationId: getDnsDump
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/DNSDumpResponse'
+              example: |
+                -
+                  - example1.com
+                  -
+                    - explanation: Required. Specifies the hostname (and priority) of the machine that handles @proxima-mail.com mail.
+                      qname: example1.com
+                      rtype: MX
+                      value: 10 box.example1.com.
+                -
+                  - example2.com
+                  -
+                    - explanation: Required. Specifies the hostname (and priority) of the machine that handles @proxima-mail.com mail.
+                      qname: example2.com
+                      rtype: MX
+                      value: 10 box.example2.com.
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/users:
+    get:
+      tags:
+        - Mail Users
+      description: Retrieve all mail users.
+      operationId: getMailUsers
+      parameters:
+        - in: query
+          name: format
+          schema:
+            $ref: '#/components/schemas/MailUsersResponseFormat'
+          description: The format of the response
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/MailUsersResponse'
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailUsersSimpleResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/users/add:
+    post:
+      tags:
+        - Mail Users
+      description: Add a new mail user.
+      operationId: addMailUser
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailUserAddRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailUserAddResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: Invalid email address
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/users/remove:
+    post:
+      tags:
+        - Mail Users
+      description: Remove a mail user.
+      operationId: removeMailUser
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailUserRemoveRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailUserRemoveResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: That's not a user (invalid@example.com)
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/users/privileges/add:
+    post:
+      tags:
+        - Mail Users
+      description: Add a privilege to a mail user.
+      operationId: addMailUserPrivilege
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailUserAddPrivilegeRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailUserAddPrivilegeResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: That's not a user (invalid@example.com)
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/users/privileges/remove:
+    post:
+      tags:
+        - Mail Users
+      description: Remove a privilege from a mail user.
+      operationId: removeMailUserPrivilege
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailUserRemovePrivilegeRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailUserRemovePrivilegeResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: That's not a user (invalid@example.com)
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/users/password:
+    post:
+      tags:
+        - Mail Users
+      description: Set a password for a user.
+      operationId: setMailUserPassword
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailUserSetPasswordRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailUserSetPasswordResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: Passwords must be at least eight characters
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/aliases:
+    get:
+      tags:
+        - Mail Aliases
+      description: Retrieve all mail aliases.
+      operationId: getMailAliases
+      parameters:
+        - in: query
+          name: format
+          schema:
+            $ref: '#/components/schemas/MailAliasesResponseFormat'
+          description: The format of the response
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/MailAliasByDomain'
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailAliasesSimpleResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/aliases/add:
+    post:
+      tags:
+        - Mail Aliases
+      description: |
+        Add or update a mail alias. If updating, you need to set `update_if_exists: 1`.
+      operationId: upsertMailAlias
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailAliasUpsertRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailAliasUpsertResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: Invalid email address (invalid@example.com)
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /mail/aliases/remove:
+    post:
+      tags:
+        - Mail Aliases
+      description: Remove a mail alias.
+      operationId: removeMailAlias
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/MailAliasRemoveRequest'
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/MailAliasRemoveResponse'
+        400:
+          description: Bad request
+          content:
+            text/html:
+              schema:
+                type: string
+                example: That's not an alias (invalid@example)
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+        5XX:
+          description: Server error
+          content:
+            text/html:
+              schema:
+                type: string
+  /web/domains:
+    get:
+      tags:
+        - Web
+      description: Retrieve all static web domains.
+      operationId: getWebDomains
+      responses:
+        200:
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/WebDomain'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+  /web/update:
+    post:
+      tags:
+        - Web
+      description: Update static websites, used for updating domain root directories.
+      operationId: updateWeb
+      responses:
+        200:
+          description: Successful operation
+          content:
+            text/html:
+              schema:
+                $ref: '#/components/schemas/WebUpdateResponse'
+        403:
+          description: Forbidden
+          content:
+            text/html:
+              schema:
+                type: string
+components:
+  securitySchemes:
+    basicAuth:
+      type: http
+      scheme: basic
+      description: |
+        Credentials can be supplied using the `Authorization` header in format `Authorization: Basic {access-token}`.
+        The `access-token` is comprised of the Base64 encoding of `username:password`. The `password` can either be
+        the users password, or the `api_key` returned from the `getMe` operation.
+  requestBodies:
+    DNSCustomRecordRequest:
+      description: The value of the DNS record
+      required: true
+      content:
+        text/plain:
+          schema:
+            type: string
+            example: 1.2.3.4
+            description: The value of the DNS record
+  schemas:
+    MailUsersResponseFormat:
+      type: string
+      enum:
+        - text
+        - json
+      example: json
+      description: Response format (`application/json` or `text/html`).
+    MailAliasesResponseFormat:
+      type: string
+      enum:
+        - text
+        - json
+      example: json
+      description: Response format (`application/json` or `text/html`).
+    MailUserSetPasswordResponse:
+      type: string
+      example: OK
+      description: Mail user set password response.
+    MailUserRemoveResponse:
+      type: string
+      example: OK
+      description: Mail user remove response.
+    MailUserAddResponse:
+      type: string
+      example: |
+        mail user added
+        updated DNS: OpenDKIM configuration
+      description: |
+        Mail user add response.
+
+        Can include information about operations related to adding new users, like updating DNS.
+    MailUserAddPrivilegeResponse:
+      type: string
+      example: OK
+      description: Mail user add admin privilege response.
+    MailUserRemovePrivilegeResponse:
+      type: string
+      example: OK
+      description: Mail user remove admin privilege response.
+    MailUsersSimpleResponse:
+      type: string
+      example: |
+        email1@example.com
+        email2@example.com
+      description: Get mail users text format response.
+    MailUsersResponse:
+      type: array
+      items:
+        $ref: '#/components/schemas/MailUserByDomain'
+      description: Get mail aliases JSON format response.
+    MailUserByDomain:
+      type: object
+      required:
+        - domain
+        - Mail Users
+      properties:
+        domain:
+          $ref: '#/components/schemas/Hostname'
+        users:
+          type: array
+          items:
+            $ref: '#/components/schemas/MailUser'
+      description: Mail users by domain.
+    MailUser:
+      type: object
+      required:
+        - email
+        - privileges
+        - status
+      properties:
+        email:
+          $ref: '#/components/schemas/Email'
+        privileges:
+          type: array
+          items:
+            $ref: '#/components/schemas/MailUserPrivilege'
+        status:
+          $ref: '#/components/schemas/MailUserStatus'
+        mailbox:
+          type: string
+          example: /home/user-data/mail/mailboxes/example.com/user
+      description: Mail user details.
+    MailAliasesSimpleResponse:
+      type: string
+      example: |
+        abuse@example.com	administrator@example.com
+        admin@example.com	administrator@example.com
+      description: Get mail aliases text format response.
+    MailAliasByDomain:
+      type: object
+      required:
+        - domain
+        - aliases
+      properties:
+        domain:
+          $ref: '#/components/schemas/Hostname'
+        aliases:
+          type: array
+          items:
+            $ref: '#/components/schemas/MailAlias'
+      description: Mail aliases by domain.
+    MailAlias:
+      type: object
+      required:
+        - address
+        - address_display
+        - forwards_to
+        - permitted_senders
+        - required
+      properties:
+        address:
+          $ref: '#/components/schemas/Email'
+        address_display:
+          $ref: '#/components/schemas/Email'
+        forwards_to:
+          type: array
+          items:
+            $ref: '#/components/schemas/Email'
+        permitted_senders:
+          type: array
+          nullable: true
+          items:
+            $ref: '#/components/schemas/Email'
+        required:
+          type: boolean
+          example: true
+      description: Mail alias details.
+    MailAliasUpsertResponse:
+      type: string
+      example: alias updated
+      description: Mail alias add/update response.
+    MailAliasUpsertRequest:
+      type: object
+      required:
+        - update_if_exists
+        - address
+        - forwards_to
+        - permitted_senders
+      properties:
+        update_if_exists:
+          type: integer
+          format: int32
+          minimum: 0
+          maximum: 1
+          example: 1
+          description: Set to `1` when updating an alias.
+        address:
+          $ref: '#/components/schemas/Email'
+        forwards_to:
+          type: string
+          example: email1@example.com, example2@example.com
+          description: |
+            If adding a regular or catch-all alias, the format needs to be `email1@example.com`.
+            Multiple address can be separated by newlines or commas.
+
+            If adding a domain alias, the format needs to be `@example.com`.
+        permitted_senders:
+          type: string
+          nullable: true
+          example: email1@example.com, example2@example.com
+          description: |
+            Mail users that can send mail claiming to be from any address on the alias domain.
+            Multiple address can be separated by newlines or commas.
+
+            Leave empty to allow any mail user listed in `forwards_to` to send mail claiming to be from any address on the alias domain.
+      description: Mail alias upsert request.
+    MailAliasRemoveResponse:
+      type: string
+      example: alias removed
+      description: Mail alias remove response.
+    MailAliasRemoveRequest:
+      type: object
+      required:
+        - address
+      properties:
+        address:
+          $ref: '#/components/schemas/Email'
+      description: Mail aliases remove request.
+    DNSRecordType:
+      enum:
+        - A
+        - AAAA
+        - CAA
+        - CNAME
+        - TXT
+        - MX
+        - SRV
+        - SSHFP
+        - NS
+      example: MX
+      description: DNS record type.
+    DNSDumpResponse:
+      type: array
+      items:
+        $ref: '#/components/schemas/DNSDumpDomains'
+      description: DNS dump response.
+    DNSDumpDomains:
+      type: array
+      items:
+        oneOf:
+          - $ref: '#/components/schemas/Hostname'
+          - $ref: '#/components/schemas/DNSDumpDomainRecords'
+      description: |
+        A list of records per domain.
+
+        The first item in the list is the domain and the second item is the list of records.
+    DNSDumpDomainRecords:
+      type: array
+      items:
+        $ref: '#/components/schemas/DNSDumpDomainRecord'
+      description: List of domain records.
+    DNSDumpDomainRecord:
+      type: object
+      required:
+        - explanation
+        - qname
+        - type
+        - value
+      properties:
+        explanation:
+          type: string
+          example: Required. Specifies the hostname (and priority) of the machine that handles @example.com mail
+        qname:
+          $ref: '#/components/schemas/Hostname'
+        rtype:
+          $ref: '#/components/schemas/DNSRecordType'
+        value:
+          type: string
+          example: 10 example.com.
+      description: Domain DNS record details.
+    DNSCustomRecord:
+      type: object
+      required:
+        - qname
+        - rtype
+        - value
+      properties:
+        qname:
+          $ref: '#/components/schemas/Hostname'
+        rtype:
+          $ref: '#/components/schemas/DNSRecordType'
+        value:
+          type: string
+          example: 10 example.com.
+      description: Custom DNS record detail detail.
+    DNSCustomResponse:
+      type: array
+      items:
+        $ref: '#/components/schemas/DNSCustomRecord'
+      description: Custom DNS records response.
+    DNSZonesResponse:
+      type: array
+      items:
+        $ref: '#/components/schemas/Hostname'
+      description: DNS zones response.
+    DNSSecondaryNameserverResponse:
+      type: object
+      required:
+        - hostnames
+      properties:
+        hostnames:
+          type: array
+          items:
+            type: string
+            example: ns1.example.com
+      description: Secondary nameserver/s response.
+    DNSCustomRecordRemoveResponse:
+      type: string
+      example: 'updated DNS: example.com'
+      description: Custom DNS record remove response.
+    DNSCustomRecordAddResponse:
+      type: string
+      example: 'updated DNS: example.com'
+      description: Custom DNS record add response.
+    DNSSecondaryNameserverAddRequest:
+      type: object
+      required:
+        - hostnames
+      properties:
+        hostnames:
+          type: string
+          description: Hostnames separated with commas or spaces
+          example: ns2.hostingcompany.com, ns3.hostingcompany.com
+      description: Secondary nameserver/s add request.
+    DNSSecondaryNameserverAddResponse:
+      type: string
+      example: 'updated DNS: example.com'
+      description: Secondary nameserver/s add response.
+    SystemPrivacyUpdateRequest:
+      type: object
+      required:
+        - value
+      properties:
+        value:
+          $ref: '#/components/schemas/SystemPrivacyStatus'
+      description: Update system privacy request.
+    SystemPrivacyStatus:
+      type: string
+      enum:
+        - private
+        - 'off'
+      example: private
+      description: System privacy status.
+    MailUserSetPasswordRequest:
+      type: object
+      required:
+        - email
+        - password
+      properties:
+        email:
+          $ref: '#/components/schemas/Email'
+        password:
+          type: string
+      description: Mail user set password request.
+    MailUserAddRequest:
+      type: object
+      required:
+        - email
+        - password
+        - privileges
+      properties:
+        email:
+          $ref: '#/components/schemas/Email'
+        password:
+          type: string
+        privileges:
+          $ref: '#/components/schemas/MailUserPrivilege'
+      description: Mail user add request.
+    MailUserRemoveRequest:
+      type: object
+      required:
+        - email
+      properties:
+        email:
+          $ref: '#/components/schemas/Email'
+      description: Mail user remove request.
+    MailUserStatus:
+      type: string
+      enum:
+        - active
+        - inactive
+      example: active
+      description: Mail user status.
+    MailUserPrivilege:
+      type: string
+      enum:
+        - admin
+        - ''
+      example: admin
+      description: Mail user privilege.
+    MailUserAddPrivilegeRequest:
+      type: object
+      required:
+        - email
+        - privilege
+      properties:
+        email:
+          $ref: '#/components/schemas/Email'
+        privilege:
+          $ref: '#/components/schemas/MailUserPrivilege'
+      description: Mail user add privilege request.
+    MailUserRemovePrivilegeRequest:
+      type: object
+      required:
+        - email
+        - privilege
+      properties:
+        email:
+          $ref: '#/components/schemas/Email'
+        privilege:
+          $ref: '#/components/schemas/MailUserPrivilege'
+      description: Mail user remove privilege request.
+    SSLCSRGenerateRequest:
+      type: object
+      required:
+        - countrycode
+      properties:
+        countrycode:
+          type: string
+          example: GB
+      description: Generate SSL CSR request.
+    SSLCSRGenerateResponse:
+      type: string
+      example: |
+        -----BEGIN CERTIFICATE REQUEST-----
+        MIICaDCCAVACAQAwIzELMAkGA1UEBhMCQlMxFDASBgNVBAMMC2V4YW1wbGUuY29t
+        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3K6dwLM2Nk8kVhIBaZmp
+        eY6y7O0T3jrexEKlW839TVYdcH+K35V1NxilbMFKMuHeowGwFyyiqOy/OUYNeq+T
+        Rz3s4b1qG2p01dwlsXHHYmXLYTAhvqvY+CU5ksieuZbyHRTwbHViQ0xtRXwoVCnj
+        CkN7kJVpkLfVN0/BG6NBFpv/JI8F+hwp+IHdkC1gUXRrLJNC79ERqFP8HoqdQWNw
+        OGGFaOe2aQhvj2zt8wFncyKVc40UKVbSzGGzdL2MPiAJHgZ2lmeY1xDyX1lOt12R
+        IFPwtxmbxaxYaVfe2hxl7m88xV3OjYcKgwVYDusk2XJ37cGew5g+NbBvzEeEUpF9
+        5wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAD7UPC3/Nkgpn53mT9puUonYdJg9
+        SD8vvTK/N78CzoEgPNyq+bYbqlcvVPKIdItf9TMiqfOSvW3e3NvkRisYle8Qp+0C
+        8pafXBvQ9eHt5CFeJn4sH9GnxeflOZT/P9Jnp71KtZQvOobirX4GgEWs79g+/NHb
+        Zyf8rbadt9HruNhKA5nlP8cn7Rdc/iuJU8MVSQszI1s1DEcXMPxr6iqb2g87/ifH
+        lWcK59kvRJkCcPhPzjpUy9NulucH4WFA/WqKeDNFS/oC+upV5w8EDEcfnenJFG+N
+        JmFDQESSfUxLPHLC660Wnf3GmrP/duZHpPC+qTe8b1AlQ7zDT3cOaAQ+Mb0=
+        -----END CERTIFICATE REQUEST-----
+      description: Generate SSL CSR response.
+    SSLCertificateInstallRequest:
+      type: object
+      required:
+        - domain
+        - cert
+        - chain
+      properties:
+        domain:
+          $ref: '#/components/schemas/Hostname'
+        cert:
+          type: string
+          description: TLS/SSL certificate
+          example: |
+            -----BEGIN CERTIFICATE-----
+            MIICaDCCAVACAQAwIzELMAkGA1UEBhMCQlMxFDASBgNVBAMMC2V4YW1wbGUuY29t
+            MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3K6dwLM2Nk8kVhIBaZmp
+            eY6y7O0T3jrexEKlW839TVYdcH+K35V1NxilbMFKMuHeowGwFyyiqOy/OUYNeq+T
+            Rz3s4b1qG2p01dwlsXHHYmXLYTAhvqvY+CU5ksieuZbyHRTwbHViQ0xtRXwoVCnj
+            CkN7kJVpkLfVN0/BG6NBFpv/JI8F+hwp+IHdkC1gUXRrLJNC79ERqFP8HoqdQWNw
+            OGGFaOe2aQhvj2zt8wFncyKVc40UKVbSzGGzdL2MPiAJHgZ2lmeY1xDyX1lOt12R
+            IFPwtxmbxaxYaVfe2hxl7m88xV3OjYcKgwVYDusk2XJ37cGew5g+NbBvzEeEUpF9
+            5wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAD7UPC3/Nkgpn53mT9puUonYdJg9
+            SD8vvTK/N78CzoEgPNyq+bYbqlcvVPKIdItf9TMiqfOSvW3e3NvkRisYle8Qp+0C
+            8pafXBvQ9eHt5CFeJn4sH9GnxeflOZT/P9Jnp71KtZQvOobirX4GgEWs79g+/NHb
+            Zyf8rbadt9HruNhKA5nlP8cn7Rdc/iuJU8MVSQszI1s1DEcXMPxr6iqb2g87/ifH
+            lWcK59kvRJkCcPhPzjpUy9NulucH4WFA/WqKeDNFS/oC+upV5w8EDEcfnenJFG+N
+            JmFDQESSfUxLPHLC660Wnf3GmrP/duZHpPC+qTe8b1AlQ7zDT3cOaAQ+Mb0=
+            -----END CERTIFICATE-----
+        chain:
+          type: string
+          description: TLS/SSL intermediate chain (if provided, else empty string)
+          example: |
+            -----BEGIN CERTIFICATE-----
+            MIICaDCCAVACAQAwIzELMAkGA1UEBhMCQlMxFDASBgNVBAMMC2V4YW1wbGUuY29t
+            MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3K6dwLM2Nk8kVhIBaZmp
+            eY6y7O0T3jrexEKlW839TVYdcH+K35V1NxilbMFKMuHeowGwFyyiqOy/OUYNeq+T
+            Rz3s4b1qG2p01dwlsXHHYmXLYTAhvqvY+CU5ksieuZbyHRTwbHViQ0xtRXwoVCnj
+            CkN7kJVpkLfVN0/BG6NBFpv/JI8F+hwp+IHdkC1gUXRrLJNC79ERqFP8HoqdQWNw
+            OGGFaOe2aQhvj2zt8wFncyKVc40UKVbSzGGzdL2MPiAJHgZ2lmeY1xDyX1lOt12R
+            IFPwtxmbxaxYaVfe2hxl7m88xV3OjYcKgwVYDusk2XJ37cGew5g+NbBvzEeEUpF9
+            5wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAD7UPC3/Nkgpn53mT9puUonYdJg9
+            SD8vvTK/N78CzoEgPNyq+bYbqlcvVPKIdItf9TMiqfOSvW3e3NvkRisYle8Qp+0C
+            8pafXBvQ9eHt5CFeJn4sH9GnxeflOZT/P9Jnp71KtZQvOobirX4GgEWs79g+/NHb
+            Zyf8rbadt9HruNhKA5nlP8cn7Rdc/iuJU8MVSQszI1s1DEcXMPxr6iqb2g87/ifH
+            lWcK59kvRJkCcPhPzjpUy9NulucH4WFA/WqKeDNFS/oC+upV5w8EDEcfnenJFG+N
+            JmFDQESSfUxLPHLC660Wnf3GmrP/duZHpPC+qTe8b1AlQ7zDT3cOaAQ+Mb0=
+            -----END CERTIFICATE-----
+      description: Install certificate request. `chain` can be an empty string.
+    SSLCertificateInstallResponse:
+      type: string
+      example: OK
+      description: Install certificate response.
+    SystemPrivacyStatusResponse:
+      type: boolean
+      description: |
+        System privacy status response.
+
+          - `true`: Private, new-version checks will not be performed
+          - `false`: Not private, new-version checks will be performed
+      example: false
+    SystemPrivacyUpdateResponse:
+      type: string
+      example: OK
+      description: System privacy update response.
+    SystemRebootStatusResponse:
+      type: boolean
+      description: |
+        System reboot status response.
+
+          - `true`: A reboot is required
+          - `false`: A reboot is not required
+      example: true
+    SystemStatusResponse:
+      type: array
+      items:
+        $ref: '#/components/schemas/StatusEntry'
+      description: System status response.
+    StatusEntry:
+      type: object
+      required:
+        - type
+        - text
+        - extra
+      properties:
+        type:
+          $ref: '#/components/schemas/StatusEntryType'
+        text:
+          type: string
+          example: This domain's DNSSEC DS record is not set
+        extra:
+          type: array
+          items:
+            $ref: '#/components/schemas/StatusEntryExtra'
+      description: System status entry.
+    StatusEntryType:
+      type: string
+      enum:
+        - heading
+        - ok
+        - warning
+        - error
+      example: warning
+      description: System status entry type.
+    StatusEntryExtra:
+      type: object
+      required:
+        - monospace
+        - text
+      properties:
+        monospace:
+          type: boolean
+          example: false
+        text:
+          type: string
+          example: 'Digest Type: 2 / SHA-256'
+      description: System entry extra information.
+    SystemBackupConfigUpdateRequest:
+      type: object
+      required:
+        - target
+        - target_user
+        - target_pass
+        - min_age
+      properties:
+        target:
+          type: string
+          format: hostname
+          example: s3://s3.eu-central-1.amazonaws.com/box-example-com
+        target_user:
+          type: string
+          example: username
+        target_pass:
+          type: string
+          example: password
+        min_age:
+          type: integer
+          format: int32
+          minimum: 1
+          example: 3
+      description: Backup config update request.
+    SystemBackupConfigUpdateResponse:
+      type: string
+      example: OK
+      description: Backup config update response.
+    SystemBackupConfigResponse:
+      type: object
+      required:
+        - enc_pw_file
+        - file_target_directory
+        - min_age_in_days
+        - ssh_pub_key
+        - target
+      properties:
+        enc_pw_file:
+          type: string
+          example: /home/user-data/backup/secret_key.txt
+        file_target_directory:
+          type: string
+          example: /home/user-data/backup/encrypted
+        min_age_in_days:
+          type: integer
+          format: int32
+          minimum: 1
+          example: 3
+        ssh_pub_key:
+          type: string
+          example: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDb root@box.example.com\n
+        target:
+          type: string
+          format: hostname
+          example: s3://s3.eu-central-1.amazonaws.com/box-example-com
+        target_user:
+          type: string
+        target_pass:
+          type: string
+      description: Backup config response.
+    SystemBackupStatusResponse:
+      type: object
+      required:
+        - unmatched_file_size
+      properties:
+        backups:
+          type: array
+          items:
+            $ref: '#/components/schemas/SystemBackupStatus'
+        unmatched_file_size:
+          type: integer
+          format: int32
+          example: 0
+        error:
+          type: string
+          example: Something is wrong with the backup
+      description: Backup status response. Lists the status for all backups.
+    SystemBackupStatus:
+      type: object
+      required:
+        - date
+        - date_delta
+        - date_str
+        - full
+        - size
+        - volumes
+      properties:
+        date:
+          type: string
+          format: date-time
+          example: 20200801T023706Z
+        date_delta:
+          type: string
+          example: 15 hours, 40 minutes
+        date_str:
+          type: string
+          example: 2020-08-01 03:37:06 BST
+        deleted_in:
+          type: string
+          example: approx. 6 days
+        full:
+          type: boolean
+          example: false
+        size:
+          type: integer
+          format: int32
+          example: 125332
+        volumes:
+          type: integer
+          format: int32
+          example: 1
+      description: Backup status details.
+    SSLStatusResponse:
+      type: object
+      required:
+        - can_provision
+        - status
+      properties:
+        can_provision:
+          type: array
+          items:
+            type: string
+        status:
+          type: array
+          items:
+            $ref: '#/components/schemas/SSLStatus'
+      description: SSL status response for all relevant domains.
+    SSLStatus:
+      type: object
+      required:
+        - domain
+        - status
+        - text
+      properties:
+        domain:
+          $ref: '#/components/schemas/Hostname'
+        status:
+          $ref: '#/components/schemas/SSLStatusType'
+        text:
+          type: string
+          example: Signed & valid. The certificate expires in 87 days on 10/28/20.
+      description: SSL status details for domain.
+    SSLStatusType:
+      type: string
+      enum:
+        - success
+        - danger
+        - not-applicable
+      example: success
+      description: SSL status type.
+    Email:
+      type: string
+      format: email
+      example: user@example.com
+      description: Email format.
+    Hostname:
+      type: string
+      format: hostname
+      example: example.com
+      description: Hostname format.
+    MeResponse:
+      type: object
+      required:
+        - status
+      properties:
+        api_key:
+          type: string
+          example: 12345abcde
+        email:
+          $ref: '#/components/schemas/Email'
+        privileges:
+          type: array
+          items:
+            $ref: '#/components/schemas/MailUserPrivilege'
+        reason:
+          type: string
+          example: Incorrect username or password
+        status:
+          $ref: '#/components/schemas/MeAuthStatus'
+      description: Me (user) response.
+    MeAuthStatus:
+      type: string
+      enum:
+        - ok
+        - invalid
+      example: invalid
+      description: Me (user) authentication result.
+    WebDomain:
+      type: object
+      required:
+        - custom_root
+        - domain
+        - root
+        - ssl_certificate
+        - static_enabled
+      properties:
+        custom_root:
+          type: string
+          example: /home/user-data/www/example.com
+        domain:
+          $ref: '#/components/schemas/Hostname'
+        root:
+          type: string
+          example: /home/user-data/www/default
+        ssl_certificate:
+          type: array
+          minItems: 2
+          maxItems: 2
+          uniqueItems: true
+          items:
+            oneOf:
+              - type: string
+                example: No certificate installed.
+              - type: string
+                enum:
+                  - danger
+                  - success
+                example: danger
+        static_enabled:
+          type: boolean
+          example: true
+      description: Web domain details.
+    WebUpdateResponse:
+      type: string
+      example: web updated
+      description: Web update response.