{
    "openapi": "3.0.0",
    "info": {
        "title": "Email System API",
        "description": "Manage email domains, mailboxes, forwarders, catch-all addresses, customer accounts and IMAP migrations from your own systems.\n\n**Address.** Send every request to the address you sign in to the panel at. Each path below starts with /api/v1 (two reads also have a /api/v2 form).\n\n**Your key.** Send an API key from the panel's API Keys page in the X-API-KEY header. Without one the answer is 401 {\"message\":\"API key is missing\"}; with an unknown, revoked or expired one, 401 {\"message\":\"Invalid API key\"}. Five failed tries with the same wrong key from one address lock that key out there for five minutes: 429 with retry_after, the seconds left. A key acts with its account's role: an admin (reseller) key reads and writes, while a key of a customer account with the user role reads and gets 403 on every write. There are no read-only or scoped keys.\n\n**Headers.** Send Accept: application/json on every request, and Content-Type: application/json with a body. Without the Accept header, a refusal the framework raises (a 403 for the role, a 429) comes back as an HTML page instead of JSON.\n\n**Errors.** Branch on the status code, and on a code where one is given (code subscription_required on a mailbox create, error dns_check_quota_exceeded on a DNS check), never on the wording. Refusals carry message, except on the customer account endpoints (/api/v1/users), which answer error. A validation error is 422 with errors, the problems per field.\n\n**Rate limit.** Plan for 30 requests a minute per IP address, across /api/v1 and /api/v2 together, whichever key they carry: two keys used from one server share them. Over it the answer is 429 with a Retry-After header. Revoking a mailbox's access is limited to 10 a minute on top.\n\n**No webhooks.** The API never calls you. To follow something that finishes later, such as a new domain's security check or a migration, read it again: the domain's provisioning_state, the migration job's status.\n\n**Billing.** Domains, forwarders, aliases and catch-all addresses are free. Each mailbox is billed monthly to the admin account that created it, or that created the customer account it was created under, from the next invoice. Deleting one lowers the next invoice; the period already paid is not refunded.",
        "license": {
            "name": "MIT",
            "url": "https://opensource.org/licenses/MIT"
        },
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "/",
            "description": "The host these docs were loaded from; every path below is absolute, so Try it out calls exactly the path it shows"
        }
    ],
    "paths": {
        "/api/v1/user": {
            "get": {
                "tags": [
                    "Users"
                ],
                "summary": "The account behind the key",
                "description": "Who the key belongs to: a cheap way to check a key works and read its role. The account itself, never one named in impersonation headers. Any role's key.",
                "operationId": "getKeyAccount",
                "responses": {
                    "200": {
                        "description": "The account's own profile, as a bare object with no data envelope. Timestamps are ISO 8601 except where a field says otherwise.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "id",
                                        "name",
                                        "email",
                                        "email_verified_at",
                                        "role",
                                        "created_by",
                                        "owner_id",
                                        "created_at",
                                        "updated_at",
                                        "suspended",
                                        "suspended_at",
                                        "first_name",
                                        "last_name",
                                        "address",
                                        "address_line_2",
                                        "zip_code",
                                        "city",
                                        "state",
                                        "country",
                                        "vat_number",
                                        "phone",
                                        "company_name",
                                        "tax_id",
                                        "billing_email",
                                        "onboarding_completed",
                                        "onboarding_completed_at",
                                        "onboarding_steps",
                                        "tutorial_completed",
                                        "tutorial_skipped",
                                        "tutorial_completed_at",
                                        "tutorial_progress",
                                        "two_factor_method",
                                        "two_factor_confirmed_at",
                                        "hourly_email_limit",
                                        "daily_email_limit",
                                        "unlimited_sending",
                                        "limits_last_updated_at",
                                        "identity_verified",
                                        "identity_verified_at",
                                        "last_login_at",
                                        "last_active_at",
                                        "payment_status",
                                        "payment_failure_count",
                                        "last_payment_failure_at",
                                        "payment_grace_period_ends_at",
                                        "first_payment_completed",
                                        "first_payment_at",
                                        "billing_cycle_start",
                                        "trial_ends_at",
                                        "stripe_customer_created",
                                        "stripe_customer_created_at",
                                        "braintree_subscription_ends_at",
                                        "is_using_braintree",
                                        "module_nudge_dismissed_at",
                                        "identity_verification_status",
                                        "analytics_consent",
                                        "mailboxes_managed_range",
                                        "billing_system"
                                    ],
                                    "properties": {
                                        "id": {
                                            "type": "integer",
                                            "example": 12
                                        },
                                        "name": {
                                            "type": "string",
                                            "example": "Example Reseller"
                                        },
                                        "email": {
                                            "type": "string",
                                            "format": "email",
                                            "example": "api@reseller.test"
                                        },
                                        "email_verified_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "role": {
                                            "type": "string",
                                            "enum": [
                                                "user",
                                                "admin",
                                                "superadmin"
                                            ],
                                            "example": "admin"
                                        },
                                        "created_by": {
                                            "description": "The account that created this one",
                                            "type": "integer",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "owner_id": {
                                            "description": "The account that manages this one",
                                            "type": "integer",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "created_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00.000000Z",
                                            "nullable": true
                                        },
                                        "updated_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00.000000Z",
                                            "nullable": true
                                        },
                                        "suspended": {
                                            "description": "1 or 0, not a boolean",
                                            "type": "integer",
                                            "enum": [
                                                0,
                                                1
                                            ],
                                            "example": 0
                                        },
                                        "suspended_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "first_name": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "last_name": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "address": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "address_line_2": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "zip_code": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "city": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "state": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "country": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "vat_number": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "phone": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "company_name": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "tax_id": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "billing_email": {
                                            "type": "string",
                                            "format": "email",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "onboarding_completed": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "onboarding_completed_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "onboarding_steps": {
                                            "description": "JSON, sent as a string",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "tutorial_completed": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "tutorial_skipped": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "tutorial_completed_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "tutorial_progress": {
                                            "type": "object",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "two_factor_method": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "two_factor_confirmed_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "hourly_email_limit": {
                                            "description": "Null means the plan default",
                                            "type": "integer",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "daily_email_limit": {
                                            "description": "Null means the plan default",
                                            "type": "integer",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "unlimited_sending": {
                                            "description": "1 or 0, not a boolean",
                                            "type": "integer",
                                            "enum": [
                                                0,
                                                1
                                            ],
                                            "example": 0
                                        },
                                        "limits_last_updated_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "identity_verified": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "identity_verified_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "last_login_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "last_active_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "payment_status": {
                                            "type": "string",
                                            "enum": [
                                                "active",
                                                "failed",
                                                "grace_period",
                                                "suspended"
                                            ],
                                            "example": "active"
                                        },
                                        "payment_failure_count": {
                                            "type": "integer",
                                            "example": 0
                                        },
                                        "last_payment_failure_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "payment_grace_period_ends_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "first_payment_completed": {
                                            "description": "1 or 0, not a boolean",
                                            "type": "integer",
                                            "enum": [
                                                0,
                                                1
                                            ],
                                            "example": 0
                                        },
                                        "first_payment_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "billing_cycle_start": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "trial_ends_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "stripe_customer_created": {
                                            "description": "1 or 0, not a boolean",
                                            "type": "integer",
                                            "enum": [
                                                0,
                                                1
                                            ],
                                            "example": 0
                                        },
                                        "stripe_customer_created_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "braintree_subscription_ends_at": {
                                            "description": "YYYY-MM-DD HH:MM:SS, not ISO 8601",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "is_using_braintree": {
                                            "description": "1 or 0, not a boolean",
                                            "type": "integer",
                                            "enum": [
                                                0,
                                                1
                                            ],
                                            "example": 0
                                        },
                                        "module_nudge_dismissed_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "identity_verification_status": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "analytics_consent": {
                                            "description": "Null until the account answers the cookie banner",
                                            "type": "boolean",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "mailboxes_managed_range": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "billing_system": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/migrations": {
            "get": {
                "tags": [
                    "Migrations"
                ],
                "summary": "List migration jobs",
                "description": "Every job whose destination is a mailbox GET /api/v1/mailboxes lists for the key: one the account created, or one a user the account created made. A login address is not one. A superadmin sees them all, including jobs into an address with no mailbox here. An unreachable mail server gives an empty list, not an error. Needs an admin or superadmin key.",
                "operationId": "getMigrationJobs",
                "responses": {
                    "200": {
                        "description": "The accessible jobs",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "data": {
                                            "properties": {
                                                "total": {
                                                    "type": "integer",
                                                    "example": 2
                                                },
                                                "jobs": {
                                                    "description": "For an admin whose jobs are not the first entries of the mail server's list this arrives as a JSON object keyed by position, since the filter keeps the server's keys",
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/MigrationJob"
                                                    }
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure here (the database or the audit log); an unreachable mail server is not one, it answers 200 with no jobs",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to fetch migration jobs"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on; null in production",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Migrations"
                ],
                "summary": "Create a migration job",
                "description": "Creates a job on the mail server that pulls a remote IMAP account into a mailbox here. The job runs on its interval once active is true; omitted, it is created switched off. Needs an admin or superadmin key, and the destination must be a mailbox GET /api/v1/mailboxes lists for the key (one the account created, or one a user the account created made), the rule the list and the by-id operations read jobs through, so the new job is one the key can then manage; a superadmin may name any mailbox.",
                "operationId": "createMigrationJob",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/MigrationJobRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The job was created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Migration job created successfully"
                                        },
                                        "data": {
                                            "properties": {
                                                "job_id": {
                                                    "description": "Not an id: the mail server's reply to the create, passed through as it came, since the mail server reports no id for a new job. A reply of type danger means it refused the job even though this answered 201.",
                                                    "type": "array",
                                                    "items": {
                                                        "properties": {
                                                            "type": {
                                                                "type": "string",
                                                                "example": "success"
                                                            },
                                                            "log": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                }
                                                            },
                                                            "msg": {
                                                                "type": "array",
                                                                "items": {
                                                                    "type": "string"
                                                                }
                                                            }
                                                        },
                                                        "type": "object"
                                                    },
                                                    "example": [
                                                        {
                                                            "type": "success",
                                                            "log": [
                                                                "syncjob",
                                                                "add"
                                                            ],
                                                            "msg": [
                                                                "mailbox_modified",
                                                                "john@example.test"
                                                            ]
                                                        }
                                                    ]
                                                },
                                                "job": {
                                                    "oneOf": [
                                                        {
                                                            "$ref": "#/components/schemas/MigrationJob"
                                                        }
                                                    ],
                                                    "nullable": true,
                                                    "description": "Null today: without an id the new job cannot be looked up"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A destination mailbox outside the account's reach, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "status": {
                                            "description": "Sent with the mailbox refusal",
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "success": {
                                            "description": "Sent with the role refusal",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to create a migration for this mailbox"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "mailbox": {
                                        "summary": "A destination mailbox outside the account's reach",
                                        "value": {
                                            "status": "error",
                                            "message": "You do not have permission to create a migration for this mailbox"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A required field is missing or invalid, or username is not a mailbox here",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "type": "object",
                                            "example": {
                                                "username": [
                                                    "The username field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server answered the create with an error status, or the request did not reach it",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to create migration job"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on, null in production; absent when the mail server answered with an error status",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/migrations/{id}": {
            "get": {
                "tags": [
                    "Migrations"
                ],
                "summary": "Get a migration job and its log",
                "description": "One job from the list GET /api/v1/migrations gives, with the mail server's log entries for it. Needs an admin or superadmin key.",
                "operationId": "getMigrationJob",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "The job id",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The job and its log",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "data": {
                                            "properties": {
                                                "job": {
                                                    "$ref": "#/components/schemas/MigrationJob"
                                                },
                                                "logs": {
                                                    "description": "The mail server's log entries for this job; empty when it has not run, or when the log could not be read",
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    }
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No job with this id in the list GET /api/v1/migrations gives; an unreachable mail server empties that list, so it answers 404 too",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/MigrationError"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure here (the database or the audit log); an unreachable mail server answers 404 instead, since the list is then empty",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to fetch migration job"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on; null in production",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Migrations"
                ],
                "summary": "Update a migration job",
                "description": "Changes the settings sent on a job from the list GET /api/v1/migrations gives, and leaves the rest. PATCH is accepted as an alias. Needs an admin or superadmin key.",
                "operationId": "updateMigrationJob",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "The job id",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/MigrationJobUpdate"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The job as it is now",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Migration job updated successfully"
                                        },
                                        "data": {
                                            "properties": {
                                                "job": {
                                                    "oneOf": [
                                                        {
                                                            "$ref": "#/components/schemas/MigrationJob"
                                                        }
                                                    ],
                                                    "nullable": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No job with this id in the list GET /api/v1/migrations gives; an unreachable mail server empties that list, so it answers 404 too",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/MigrationError"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field is invalid",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "type": "object",
                                            "example": {
                                                "enc1": [
                                                    "The selected enc1 is invalid."
                                                ]
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server answered the edit with an error status, or the request did not reach it",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to update migration job"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on, null in production; absent when the mail server answered with an error status",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Migrations"
                ],
                "summary": "Delete a migration job",
                "description": "Removes a job from the list GET /api/v1/migrations gives from the mail server; mail already copied stays in the destination mailbox. Needs an admin or superadmin key.",
                "operationId": "deleteMigrationJob",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "The job id",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The job is gone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Migration job deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No job with this id in the list GET /api/v1/migrations gives; an unreachable mail server empties that list, so it answers 404 too",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/MigrationError"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server answered the delete with an error status, or the request did not reach it; the job is kept, repeat the call",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to delete migration job"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on, null in production; absent when the mail server answered with an error status",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/migrations/stats": {
            "get": {
                "tags": [
                    "Migrations"
                ],
                "summary": "Count the migration jobs",
                "description": "How many jobs the list GET /api/v1/migrations gives holds, how many are switched on, how many are running now, and its first five in the mail server's order. Needs an admin or superadmin key.",
                "operationId": "getMigrationJobStats",
                "responses": {
                    "200": {
                        "description": "The counts",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "data": {
                                            "properties": {
                                                "total_jobs": {
                                                    "type": "integer",
                                                    "example": 2
                                                },
                                                "active_jobs": {
                                                    "type": "integer",
                                                    "example": 1
                                                },
                                                "running_jobs": {
                                                    "type": "integer",
                                                    "example": 0
                                                },
                                                "recent_jobs": {
                                                    "description": "The first five of the list, in the mail server's order; nothing sorts them by date",
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/MigrationJob"
                                                    }
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure here (the database or the audit log); an unreachable mail server is not one, it answers 200 with no jobs",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to fetch migration statistics"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on; null in production",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/migrations/{id}/toggle": {
            "post": {
                "tags": [
                    "Migrations"
                ],
                "summary": "Switch a migration job on or off",
                "description": "Flips active on the mail server for a job from the list GET /api/v1/migrations gives: an active job is scheduled on its interval, an inactive one is not. No body. Needs an admin or superadmin key.",
                "operationId": "toggleMigrationJob",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "The job id",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The job as it is now, and its new state",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Migration job status toggled successfully"
                                        },
                                        "data": {
                                            "properties": {
                                                "job": {
                                                    "oneOf": [
                                                        {
                                                            "$ref": "#/components/schemas/MigrationJob"
                                                        }
                                                    ],
                                                    "nullable": true
                                                },
                                                "active": {
                                                    "type": "boolean",
                                                    "example": false
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No job with this id in the list GET /api/v1/migrations gives; an unreachable mail server empties that list, so it answers 404 too",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/MigrationError"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server answered the edit with an error status, or the request did not reach it",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to toggle migration job status"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on, null in production; absent when the mail server answered with an error status",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/status": {
            "get": {
                "tags": [
                    "Status"
                ],
                "summary": "Get API health status",
                "description": "Returns health status of the API and connected services. Needs an admin or superadmin key.",
                "operationId": "getApiStatus",
                "responses": {
                    "200": {
                        "description": "Successful operation",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "healthy"
                                        },
                                        "timestamp": {
                                            "type": "string",
                                            "format": "date-time"
                                        },
                                        "services": {
                                            "properties": {
                                                "database": {
                                                    "properties": {
                                                        "status": {
                                                            "type": "string"
                                                        },
                                                        "message": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "type": "object"
                                                },
                                                "mailcow": {
                                                    "properties": {
                                                        "status": {
                                                            "type": "string"
                                                        },
                                                        "message": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "type": "object"
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "api_version": {
                                            "type": "string"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/dashboard": {
            "get": {
                "tags": [
                    "Status"
                ],
                "summary": "Get dashboard statistics",
                "description": "Returns consolidated statistics about domains, mailboxes, and migrations. Needs an admin or superadmin key.",
                "operationId": "getDashboardStats",
                "responses": {
                    "200": {
                        "description": "Successful operation",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "data": {
                                            "properties": {
                                                "timestamp": {
                                                    "type": "string",
                                                    "format": "date-time"
                                                },
                                                "email_system": {
                                                    "properties": {
                                                        "domains_count": {
                                                            "type": "integer"
                                                        },
                                                        "mailboxes_count": {
                                                            "type": "integer"
                                                        },
                                                        "total_quota_mb": {
                                                            "type": "number"
                                                        },
                                                        "used_quota_mb": {
                                                            "type": "number"
                                                        },
                                                        "quota_usage_percent": {
                                                            "type": "number"
                                                        },
                                                        "aliases_count": {
                                                            "type": "integer"
                                                        }
                                                    },
                                                    "type": "object"
                                                },
                                                "migrations": {
                                                    "properties": {
                                                        "total_count": {
                                                            "type": "integer"
                                                        },
                                                        "active_count": {
                                                            "type": "integer"
                                                        },
                                                        "running_count": {
                                                            "type": "integer"
                                                        },
                                                        "recent_jobs": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "object"
                                                            }
                                                        }
                                                    },
                                                    "type": "object"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on; null in production",
                                            "type": "string",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/search": {
            "get": {
                "tags": [
                    "Status"
                ],
                "summary": "Search across all resources",
                "description": "Search for domains, mailboxes, aliases, and migrations matching the query. Needs an admin or superadmin key.",
                "operationId": "searchResources",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "description": "Search query (minimum 3 characters)",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "minLength": 3
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful operation",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "query": {
                                            "type": "string"
                                        },
                                        "data": {
                                            "properties": {
                                                "domains": {
                                                    "description": "Up to ten, as GET /api/v1/domains lists them; always empty for a user-role key",
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Domain"
                                                    }
                                                },
                                                "mailboxes": {
                                                    "description": "Up to ten",
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Mailbox"
                                                    }
                                                },
                                                "aliases": {
                                                    "description": "Up to ten forwarders, aliases or catch-alls, each shaped as a forwarder",
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Forwarder"
                                                    }
                                                },
                                                "migrations": {
                                                    "description": "Up to ten migration jobs whose source or destination matches",
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/MigrationJob"
                                                    }
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Search query must be at least 3 characters long"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A key on a user-role account answers this; a suspended account, or a key that may not act for the account named in its impersonation headers, answers {message} alone",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "error"
                                        },
                                        "message": {
                                            "type": "string"
                                        },
                                        "error": {
                                            "description": "The exception message when debug mode is on; null in production",
                                            "type": "string",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/catch-all": {
            "get": {
                "tags": [
                    "Catch-All"
                ],
                "summary": "Get list of catch-all addresses",
                "description": "The catch-alls the key can see: a superadmin sees all of them, an admin the ones it created and the ones its users created, any other key the ones it created. Any role's key.",
                "operationId": "getCatchAllList",
                "parameters": [
                    {
                        "name": "domain_id",
                        "in": "query",
                        "description": "Only this domain's catch-all",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "active",
                        "in": "query",
                        "description": "Only active (true) or inactive (false) catch-alls",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "created_by",
                        "in": "query",
                        "description": "Only catch-alls this account created",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "created_at_from",
                        "in": "query",
                        "description": "Only catch-alls created on or after this date (YYYY-MM-DD)",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "created_at_to",
                        "in": "query",
                        "description": "Only catch-alls created on or before this date",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "updated_at_from",
                        "in": "query",
                        "description": "Only catch-alls changed on or after this date",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "updated_at_to",
                        "in": "query",
                        "description": "Only catch-alls changed on or before this date",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Part of the address, destinations or private comment",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "Any other value sorts by created_at",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "created_at",
                            "enum": [
                                "address",
                                "active",
                                "created_at",
                                "updated_at"
                            ]
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "Applied only with a sort_by from the list",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "desc",
                            "enum": [
                                "asc",
                                "desc"
                            ]
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Number of items per page: 15 by default, at most 200. A larger value returns 200; 0, a negative or a non-numeric value returns 15.",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "maximum": 200,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One page of catch-alls",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data",
                                        "meta",
                                        "links",
                                        "timestamp"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/CatchAll"
                                            }
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PageMeta"
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PageLinks"
                                        },
                                        "timestamp": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00+00:00"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Catch-All"
                ],
                "summary": "Create a catch-all",
                "description": "Sends mail for any address on the domain that has no mailbox or forwarder to the mailboxes in goto_array. One per domain. Catch-alls are free, so the domain needs at least one mailbox first (a superadmin key is exempt). Needs an admin or superadmin key, on a domain it or one of its users added.",
                "operationId": "createCatchAll",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "domain_id",
                                    "goto_array"
                                ],
                                "properties": {
                                    "domain_id": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "goto_array": {
                                        "description": "Mailboxes that receive the mail: each must be a mailbox the key can see (any mailbox for a superadmin key)",
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "example": "john@example.com"
                                        }
                                    },
                                    "active": {
                                        "description": "Defaults to true",
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "private_comment": {
                                        "description": "Up to 255 characters",
                                        "type": "string",
                                        "example": "Catch-all for example.com",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created here and on the mail server",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all created successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatchAll"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Saved here, but the mail server did not create it: sync_status in data reads error. Update it to retry, or delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all created in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatchAll"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A domain the key cannot add a catch-all to, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to create catch-all for this domain"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "domain": {
                                        "summary": "A domain the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to create catch-all for this domain"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation, the domain has no mailbox yet, a destination is not a mailbox the key can see, or the domain has a catch-all already",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        },
                                        "invalid_destinations": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            }
                                        },
                                        "domain": {
                                            "type": "string"
                                        },
                                        "address": {
                                            "type": "string"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "A field failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "goto_array": [
                                                    "The goto array field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "no_mailbox": {
                                        "summary": "The domain has no mailbox yet",
                                        "value": {
                                            "message": "example.com has no email accounts yet. Catch-alls are free, so we offer them on domains that already have a mailbox. Create a mailbox on example.com, then add the catch-all.",
                                            "errors": {
                                                "domain_id": [
                                                    "example.com has no email accounts yet. Catch-alls are free, so we offer them on domains that already have a mailbox. Create a mailbox on example.com, then add the catch-all."
                                                ]
                                            }
                                        }
                                    },
                                    "invalid_destinations": {
                                        "summary": "A destination is not a mailbox the key can see",
                                        "value": {
                                            "message": "Some destinations are not valid mailboxes you have access to",
                                            "invalid_destinations": [
                                                "someone@elsewhere.test"
                                            ]
                                        }
                                    },
                                    "exists": {
                                        "summary": "The domain has a catch-all already",
                                        "value": {
                                            "message": "Catch-all for this domain already exists",
                                            "domain": "example.com",
                                            "address": "@example.com"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/catch-all/{id}": {
            "get": {
                "tags": [
                    "Catch-All"
                ],
                "summary": "Get a specific catch-all",
                "description": "One catch-all the key can see (the rule GET /api/v1/catch-all lists by). Any role's key.",
                "operationId": "getCatchAll",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Catch-all ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The catch-all, under data",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/CatchAll"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "The catch-all exists but the key cannot see it, or the key's account is suspended",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have access to this catch-all"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "catch_all": {
                                        "summary": "A catch-all the key cannot see",
                                        "value": {
                                            "message": "You do not have access to this catch-all"
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No catch-all with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Catch-All"
                ],
                "summary": "Update a catch-all",
                "description": "Changes only the fields sent; PATCH does the same. Every call writes the catch-all to the mail server again, an empty body included. Needs an admin or superadmin key.",
                "operationId": "updateCatchAll",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Catch-all ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "goto_array": {
                                        "description": "Mailboxes that receive the mail: each must be a mailbox the key can see (any mailbox for a superadmin key)",
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "example": "john@example.com"
                                        }
                                    },
                                    "active": {
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "private_comment": {
                                        "description": "Up to 255 characters; null clears it",
                                        "type": "string",
                                        "example": "Catch-all for example.com",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated here and on the mail server",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all updated successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatchAll"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Saved here, but the mail server did not take the change: sync_status in data reads error. Repeat the call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all updated in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatchAll"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A catch-all the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to update this catch-all"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "catch_all": {
                                        "summary": "A catch-all the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to update this catch-all"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No catch-all with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation, or a destination is not a mailbox the key can see; checked after the 403 and 404",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        },
                                        "invalid_destinations": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            }
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "A field failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "goto_array": [
                                                    "The goto array field must have at least 1 items."
                                                ]
                                            }
                                        }
                                    },
                                    "invalid_destinations": {
                                        "summary": "A destination is not a mailbox the key can see",
                                        "value": {
                                            "message": "Some destinations are not valid mailboxes you have access to",
                                            "invalid_destinations": [
                                                "someone@elsewhere.test"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Catch-All"
                ],
                "summary": "Delete a catch-all configuration",
                "description": "Deletes the catch-all on the mail server and then here; there is no undo. Catch-alls only: a forwarder or alias id answers 404. Needs an admin or superadmin key.",
                "operationId": "deleteCatchAll",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Catch-all deleted successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A catch-all the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to delete this catch-all"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "catch_all": {
                                        "summary": "A catch-all the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to delete this catch-all"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No catch-all with this id: none exists, or the id is a forwarder or an alias",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Catch-all not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server refused the delete; the catch-all is kept and flagged, repeat the call",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to delete catch-all from Mailcow. Please try again later."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains/{id}/dns-check": {
            "post": {
                "tags": [
                    "DNS checks"
                ],
                "summary": "Check a domain's mail DNS records",
                "description": "Reads the domain's live DNS and compares MX, SPF, DKIM, DMARC and (when enabled) the Amazon SES records with the values the platform expects. Counts against the account's DNS check allowance unless the result is served from the 60 second cache. Available to every role for the domains the key can list.",
                "operationId": "checkDomainDns",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "fresh": {
                                        "description": "Bypass the 60 second cache and query DNS again. Counts against the allowance.",
                                        "type": "boolean",
                                        "example": false
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The check report",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DnsCheckReport"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    },
                    "404": {
                        "description": "Domain not found or not accessible with this key",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "error",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "error": {
                                            "type": "string",
                                            "example": "domain_not_found"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Domain not found or not accessible with this key."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "The account's DNS check allowance is used up (Retry-After and X-DnsCheck-* headers say when it frees up)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DnsCheckQuotaExceeded"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/dns-check": {
            "post": {
                "tags": [
                    "DNS checks"
                ],
                "summary": "Check a domain's mail DNS records by name",
                "description": "Like /domains/{id}/dns-check, addressed by domain name. In mode auto (the default) a domain the key can list is checked against its exact expected values; any other domain gets a generic check (MX, one valid SPF that authorises the mail host, DKIM presence for the selector, DMARC). The generic result never reveals whether a domain is hosted on the platform. Counts against the allowance unless served from the cache.",
                "operationId": "checkDns",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "domain"
                                ],
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "example": "customer.com"
                                    },
                                    "mode": {
                                        "description": "account: 404 unless the domain is in the account. generic: never consults the account.",
                                        "type": "string",
                                        "enum": [
                                            "auto",
                                            "account",
                                            "generic"
                                        ],
                                        "example": "auto"
                                    },
                                    "selector": {
                                        "description": "DKIM selector to look up in generic mode",
                                        "type": "string",
                                        "example": "dkim"
                                    },
                                    "fresh": {
                                        "type": "boolean",
                                        "example": false
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The check report",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DnsCheckReport"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    },
                    "404": {
                        "description": "mode is account and the domain is not in the account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "error",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "error": {
                                            "type": "string",
                                            "example": "domain_not_found"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Domain not found or not accessible with this key."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The domain or selector is not valid",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "error",
                                        "message",
                                        "errors"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "error": {
                                            "type": "string",
                                            "example": "validation_failed"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "The given data was invalid."
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object",
                                            "example": {
                                                "domain": [
                                                    "The domain field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "The account's DNS check allowance is used up",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DnsCheckQuotaExceeded"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/dns-check/quota": {
            "get": {
                "tags": [
                    "DNS checks"
                ],
                "summary": "Current DNS check allowance and usage",
                "description": "The allowance grows with the number of domains in the account: 2 per domain per rolling 24 hours (minimum 10) and 8 per domain per rolling 7 days (minimum 40). Checks of domains outside the account share it and are capped at the minimums on their own. This call is free.",
                "operationId": "getDnsCheckQuota",
                "responses": {
                    "200": {
                        "description": "Allowance and usage",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DnsCheckQuota"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Get list of email domains",
                "description": "The domains the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns. Any role's key.",
                "operationId": "getDomainsList",
                "parameters": [
                    {
                        "name": "ids[]",
                        "in": "query",
                        "description": "Return only the domains with these ids (still scoped by the caller's own visibility, same as every other filter here). Lets a caller that already knows N specific ids fetch all of them in one call instead of N.",
                        "required": false,
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "integer"
                            }
                        }
                    },
                    {
                        "name": "with_counts",
                        "in": "query",
                        "description": "Add aliases_count to each row. mailboxes_count is always present on this endpoint.",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "active",
                        "in": "query",
                        "description": "Only active (true) or inactive (false) domains",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "domain_name",
                        "in": "query",
                        "description": "Only the domain with exactly this name; add domain_name_like=1 to match any domain whose name contains it",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "domain_name_like",
                        "in": "query",
                        "description": "Turns domain_name into a contains match",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "created_by",
                        "in": "query",
                        "description": "Only domains this account added",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "created_at_from",
                        "in": "query",
                        "description": "Only domains created on or after this date (YYYY-MM-DD)",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "created_at_to",
                        "in": "query",
                        "description": "Only domains created on or before this date",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "updated_at_from",
                        "in": "query",
                        "description": "Only domains changed on or after this date",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "updated_at_to",
                        "in": "query",
                        "description": "Only domains changed on or before this date",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Part of the domain name or description",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "Any other value sorts by created_at",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "created_at",
                            "enum": [
                                "domain_name",
                                "active",
                                "created_at",
                                "updated_at"
                            ]
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "Applied only with a sort_by from the list",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "desc",
                            "enum": [
                                "asc",
                                "desc"
                            ]
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Number of items per page: 15 by default, at most 200. A larger value returns 200; 0, a negative or a non-numeric value returns 15. Every v1 list reads per_page the same way. With ids[], up to the number of ids sent, so one page can hold them all.",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "maximum": 200,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One page of domains",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data",
                                        "meta",
                                        "links",
                                        "timestamp"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Domain"
                                            }
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PageMeta"
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PageLinks"
                                        },
                                        "timestamp": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00+00:00"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Domains"
                ],
                "summary": "Store new domain",
                "description": "Adds a domain. It is created on the mail server at once, switched on or off as active says, with its DKIM signing key, and an automated security check starts: provisioning_state reads screening, and mailboxes cannot be created on it (409) until the check clears. When it clears, the domain's sending identity (Amazon SES, with its own DKIM records) and automatic DNS (for a domain in a DNS account connected to the panel) are set up, whether the domain is switched on or not. A domain the check holds is switched off and waits for a person to review it (provisioning_state review). Domains are free and need no subscription. Needs an admin or superadmin key.",
                "operationId": "storeDomain",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "domain_name"
                                ],
                                "properties": {
                                    "domain_name": {
                                        "description": "The domain, not yet on this platform",
                                        "type": "string",
                                        "example": "example.com"
                                    },
                                    "description": {
                                        "description": "Domain description, kept in the panel; up to 255 characters",
                                        "type": "string",
                                        "example": "My company domain",
                                        "nullable": true
                                    },
                                    "active": {
                                        "description": "Default true. false creates the domain switched off on the mail server; its DKIM key, security check, sending identity and DNS are set up all the same.",
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "owner_id": {
                                        "description": "The account to file the domain under: yours (the default) or a customer account you manage. Sending null leaves the domain without an owner.",
                                        "type": "integer",
                                        "example": 12,
                                        "nullable": true
                                    },
                                    "max_mailboxes": {
                                        "description": "A cap on its mailboxes; omitted or null, none",
                                        "type": "integer",
                                        "minimum": 1,
                                        "example": 50,
                                        "nullable": true
                                    },
                                    "storage_quota_mb": {
                                        "description": "A cap on the storage its mailboxes are given, in MB; omitted or null, none",
                                        "type": "integer",
                                        "minimum": 1,
                                        "example": 51200,
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Domain created on the mail server; the security check is running",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain created. An automated security check is running — mailboxes can be created on it once the check clears."
                                        },
                                        "status": {
                                            "type": "string",
                                            "example": "screening"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Domain"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Created here, but the mail server refused it; the panel retries creating it there",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain created in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Domain"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "The account must verify its identity before adding anything, the key is on a user-role account, or its account is suspended",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Identity verification required before creating new services."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "identity": {
                                        "summary": "The account must verify its identity first",
                                        "value": {
                                            "message": "Identity verification required before creating new services."
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error: a missing, malformed or taken domain_name, a domain of a major email provider or one that impersonates a brand, or an owner_id you do not manage",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "errors"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "taken": {
                                        "summary": "The domain is on the platform already",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "domain_name": [
                                                    "The domain name has already been taken."
                                                ]
                                            }
                                        }
                                    },
                                    "owner": {
                                        "summary": "owner_id is an account the key does not manage",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "owner_id": [
                                                    "You can only add a domain to your own account or to an account you manage."
                                                ]
                                            }
                                        }
                                    },
                                    "impersonation": {
                                        "summary": "The name looks like a well-known brand",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "domain_name": [
                                                    "This domain appears to impersonate a well-known brand or service and cannot be added. Contact support if you believe this is a mistake."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure; debug carries the reason when debug mode is on and is null in production",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Internal Server Error"
                                        },
                                        "debug": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains/{id}": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Get domain by ID",
                "description": "One domain the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns. Any role's key.",
                "operationId": "getDomainById",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The domain, under data",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Domain"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "The domain exists but the key does not reach it, or the key's account is suspended",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to view this domain"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "domain": {
                                        "summary": "A domain the key does not reach",
                                        "value": {
                                            "message": "You do not have permission to view this domain"
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No domain with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Domains"
                ],
                "summary": "Update domain",
                "description": "Changes only the fields sent; PATCH takes the same body. active switches the domain on or off on the mail server, and is sent there before anything is saved: switched off, mail is no longer delivered to it. Nothing is deleted: its mailboxes, forwarders and catch-all keep their own settings, its sending identity and DNS records stay, and its mailboxes are still billed. Switching an inactive domain back on is refused with 422 while it is in its security check, held for review, rejected, or suspended for its sending reputation. description, owner_id, max_mailboxes and storage_quota_mb are kept in the panel; they change nothing on the mail server. Changing this domain changes no other domain. Needs an admin or superadmin key, on a domain it reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added.",
                "operationId": "updateDomain",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "description": {
                                        "type": "string",
                                        "example": "Updated description"
                                    },
                                    "active": {
                                        "description": "Only the fields sent are changed. Switching a held or reputation-suspended domain on is refused with 422; the change reaches the mail server first and is not saved if it refuses (502).",
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "owner_id": {
                                        "description": "The account the domain is filed under; must be one you manage",
                                        "type": "integer",
                                        "example": 12,
                                        "nullable": true
                                    },
                                    "max_mailboxes": {
                                        "type": "integer",
                                        "example": 50,
                                        "nullable": true
                                    },
                                    "storage_quota_mb": {
                                        "type": "integer",
                                        "example": 51200,
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Domain updated successfully; the updated domain is under data",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain updated successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Domain"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A domain the key does not reach, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to update this domain"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "domain": {
                                        "summary": "A domain the key does not reach",
                                        "value": {
                                            "message": "You do not have permission to update this domain"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No domain with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation, a plan limit is set below what the domain already uses, or active=true on a domain that is held for review or suspended for its sending reputation",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "errors"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "A field failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "max_mailboxes": [
                                                    "The max mailboxes field must be at least 1."
                                                ]
                                            }
                                        }
                                    },
                                    "mailbox_limit": {
                                        "summary": "The new limit is below the mailboxes the domain has",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "max_mailboxes": [
                                                    "This domain already has 12 mailboxes, so the limit cannot be set below 12."
                                                ]
                                            }
                                        }
                                    },
                                    "storage_limit": {
                                        "summary": "The new storage limit is below what is allocated",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "storage_quota_mb": [
                                                    "This domain has already allocated 30720 MB across its mailboxes, so the quota cannot be set below 30720 MB."
                                                ]
                                            }
                                        }
                                    },
                                    "reputation": {
                                        "summary": "Switching on a domain suspended for its sending reputation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "active": [
                                                    "This domain was suspended because too much of its recent mail bounced or was reported as spam. Contact support to have it reviewed."
                                                ]
                                            }
                                        }
                                    },
                                    "screening": {
                                        "summary": "Switching on a domain in its security check",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "active": [
                                                    "This domain is going through a quick security check, which usually takes a few seconds."
                                                ]
                                            }
                                        }
                                    },
                                    "review": {
                                        "summary": "Switching on a domain awaiting review",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "active": [
                                                    "This domain is awaiting a security review and will be activated once approved."
                                                ]
                                            }
                                        }
                                    },
                                    "rejected": {
                                        "summary": "Switching on a rejected domain",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "active": [
                                                    "This domain was not approved for use on this platform, so it cannot be activated. Contact support if you believe this is a mistake."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "The mail server refused the active change; none of the fields sent were saved",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "The domain could not be reactivated on the mail server, so nothing was changed."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "reactivate": {
                                        "summary": "Switching the domain on",
                                        "value": {
                                            "message": "The domain could not be reactivated on the mail server, so nothing was changed."
                                        }
                                    },
                                    "suspend": {
                                        "summary": "Switching the domain off",
                                        "value": {
                                            "message": "The domain could not be suspended on the mail server, so mail is still being delivered and nothing was changed."
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Domains"
                ],
                "summary": "Delete domain",
                "description": "Deletes the domain and, first, every mailbox, alias, forwarder and catch-all on it, on the mail server and then here. This cannot be undone: the mail stored in those mailboxes is deleted with them, and subscription quantities are reconciled for the mailboxes removed, from the next invoice. Only this domain and what is on it are touched: another domain of the same account keeps its mailboxes, aliases and sending setup. The domain's sending identity is removed afterwards, on a queue; DNS records published at your DNS provider are not removed. Needs an admin or superadmin key; an admin reaches the domains it created or owns and those of the accounts it created.",
                "operationId": "deleteDomain",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Domain deleted successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Some mailboxes or aliases could not be removed from the mail server, so the domain was kept. Repeat the call once the mail server is reachable; what was removed stays removed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain deletion partially completed: some mailboxes/aliases could not be removed from Mailcow. The domain was not deleted."
                                        },
                                        "mailboxes_deleted": {
                                            "type": "integer",
                                            "example": 3
                                        },
                                        "aliases_deleted": {
                                            "type": "integer",
                                            "example": 1
                                        },
                                        "mailbox_errors": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "example": [
                                                "old@example.com: Mailcow unreachable"
                                            ]
                                        },
                                        "alias_errors": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "example": []
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A domain the key does not reach, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to delete this domain"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "domain": {
                                        "summary": "A domain the key does not reach",
                                        "value": {
                                            "message": "You do not have permission to delete this domain"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Domain not found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Domain not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server refused the domain itself; it is kept, repeat the call",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to delete domain from Mailcow. Please try again later."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains/{id}/ses-dns-records": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Get SES DNS records for domain verification",
                "description": "The DNS records that verify the domain for outgoing mail, plus the domain's DKIM record (mailcow_dkim), so a caller can publish the complete set in one pass. Answers 200 once outgoing mail is set up and 202 while it is still being set up or has failed. Needs an admin or superadmin key, on a domain it reaches.",
                "operationId": "getSesDnsRecords",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Set up: the records to publish",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "ses_enabled",
                                        "verification_status",
                                        "dkim_status",
                                        "dns_records",
                                        "mailcow_dkim",
                                        "processing_status",
                                        "last_updated"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "verification_status": {
                                            "description": "Whether Amazon SES has verified the domain: pending, success, failed or temporary_failure",
                                            "type": "string",
                                            "example": "success",
                                            "nullable": true
                                        },
                                        "dkim_status": {
                                            "description": "Amazon SES DKIM state for the domain, not the mailcow_dkim record below",
                                            "type": "string",
                                            "example": "success",
                                            "nullable": true
                                        },
                                        "dns_records": {
                                            "description": "The SES records as one JSON-encoded string: decode it once. /api/v2/domains/{id}/ses-dns-records sends the list itself.",
                                            "type": "string",
                                            "example": "[{\"type\":\"TXT\",\"name\":\"_amazonses.example.com\",\"value\":\"pmBGN\\/7MjnfhTKUZ06Enqq1PeGUaOkw8lGhcfwefcHU=\",\"ttl\":1800}]"
                                        },
                                        "mailcow_dkim": {
                                            "$ref": "#/components/schemas/MailcowDkimRecord"
                                        },
                                        "processing_status": {
                                            "type": "string",
                                            "example": "completed"
                                        },
                                        "last_updated": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00.000000Z",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Still being set up, or the setup failed (error_message says why); ask again later",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "ses_enabled",
                                        "processing_status",
                                        "error_message",
                                        "last_attempt",
                                        "retry_count",
                                        "dns_records",
                                        "mailcow_dkim"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "processing_status": {
                                            "description": "pending, processing, failed or suspended_reputation; completed when the records are not stored yet",
                                            "type": "string",
                                            "example": "processing"
                                        },
                                        "error_message": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "last_attempt": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00.000000Z",
                                            "nullable": true
                                        },
                                        "retry_count": {
                                            "type": "integer",
                                            "example": 0
                                        },
                                        "dns_records": {
                                            "description": "The records so far: a JSON-encoded string like the 200 sends, or an empty array [] when there are none yet"
                                        },
                                        "mailcow_dkim": {
                                            "$ref": "#/components/schemas/MailcowDkimRecord"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Outgoing mail is not enabled for this domain",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "domain",
                                        "ses_enabled"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "SES is not enabled for this domain"
                                        },
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": false
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No domain with this id that the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v2/domains/{id}/ses-dns-records": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Get SES DNS records for domain verification (v2: dns_records as an array)",
                "description": "Identical to GET /api/v1/domains/{id}/ses-dns-records except that dns_records is a JSON array of records instead of a JSON-encoded string. Answers 200 once outgoing mail is set up and 202 while it is still being set up or has failed. Needs an admin or superadmin key, on a domain it reaches.",
                "operationId": "getSesDnsRecordsV2",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Set up: the records to publish",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "ses_enabled",
                                        "verification_status",
                                        "dkim_status",
                                        "dns_records",
                                        "mailcow_dkim",
                                        "processing_status",
                                        "last_updated"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "verification_status": {
                                            "description": "Whether Amazon SES has verified the domain: pending, success, failed or temporary_failure",
                                            "type": "string",
                                            "example": "success",
                                            "nullable": true
                                        },
                                        "dkim_status": {
                                            "description": "Amazon SES DKIM state for the domain, not the mailcow_dkim record below",
                                            "type": "string",
                                            "example": "success",
                                            "nullable": true
                                        },
                                        "dns_records": {
                                            "description": "The SES records",
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/SesDnsRecord"
                                            }
                                        },
                                        "mailcow_dkim": {
                                            "$ref": "#/components/schemas/MailcowDkimRecord"
                                        },
                                        "processing_status": {
                                            "type": "string",
                                            "example": "completed"
                                        },
                                        "last_updated": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00.000000Z",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Still being set up, or the setup failed (error_message says why); ask again later",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "ses_enabled",
                                        "processing_status",
                                        "error_message",
                                        "last_attempt",
                                        "retry_count",
                                        "dns_records",
                                        "mailcow_dkim"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "processing_status": {
                                            "description": "pending, processing, failed or suspended_reputation; completed when the records are not stored yet",
                                            "type": "string",
                                            "example": "processing"
                                        },
                                        "error_message": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "last_attempt": {
                                            "type": "string",
                                            "format": "date-time",
                                            "example": "2026-10-20T09:00:00.000000Z",
                                            "nullable": true
                                        },
                                        "retry_count": {
                                            "type": "integer",
                                            "example": 0
                                        },
                                        "dns_records": {
                                            "description": "The records so far; empty until they exist",
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/SesDnsRecord"
                                            }
                                        },
                                        "mailcow_dkim": {
                                            "$ref": "#/components/schemas/MailcowDkimRecord"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Outgoing mail is not enabled for this domain",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "domain",
                                        "ses_enabled"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "SES is not enabled for this domain"
                                        },
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": false
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No domain with this id that the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains/{id}/ses-verification-status": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Ask Amazon SES whether the domain is verified",
                "description": "Asks Amazon SES, on every call, whether it has verified the domain for outgoing mail, and returns the records that verify it. Needs an admin or superadmin key, on a domain it reaches.",
                "operationId": "getSesVerificationStatus",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Amazon's answer. When Amazon cannot be asked, this is still a 200, with verification_status null.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "ses_enabled",
                                        "verification_status",
                                        "dns_records"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "verification_status": {
                                            "description": "Amazon's own spelling, not the lower-case values the other domain endpoints send; null when Amazon does not know the domain or could not be asked",
                                            "type": "string",
                                            "enum": [
                                                "Pending",
                                                "Success",
                                                "Failed",
                                                "TemporaryFailure",
                                                "NotStarted"
                                            ],
                                            "example": "Success",
                                            "nullable": true
                                        },
                                        "dns_records": {
                                            "description": "The SES records as one JSON-encoded string, null when there are none. /api/v2/domains/{id}/ses-verification-status sends the list itself.",
                                            "type": "string",
                                            "example": "[{\"type\":\"TXT\",\"name\":\"_amazonses.example.com\",\"value\":\"pmBGN\\/7MjnfhTKUZ06Enqq1PeGUaOkw8lGhcfwefcHU=\",\"ttl\":1800}]",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Outgoing mail is not enabled for this domain",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "SES not enabled for this domain"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No domain with this id that the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Failed to get SES verification status"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v2/domains/{id}/ses-verification-status": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Ask Amazon SES whether the domain is verified (v2: dns_records as an array)",
                "description": "Identical to GET /api/v1/domains/{id}/ses-verification-status except that dns_records is a JSON array of records instead of a JSON-encoded string. Needs an admin or superadmin key, on a domain it reaches.",
                "operationId": "getSesVerificationStatusV2",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Amazon's answer. When Amazon cannot be asked, this is still a 200, with verification_status null.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "ses_enabled",
                                        "verification_status",
                                        "dns_records"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "verification_status": {
                                            "description": "Amazon's own spelling, not the lower-case values the other domain endpoints send; null when Amazon does not know the domain or could not be asked",
                                            "type": "string",
                                            "enum": [
                                                "Pending",
                                                "Success",
                                                "Failed",
                                                "TemporaryFailure",
                                                "NotStarted"
                                            ],
                                            "example": "Success",
                                            "nullable": true
                                        },
                                        "dns_records": {
                                            "description": "The SES records, null when there are none",
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/SesDnsRecord"
                                            },
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Outgoing mail is not enabled for this domain",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "SES not enabled for this domain"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No domain with this id that the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Failed to get SES verification status"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains/{id}/dns-propagation-status": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Check whether the domain's DNS records are live",
                "description": "Looks up the domain's MX, SPF and DKIM records on every call, and its two SES record sets when outgoing mail is set up, and reports each one against what it should be. The MX and SPF checks expect this platform's own mail host, so a white-label domain set up as GET /api/v1/domains/{id}/mail-settings says can report a mismatch here; POST /api/v1/domains/{id}/dns-check checks against the right host. Needs an admin or superadmin key, on a domain it reaches.",
                "operationId": "getDnsPropagationStatus",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One result per record",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "propagation_status",
                                        "ses_enabled",
                                        "ses_verification_status"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "propagation_status": {
                                            "properties": {
                                                "percentage": {
                                                    "description": "Share of the checks that passed, rounded to a whole number",
                                                    "type": "number",
                                                    "example": 67
                                                },
                                                "details": {
                                                    "properties": {
                                                        "mx": {
                                                            "$ref": "#/components/schemas/DnsPropagationCheck"
                                                        },
                                                        "spf": {
                                                            "$ref": "#/components/schemas/DnsPropagationCheck"
                                                        },
                                                        "dkim": {
                                                            "$ref": "#/components/schemas/DnsPropagationCheck"
                                                        },
                                                        "ses_verification": {
                                                            "$ref": "#/components/schemas/DnsPropagationCheck"
                                                        },
                                                        "ses_dkim": {
                                                            "$ref": "#/components/schemas/DnsPropagationCheck"
                                                        }
                                                    },
                                                    "type": "object"
                                                },
                                                "total_checks": {
                                                    "description": "3, or 5 with the two SES checks",
                                                    "type": "integer",
                                                    "example": 3
                                                },
                                                "passed_checks": {
                                                    "type": "integer",
                                                    "example": 2
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "ses_enabled": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "ses_verification_status": {
                                            "description": "pending, success, failed or temporary_failure",
                                            "type": "string",
                                            "example": "success",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No domain with this id that the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Failed to get DNS propagation status"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/domains/{id}/mail-settings": {
            "get": {
                "tags": [
                    "Domains"
                ],
                "summary": "Get mail server settings for a domain",
                "description": "Returns the MX record, SPF record, and IMAP/SMTP client settings a customer needs to configure their domain and mail clients. Reflects the owning reseller's white-label mail server hostname when one is configured. Needs an admin or superadmin key, on a domain it reaches.",
                "operationId": "getMailSettings",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Domain ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The settings",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "domain",
                                        "mx",
                                        "spf",
                                        "imap",
                                        "smtp",
                                        "username_pattern"
                                    ],
                                    "properties": {
                                        "domain": {
                                            "type": "string",
                                            "example": "example.com"
                                        },
                                        "mx": {
                                            "properties": {
                                                "hostname": {
                                                    "type": "string",
                                                    "example": "mail.provider.example"
                                                },
                                                "priority": {
                                                    "type": "integer",
                                                    "example": 10
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "spf": {
                                            "type": "string",
                                            "example": "v=spf1 mx a:mail.provider.example ~all"
                                        },
                                        "imap": {
                                            "properties": {
                                                "server": {
                                                    "type": "string",
                                                    "example": "mail.provider.example"
                                                },
                                                "port": {
                                                    "type": "integer",
                                                    "example": 993
                                                },
                                                "security": {
                                                    "type": "string",
                                                    "example": "SSL/TLS"
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "smtp": {
                                            "properties": {
                                                "server": {
                                                    "type": "string",
                                                    "example": "mail.provider.example"
                                                },
                                                "port": {
                                                    "type": "integer",
                                                    "example": 587
                                                },
                                                "security": {
                                                    "type": "string",
                                                    "example": "STARTTLS"
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "username_pattern": {
                                            "type": "string",
                                            "example": "Full email address"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No domain with this id that the key reaches: a superadmin reaches every domain, an admin the domains it added, owns or one of its users added, any other key the domains it added or owns",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/forwarders": {
            "get": {
                "tags": [
                    "Forwarders"
                ],
                "summary": "Get list of email forwarders",
                "description": "The forwarders the key can see: a superadmin sees all of them, an admin the ones it created and the ones its users created, any other key the ones it created. Any role's key.",
                "operationId": "getForwardersList",
                "parameters": [
                    {
                        "name": "domain_id",
                        "in": "query",
                        "description": "Only this domain's forwarders",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "active",
                        "in": "query",
                        "description": "Only active (true) or inactive (false) forwarders",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Part of the address or of a destination",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "Any other value sorts by created_at",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "created_at",
                            "enum": [
                                "address",
                                "created_at",
                                "active"
                            ]
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "Anything but asc sorts descending",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "desc",
                            "enum": [
                                "asc",
                                "desc"
                            ]
                        }
                    },
                    {
                        "name": "with_domain",
                        "in": "query",
                        "description": "Add the domain name to each forwarder as domain",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Number of items per page: 15 by default, at most 200. A larger value returns 200; 0, a negative or a non-numeric value returns 15.",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "maximum": 200,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One page of forwarders",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Forwarder"
                                            }
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PageLinks"
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PageMeta"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Forwarders"
                ],
                "summary": "Create a new email forwarder",
                "description": "Creates local_part@domain, forwarding to every address in goto_array. Forwarders are free, so a domain needs at least one mailbox first (a superadmin key is exempt). Needs an admin or superadmin key, on a domain it or one of its users added.",
                "operationId": "createForwarder",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "local_part",
                                    "domain_id",
                                    "goto_array"
                                ],
                                "properties": {
                                    "local_part": {
                                        "description": "The part before the @: letters, digits and . _ % + -, up to 64 characters",
                                        "type": "string",
                                        "example": "sales"
                                    },
                                    "domain_id": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "goto_array": {
                                        "description": "The destination addresses; at least one",
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "format": "email",
                                            "example": "john@example.com"
                                        }
                                    },
                                    "active": {
                                        "description": "Defaults to true",
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "private_comment": {
                                        "description": "Up to 255 characters",
                                        "type": "string",
                                        "example": "Sales team",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created here and on the mail server. data carries no domain key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder created successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Forwarder"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Saved here, but the mail server did not create it: sync_status in data reads error. Update it to retry, or delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder created in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Forwarder"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A domain the key cannot add forwarders to, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to create forwarders for this domain"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "domain": {
                                        "summary": "A domain the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to create forwarders for this domain"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation, the domain has no mailbox yet, or the address is taken",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        },
                                        "address": {
                                            "description": "The address that is taken",
                                            "type": "string"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "A field failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "goto_array": [
                                                    "The goto array field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "no_mailbox": {
                                        "summary": "The domain has no mailbox yet",
                                        "value": {
                                            "message": "example.com has no email accounts yet. Forwarders are free, so we offer them on domains that already have a mailbox. Create a mailbox on example.com, then add the forwarder.",
                                            "errors": {
                                                "domain_id": [
                                                    "example.com has no email accounts yet. Forwarders are free, so we offer them on domains that already have a mailbox. Create a mailbox on example.com, then add the forwarder."
                                                ]
                                            }
                                        }
                                    },
                                    "forwarder_exists": {
                                        "summary": "A forwarder already has the address",
                                        "value": {
                                            "message": "Forwarder with this address already exists",
                                            "address": "sales@example.com"
                                        }
                                    },
                                    "alias_exists": {
                                        "summary": "An alias made in the control panel has the address",
                                        "value": {
                                            "message": "This address is already taken by a mail alias managed in the control panel. Remove it there, or choose another address.",
                                            "address": "sales@example.com"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/forwarders/{id}": {
            "get": {
                "tags": [
                    "Forwarders"
                ],
                "summary": "Get a specific forwarder",
                "description": "One forwarder the key can see (the rule GET /api/v1/forwarders lists by). Any role's key.",
                "operationId": "getForwarder",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Forwarder ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "with_domain",
                        "in": "query",
                        "description": "Add the domain name as domain",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The forwarder, under data",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Forwarder"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "The forwarder exists but the key cannot see it, or the key's account is suspended",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have access to this forwarder"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "forwarder": {
                                        "summary": "A forwarder the key cannot see",
                                        "value": {
                                            "message": "You do not have access to this forwarder"
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No forwarder with this id: none exists, or the id is an alias or a catch-all",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Forwarders"
                ],
                "summary": "Update a forwarder",
                "description": "Changes only the fields sent; PATCH does the same. Every call writes the forwarder to the mail server again, an empty body included. Needs an admin or superadmin key.",
                "operationId": "updateForwarder",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Forwarder ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "goto_array": {
                                        "description": "The destination addresses; at least one",
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "format": "email",
                                            "example": "john@example.com"
                                        }
                                    },
                                    "active": {
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "private_comment": {
                                        "description": "Up to 255 characters; null clears it",
                                        "type": "string",
                                        "example": "Sales team",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated here and on the mail server",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder updated successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Forwarder"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Saved here, but the mail server did not take the change: sync_status in data reads error. Repeat the call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder updated in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Forwarder"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A forwarder the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to update this forwarder"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "forwarder": {
                                        "summary": "A forwarder the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to update this forwarder"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No forwarder with this id: none exists, or the id is an alias or a catch-all",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation; checked after the 403 and 404",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationFailed"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Forwarders"
                ],
                "summary": "Delete a forwarder",
                "description": "Deletes the forwarder on the mail server and then here; there is no undo. Forwarders only: an alias or catch-all id answers 404. Needs an admin or superadmin key.",
                "operationId": "deleteForwarder",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Forwarder deleted successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A forwarder the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to delete this forwarder"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "forwarder": {
                                        "summary": "A forwarder the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to delete this forwarder"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No forwarder with this id: none exists, or the id is an alias or a catch-all",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Forwarder not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server refused the delete; the forwarder is kept and flagged, repeat the call",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to delete forwarder from Mailcow. Please try again later."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/mailboxes": {
            "get": {
                "tags": [
                    "Mailboxes"
                ],
                "summary": "Get list of email mailboxes",
                "description": "The mailboxes the key can see: a superadmin sees all of them, an admin the ones it created and the ones its users created, any other key the ones it created. Any role's key.",
                "operationId": "getMailboxesList",
                "parameters": [
                    {
                        "name": "domain_id",
                        "in": "query",
                        "description": "Only this domain's mailboxes",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "active",
                        "in": "query",
                        "description": "Only active (true) or inactive (false) mailboxes",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Part of the address or of the name",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "sort_by",
                        "in": "query",
                        "description": "Any other value sorts by created_at",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "created_at",
                            "enum": [
                                "username",
                                "name",
                                "created_at",
                                "active",
                                "quota_used"
                            ]
                        }
                    },
                    {
                        "name": "sort_direction",
                        "in": "query",
                        "description": "Anything but asc sorts descending",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "desc",
                            "enum": [
                                "asc",
                                "desc"
                            ]
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Number of items per page: 15 by default, at most 200. A larger value returns 200; 0, a negative or a non-numeric value returns 15.",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "maximum": 200,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One page of mailboxes",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Mailbox"
                                            }
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PageLinks"
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PageMeta"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Mailboxes"
                ],
                "summary": "Create a new mailbox",
                "description": "Creates a mailbox on a domain owned by your account or by a customer account you created, on the mail server and here. It is billed monthly to the admin account behind the key, from the next invoice, so that account needs an active subscription (402 otherwise). Every mailbox includes 15 GB. Refused with 409 while the domain is in its security check, held for review or rejected (read the domain's provisioning_state), and with 403 while the account's identity verification is outstanding. Needs an admin or superadmin key.",
                "operationId": "createMailbox",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "local_part",
                                    "domain_id",
                                    "name",
                                    "password"
                                ],
                                "properties": {
                                    "local_part": {
                                        "description": "The part before the @: letters, digits and . _ % + -, at most 64",
                                        "type": "string",
                                        "example": "john"
                                    },
                                    "domain_id": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "name": {
                                        "description": "The display name, at most 255",
                                        "type": "string",
                                        "example": "John Doe"
                                    },
                                    "password": {
                                        "description": "At least 8 characters",
                                        "type": "string",
                                        "format": "password",
                                        "example": "a-long-passphrase"
                                    },
                                    "quota": {
                                        "description": "Mailbox size in MB. Every mailbox includes 15 GB, so an omitted, null or smaller value creates a 15360 MB mailbox.",
                                        "type": "integer",
                                        "example": 15360,
                                        "nullable": true
                                    },
                                    "active": {
                                        "description": "Default true; false creates it switched off",
                                        "type": "boolean",
                                        "example": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created here and on the mail server",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox created successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Mailbox"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Saved here, but the mail server did not create it: sync_status in data reads error. Update it to retry, or delete it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox created in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Mailbox"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "402": {
                        "description": "The account has no active subscription, so it cannot create mailboxes. Existing mailboxes are unaffected.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "code"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "This account needs an active subscription before it can create mailboxes. Add one on the Subscription page, then retry."
                                        },
                                        "code": {
                                            "type": "string",
                                            "example": "subscription_required"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "The account must verify its identity first, the domain is not one the key may add mailboxes to, the key is on a user-role account, or its account is suspended. verification_url, when sent, is the panel page where the account owner verifies.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to create mailboxes for this domain"
                                        },
                                        "verification_url": {
                                            "type": "string",
                                            "example": "https://panel.provider.example/admin/identity-verification"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "domain": {
                                        "summary": "A domain the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to create mailboxes for this domain"
                                        }
                                    },
                                    "identity_hold": {
                                        "summary": "The account is held for an identity check",
                                        "value": {
                                            "message": "Identity verification required before creating new mailboxes. The account that owns this API key must complete a one-time identity check, which its owner can do in the panel under Account Settings > Verify Identity.",
                                            "verification_url": "https://panel.provider.example/admin/identity-verification"
                                        }
                                    },
                                    "identity_over_ten": {
                                        "summary": "More than ten mailboxes need a verified identity",
                                        "value": {
                                            "message": "Your account has 10 email accounts. To create more than 10, please verify your identity first. This is a one-time check that takes about 2 minutes.",
                                            "verification_url": "https://panel.provider.example/admin/identity-verification"
                                        }
                                    },
                                    "identity_flagged": {
                                        "summary": "The account is flagged and must verify before creating anything",
                                        "value": {
                                            "message": "Identity verification required before creating new services."
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The domain is not ready for mailboxes yet (its provisioning_state is screening, review or rejected); nothing was created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "We're still running a quick security check on example.com. This usually takes a few seconds — please try again shortly."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "screening": {
                                        "summary": "The domain is still in its automated security check",
                                        "value": {
                                            "message": "We're still running a quick security check on example.com. This usually takes a few seconds — please try again shortly."
                                        }
                                    },
                                    "review": {
                                        "summary": "The domain waits for a person to review it",
                                        "value": {
                                            "message": "example.com is being reviewed by our security team before it can be used. You'll be able to add mailboxes once it's approved."
                                        }
                                    },
                                    "rejected": {
                                        "summary": "The domain was not approved",
                                        "value": {
                                            "message": "example.com was not approved for use on this platform, so mailboxes cannot be created on it. Contact support if you believe this is a mistake."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation, the domain's plan has no room for the mailbox, or the address is taken",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        },
                                        "username": {
                                            "description": "The address that is taken",
                                            "type": "string"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "A field failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "name": [
                                                    "The name field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "mailbox_limit": {
                                        "summary": "The domain's plan has no mailbox left",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "domain_id": [
                                                    "This domain has reached its limit of 10 mailboxes. Upgrade the plan to add more."
                                                ]
                                            }
                                        }
                                    },
                                    "storage_limit": {
                                        "summary": "The domain's plan has too little storage left",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "quota": [
                                                    "This domain has 5120 MB of storage left, so a 15360 MB mailbox cannot be created. Upgrade the plan for more storage."
                                                ]
                                            }
                                        }
                                    },
                                    "exists": {
                                        "summary": "A mailbox has the address already",
                                        "value": {
                                            "message": "Mailbox with this username already exists",
                                            "username": "john@example.com"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/mailboxes/{id}": {
            "get": {
                "tags": [
                    "Mailboxes"
                ],
                "summary": "Get a specific mailbox",
                "description": "One mailbox the key can see (the rule GET /api/v1/mailboxes lists by). Any role's key.",
                "operationId": "getMailbox",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Mailbox ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The mailbox, under data",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Mailbox"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "The mailbox exists but the key cannot see it, or the key's account is suspended",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have access to this mailbox"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "mailbox": {
                                        "summary": "A mailbox the key cannot see",
                                        "value": {
                                            "message": "You do not have access to this mailbox"
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No mailbox with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Mailboxes"
                ],
                "summary": "Update a mailbox",
                "description": "Updates an existing mailbox. Only the fields sent are changed; anything left out keeps its current value. PATCH takes the same body. active false switches the mailbox off on the mail server: it can no longer sign in, and it stays billed. It does not close connections already open or delete its app passwords: send revoke_sessions true as well, or use revoke-access. A mail server refusal answers 207 with the change kept here (data.sync_status error). Needs an admin or superadmin key, on a mailbox it or one of its users created.",
                "operationId": "updateMailbox",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Mailbox ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "name": {
                                        "description": "Up to 255 characters; null is refused",
                                        "type": "string",
                                        "example": "John Doe"
                                    },
                                    "password": {
                                        "description": "At least 8 characters; null or empty leaves the password as it is",
                                        "type": "string",
                                        "format": "password",
                                        "example": "a-new-passphrase",
                                        "nullable": true
                                    },
                                    "quota": {
                                        "description": "Size in MB. Every mailbox includes 15 GB: a value below 15360 is raised to 15360; null leaves the size as it is. It cannot go below what the mailbox holds.",
                                        "type": "integer",
                                        "example": 20480,
                                        "nullable": true
                                    },
                                    "active": {
                                        "description": "false switches the mailbox off on the mail server",
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "revoke_sessions": {
                                        "description": "Also delete the mailbox's app passwords, close its open mail connections and clear the login cache, as POST /api/v1/mailboxes/{id}/revoke-access does",
                                        "type": "boolean",
                                        "example": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Mailbox updated successfully; with revoke_sessions, revocation and limits as in revoke-access",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox updated successfully"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Mailbox"
                                        },
                                        "revocation": {
                                            "$ref": "#/components/schemas/MailboxRevocation"
                                        },
                                        "limits": {
                                            "description": "What revoking cannot do, always the same two sentences",
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "example": "An open webmail browser session is not ended. Its mail connection is dropped and a suspended mailbox cannot reopen one, but the session itself lives in the mail server."
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Saved here, but the mail server did not take the change: sync_status in data reads error. With revoke_sessions, nothing was revoked and revocation_skipped says so.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox updated in database but failed to sync with Mailcow"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Mailbox"
                                        },
                                        "revocation_skipped": {
                                            "type": "string",
                                            "example": "The edit did not reach the mail server, so nothing was revoked: no app passwords were deleted, no sessions were closed and the login cache was not cleared. Retry, or use POST /api/v1/mailboxes/{id}/revoke-access."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A mailbox the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to update this mailbox"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "mailbox": {
                                        "summary": "A mailbox the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to update this mailbox"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No mailbox with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "active:true on a deactivated mailbox whose domain is suspended for its sending reputation, still in its security check, under review or rejected; nothing was changed",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "example.com was suspended because too much of its recent mail bounced or was reported as spam, so its mailboxes stay deactivated until our security team lifts the suspension. Contact support to have it reviewed."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "reputation": {
                                        "summary": "The domain was suspended for its sending reputation",
                                        "value": {
                                            "message": "example.com was suspended because too much of its recent mail bounced or was reported as spam, so its mailboxes stay deactivated until our security team lifts the suspension. Contact support to have it reviewed."
                                        }
                                    },
                                    "screening": {
                                        "summary": "The domain is still in its automated security check",
                                        "value": {
                                            "message": "We're still running a quick security check on example.com. Please try again shortly."
                                        }
                                    },
                                    "review": {
                                        "summary": "The domain waits for a person to review it",
                                        "value": {
                                            "message": "example.com is being reviewed by our security team. You'll be able to reactivate its mailboxes once it's approved."
                                        }
                                    },
                                    "rejected": {
                                        "summary": "The domain was not approved",
                                        "value": {
                                            "message": "example.com was not approved for use on this platform, so its mailboxes cannot be reactivated. Contact support if you believe this is a mistake."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation, or the new size is below what the mailbox holds or above what the domain's plan has left; checked after the 403 and 404",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "errors"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "A field failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "password": [
                                                    "The password field must be at least 8 characters."
                                                ]
                                            }
                                        }
                                    },
                                    "below_usage": {
                                        "summary": "The mailbox holds more than the new size",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "quota": [
                                                    "Cannot reduce quota below current usage of 17.5GB"
                                                ]
                                            }
                                        }
                                    },
                                    "storage_limit": {
                                        "summary": "The domain's plan has too little storage left",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "quota": [
                                                    "This domain allows this mailbox at most 20480 MB. Upgrade the plan for more storage."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "More than ten revoke requests from this account in a minute (revoke-access and update with revoke_sessions count together). The Retry-After header carries the seconds too.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Too many revoke requests. Try again in 42 seconds."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Mailboxes"
                ],
                "summary": "Delete a mailbox",
                "description": "Deletes the mailbox on the mail server and then here. The mail stored in it is deleted with it and cannot be recovered, and the account's subscription quantity is reconciled at once: the next invoice is lower, and the period already paid is not refunded. A mailbox the mail server no longer has counts as deleted (200). Forwarders and aliases that point at it are not removed. Needs an admin or superadmin key; an admin reaches the mailboxes it created and those of the accounts it created.",
                "operationId": "deleteMailbox",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Mailbox deleted successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "A mailbox the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to delete this mailbox"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "mailbox": {
                                        "summary": "A mailbox the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to delete this mailbox"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Mailbox not found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The mail server refused the delete; the mailbox is kept, repeat the call",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to delete mailbox from Mailcow. Please try again later."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/mailboxes/{id}/revoke-access": {
            "post": {
                "tags": [
                    "Mailboxes"
                ],
                "summary": "Revoke a mailbox's access",
                "description": "Locks a compromised mailbox out, in five steps reported one by one under revocation: switch it off (suspend, on unless sent as false), set a new password (only when password is sent), delete its app passwords, close its open connections and clear the login cache; the last two run on a queue. The answer is 200 even when a step failed, so read each step's status: done, skipped, failed, queued or unavailable. limits says what it cannot do. To undo, PUT active true switches the mailbox back on; deleted app passwords are gone and have to be made again. At most 10 a minute. Needs an admin or superadmin key, on a mailbox it or one of its users created.",
                "operationId": "revokeMailboxAccess",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Mailbox ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "suspend": {
                                        "description": "Deactivate the mailbox too; defaults to true",
                                        "type": "boolean",
                                        "example": true
                                    },
                                    "password": {
                                        "description": "A new password, at least 8 characters; omitted or null keeps the current one",
                                        "type": "string",
                                        "format": "password",
                                        "example": "a-new-passphrase",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Each step reported in revocation; a step can fail while the others succeed",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data",
                                        "revocation",
                                        "limits"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox access revoked"
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Mailbox"
                                        },
                                        "revocation": {
                                            "$ref": "#/components/schemas/MailboxRevocation"
                                        },
                                        "limits": {
                                            "description": "What revoking cannot do, always the same two sentences",
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "example": "An open webmail browser session is not ended. Its mail connection is dropped and a suspended mailbox cannot reopen one, but the session itself lives in the mail server."
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "A mailbox the key cannot manage, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to revoke access to this mailbox"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "mailbox": {
                                        "summary": "A mailbox the key cannot manage",
                                        "value": {
                                            "message": "You do not have permission to revoke access to this mailbox"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No mailbox with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Mailbox not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationFailed"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "More than ten revoke requests from this account in a minute (revoke-access and update with revoke_sessions count together). The Retry-After header carries the seconds too.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Too many revoke requests. Try again in 42 seconds."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/mailboxes/{id}/quota": {
            "get": {
                "tags": [
                    "Quotas"
                ],
                "summary": "Get mailbox quota information",
                "description": "The mailbox's storage plan: its base size, the extra blocks bought on top and what they cost. Sizes here are in GB, usage in bytes. Any role's key. Only mailboxes the key created are reachable here, a superadmin key's included, plus for a user-role key the mailboxes on domains it owns; any other id answers 404.",
                "operationId": "getMailboxQuota",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Mailbox ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The plan. price, subscription_id and stripe_subscription_id are sent when has_subscription is true.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "quota",
                                        "usage",
                                        "mailbox",
                                        "has_subscription"
                                    ],
                                    "properties": {
                                        "quota": {
                                            "properties": {
                                                "base_quota": {
                                                    "description": "GB every mailbox includes",
                                                    "type": "integer",
                                                    "example": 15
                                                },
                                                "increment_size": {
                                                    "description": "GB per extra block",
                                                    "type": "integer",
                                                    "example": 5
                                                },
                                                "base_price": {
                                                    "description": "A number, or a string such as \"5.00\" when it comes from a plan",
                                                    "example": "5.00"
                                                },
                                                "increment_price": {
                                                    "description": "A number, or a string such as \"5.00\" when it comes from a plan",
                                                    "example": "2.00"
                                                },
                                                "additional_blocks": {
                                                    "type": "integer",
                                                    "example": 1
                                                },
                                                "total_quota": {
                                                    "description": "GB in all",
                                                    "type": "integer",
                                                    "example": 20
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "usage": {
                                            "description": "Bytes the mailbox holds",
                                            "type": "integer",
                                            "example": 52428800
                                        },
                                        "mailbox": {
                                            "type": "string",
                                            "example": "john@example.com"
                                        },
                                        "price": {
                                            "description": "What the mailbox costs per month with its extra blocks",
                                            "properties": {
                                                "base_price": {
                                                    "example": "5.00"
                                                },
                                                "additional_blocks_price": {
                                                    "type": "number",
                                                    "example": 4
                                                },
                                                "total_price": {
                                                    "type": "number",
                                                    "example": 9
                                                },
                                                "currency": {
                                                    "type": "string",
                                                    "example": "USD"
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "has_subscription": {
                                            "description": "Whether the mailbox has a storage subscription; false means it is on the base size",
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "subscription_id": {
                                            "type": "integer",
                                            "example": 7
                                        },
                                        "stripe_subscription_id": {
                                            "type": "string",
                                            "example": "sub_1Q2w3E4r5T6y",
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/AccountRefused"
                    },
                    "404": {
                        "description": "No mailbox with this id that the key created (or, for a user-role key, on a domain it owns)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/mailboxes/{id}/quota/increase": {
            "post": {
                "tags": [
                    "Quotas"
                ],
                "summary": "Increase mailbox quota",
                "description": "Adds storage blocks on the mailbox and its subscription. Sizes are in GB. Needs an admin or superadmin key. Only mailboxes the key created are reachable here, a superadmin key's included; any other id answers 404.",
                "operationId": "increaseMailboxQuota",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Mailbox ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "blocks"
                                ],
                                "properties": {
                                    "blocks": {
                                        "description": "Blocks to add, each the increment_size GET /api/v1/mailboxes/{id}/quota reports",
                                        "type": "integer",
                                        "maximum": 20,
                                        "minimum": 1,
                                        "example": 1
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The new size and price",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "new_quota",
                                        "additional_blocks",
                                        "price"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Quota increased successfully"
                                        },
                                        "new_quota": {
                                            "description": "GB in all",
                                            "type": "integer",
                                            "example": 20
                                        },
                                        "additional_blocks": {
                                            "type": "integer",
                                            "example": 1
                                        },
                                        "price": {
                                            "description": "What the mailbox costs per month with its extra blocks",
                                            "properties": {
                                                "base_price": {
                                                    "example": "5.00"
                                                },
                                                "additional_blocks_price": {
                                                    "type": "number",
                                                    "example": 4
                                                },
                                                "total_price": {
                                                    "type": "number",
                                                    "example": 9
                                                },
                                                "currency": {
                                                    "type": "string",
                                                    "example": "USD"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No mailbox with this id that the key created (or, for a user-role key, on a domain it owns)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "blocks failed validation (checked before the mailbox is looked up), or the change cannot be made",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "blocks failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "blocks": [
                                                    "The blocks field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "storage_limit": {
                                        "summary": "The domain's plan has too little storage left",
                                        "value": {
                                            "message": "This domain allows this mailbox at most 20480 MB. Upgrade the domain plan for more storage."
                                        }
                                    },
                                    "mail_server": {
                                        "summary": "The mail server refused the new size",
                                        "value": {
                                            "message": "Failed to update mailbox quota in Mailcow"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/mailboxes/{id}/quota/decrease": {
            "post": {
                "tags": [
                    "Quotas"
                ],
                "summary": "Decrease mailbox quota",
                "description": "Removes storage blocks on the mailbox and its subscription. Sizes are in GB. Needs an admin or superadmin key. Only mailboxes the key created are reachable here, a superadmin key's included; any other id answers 404.",
                "operationId": "decreaseMailboxQuota",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "Mailbox ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "blocks"
                                ],
                                "properties": {
                                    "blocks": {
                                        "description": "Blocks to remove, each the increment_size GET /api/v1/mailboxes/{id}/quota reports",
                                        "type": "integer",
                                        "minimum": 1,
                                        "example": 1
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The new size and price",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "new_quota",
                                        "additional_blocks",
                                        "price"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Quota decreased successfully"
                                        },
                                        "new_quota": {
                                            "description": "GB in all",
                                            "type": "integer",
                                            "example": 15
                                        },
                                        "additional_blocks": {
                                            "type": "integer",
                                            "example": 0
                                        },
                                        "price": {
                                            "description": "What the mailbox costs per month with its extra blocks",
                                            "properties": {
                                                "base_price": {
                                                    "example": "5.00"
                                                },
                                                "additional_blocks_price": {
                                                    "type": "number",
                                                    "example": 4
                                                },
                                                "total_price": {
                                                    "type": "number",
                                                    "example": 9
                                                },
                                                "currency": {
                                                    "type": "string",
                                                    "example": "USD"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    },
                    "404": {
                        "description": "No mailbox with this id that the key created (or, for a user-role key, on a domain it owns)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "success",
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Resource not found."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "blocks failed validation (checked before the mailbox is looked up), or the change cannot be made",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Validation failed"
                                        },
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "blocks failed validation",
                                        "value": {
                                            "message": "Validation failed",
                                            "errors": {
                                                "blocks": [
                                                    "The blocks field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "no_subscription": {
                                        "summary": "The mailbox has no extra blocks to remove",
                                        "value": {
                                            "message": "No quota subscription found for this mailbox"
                                        }
                                    },
                                    "below_base": {
                                        "summary": "More blocks than the mailbox has",
                                        "value": {
                                            "message": "Cannot decrease quota below the base level"
                                        }
                                    },
                                    "below_usage": {
                                        "summary": "The mailbox holds more than the smaller size",
                                        "value": {
                                            "message": "Cannot reduce quota below current usage of 17.5GB"
                                        }
                                    },
                                    "mail_server": {
                                        "summary": "The mail server refused the new size",
                                        "value": {
                                            "message": "Failed to update mailbox quota in Mailcow"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/sso/token": {
            "post": {
                "tags": [
                    "Single sign-on"
                ],
                "summary": "Create a one-time sign-in link",
                "description": "A link that signs the browser that opens it in to the control panel as the account named, skipping its password and two-factor step. It works once, within 60 seconds, so create it when the person clicks, not ahead of time. Allowed for the key's own account and the accounts it created or owns (any account for a superadmin key), never for a superadmin account or a suspended one. Needs an admin or superadmin key.",
                "operationId": "createSsoToken",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "user_id": {
                                        "description": "The account to sign in as; send this or user_email. When both are sent, user_id wins.",
                                        "type": "integer",
                                        "example": 57
                                    },
                                    "user_email": {
                                        "description": "The account to sign in as, by email",
                                        "type": "string",
                                        "format": "email",
                                        "example": "jane@customer.test"
                                    },
                                    "redirect": {
                                        "description": "Where the link lands: the control panel (the default) or webmail",
                                        "type": "string",
                                        "enum": [
                                            "panel",
                                            "webmail"
                                        ],
                                        "example": "panel",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The link",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "url": {
                                                    "description": "Open it in the person's browser; a used or expired link answers 403",
                                                    "type": "string",
                                                    "example": "https://panel.provider.example/sso/consume/kq3Yv0bX7mR2pL9sT4wZ8nC1fH6jD5gA"
                                                },
                                                "expires_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "example": "2026-10-20T09:01:00+00:00"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "An account the key may not sign in as, a superadmin or suspended account, a key on a user-role account, or a suspended key account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message"
                                    ],
                                    "properties": {
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "You do not have permission to sign in as this user."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "not_yours": {
                                        "summary": "An account the key did not create and does not own",
                                        "value": {
                                            "message": "You do not have permission to sign in as this user."
                                        }
                                    },
                                    "superadmin": {
                                        "summary": "A superadmin account",
                                        "value": {
                                            "message": "Single sign-on is not available for platform administrator accounts."
                                        }
                                    },
                                    "target_suspended": {
                                        "summary": "The account is suspended",
                                        "value": {
                                            "message": "This account is suspended and cannot be signed in to."
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Neither user_id nor user_email was sent, the account does not exist, or redirect is not panel or webmail",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ValidationFailed"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/users": {
            "get": {
                "tags": [
                    "Users"
                ],
                "summary": "List users",
                "description": "The accounts the key reaches: an admin reaches itself, the accounts it created and the accounts those accounts created; a superadmin reaches every account. No filters or sorting. The body is the paginator itself, not a data envelope. Needs an admin or superadmin key.",
                "operationId": "getUsers",
                "parameters": [
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Number of items per page: 15 by default, at most 200. A larger value returns 200; 0, a negative or a non-numeric value returns 15.",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 15,
                            "maximum": 200,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "One page of accounts",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "current_page",
                                        "data",
                                        "first_page_url",
                                        "from",
                                        "last_page",
                                        "last_page_url",
                                        "links",
                                        "next_page_url",
                                        "path",
                                        "per_page",
                                        "prev_page_url",
                                        "to",
                                        "total"
                                    ],
                                    "properties": {
                                        "current_page": {
                                            "type": "integer",
                                            "example": 1
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/User"
                                            }
                                        },
                                        "first_page_url": {
                                            "type": "string",
                                            "example": "https://panel.provider.example/api/v1/users?page=1"
                                        },
                                        "from": {
                                            "type": "integer",
                                            "example": 1,
                                            "nullable": true
                                        },
                                        "last_page": {
                                            "type": "integer",
                                            "example": 3
                                        },
                                        "last_page_url": {
                                            "type": "string",
                                            "example": "https://panel.provider.example/api/v1/users?page=3"
                                        },
                                        "links": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "url": {
                                                        "type": "string",
                                                        "nullable": true
                                                    },
                                                    "label": {
                                                        "type": "string"
                                                    },
                                                    "page": {
                                                        "type": "integer",
                                                        "nullable": true
                                                    },
                                                    "active": {
                                                        "type": "boolean"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "next_page_url": {
                                            "type": "string",
                                            "example": "https://panel.provider.example/api/v1/users?page=2",
                                            "nullable": true
                                        },
                                        "path": {
                                            "type": "string",
                                            "example": "https://panel.provider.example/api/v1/users"
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "example": 15
                                        },
                                        "prev_page_url": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "to": {
                                            "type": "integer",
                                            "example": 15,
                                            "nullable": true
                                        },
                                        "total": {
                                            "type": "integer",
                                            "example": 42
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/RoleRefused"
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Users"
                ],
                "summary": "Create a user",
                "description": "Creates an account under the key's account, with an API key of its own. Repeating the call with the email of an account the key created or owns answers 200 with that account and no key, so a retry never makes a second account. An admin key may create user and admin accounts; only a superadmin key creates superadmins. Needs an admin or superadmin key.",
                "operationId": "createUser",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "name",
                                    "email",
                                    "password"
                                ],
                                "properties": {
                                    "name": {
                                        "description": "Up to 255 characters",
                                        "type": "string",
                                        "example": "Jane Customer"
                                    },
                                    "email": {
                                        "description": "Must not belong to another account",
                                        "type": "string",
                                        "format": "email",
                                        "example": "jane@customer.test"
                                    },
                                    "password": {
                                        "description": "At least 8 characters",
                                        "type": "string",
                                        "format": "password",
                                        "example": "a-long-passphrase"
                                    },
                                    "role": {
                                        "description": "Defaults to user when left out",
                                        "type": "string",
                                        "enum": [
                                            "user",
                                            "admin",
                                            "superadmin"
                                        ],
                                        "example": "user"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created. data.api_key is the new account's key, shown this once.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "User created successfully"
                                        },
                                        "data": {
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "example": 57
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "example": "Jane Customer"
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "example": "jane@customer.test"
                                                },
                                                "role": {
                                                    "type": "string",
                                                    "enum": [
                                                        "user",
                                                        "admin",
                                                        "superadmin"
                                                    ],
                                                    "example": "user"
                                                },
                                                "owner_id": {
                                                    "description": "The admin that created the account; null when a superadmin created it",
                                                    "type": "integer",
                                                    "example": 12,
                                                    "nullable": true
                                                },
                                                "api_key": {
                                                    "description": "A key for the new account, shown this once and never again",
                                                    "type": "string",
                                                    "example": "0b5f1c1e-7a52-4c39-9a3e-0f1d2c3b4a59"
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "example": "2026-10-20T09:00:00.000000Z"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "An account the key created or owns already has this email: nothing was created or changed, and no key is sent",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "User already exists"
                                        },
                                        "data": {
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "example": 57
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "example": "Jane Customer"
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "example": "jane@customer.test"
                                                },
                                                "role": {
                                                    "type": "string",
                                                    "example": "user"
                                                },
                                                "owner_id": {
                                                    "type": "integer",
                                                    "example": 12,
                                                    "nullable": true
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "example": "2026-10-20T09:00:00.000000Z"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "An admin key asking for a superadmin, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "description": "The operation's own refusals",
                                            "type": "string",
                                            "example": "You do not have permission to create superadmin users"
                                        },
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "description": "Sent with the role refusal and the suspended-account refusal",
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "superadmin": {
                                        "summary": "An admin key asking for a superadmin account",
                                        "value": {
                                            "error": "You do not have permission to create superadmin users"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation. This body has errors alone, no message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "errors"
                                    ],
                                    "properties": {
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object",
                                            "example": {
                                                "email": [
                                                    "The email has already been taken."
                                                ]
                                            },
                                            "additionalProperties": {
                                                "type": "array",
                                                "items": {
                                                    "type": "string"
                                                }
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure; message carries the reason when debug mode is on and is null in production",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error",
                                        "message"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "An error occurred while creating the user"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        },
        "/api/v1/users/{id}": {
            "get": {
                "tags": [
                    "Users"
                ],
                "summary": "Get a user",
                "description": "One account the key reaches: an admin reaches itself, the accounts it created and the accounts those accounts created; a superadmin reaches every account. Needs an admin or superadmin key.",
                "operationId": "getUser",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "User ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The account, under data",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/User"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "An account the key does not reach, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "description": "The operation's own refusals",
                                            "type": "string",
                                            "example": "Forbidden"
                                        },
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "description": "Sent with the role refusal and the suspended-account refusal",
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "user": {
                                        "summary": "An account the key does not reach",
                                        "value": {
                                            "error": "Forbidden"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No account with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "User not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Users"
                ],
                "summary": "Update a user",
                "description": "Changes only the fields sent; PATCH does the same. The account must be one the key reaches: an admin reaches itself, the accounts it created and the accounts those accounts created; a superadmin reaches every account. Only a superadmin key assigns the superadmin role. Needs an admin or superadmin key.",
                "operationId": "updateUser",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "User ID",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "name": {
                                        "description": "Up to 255 characters",
                                        "type": "string",
                                        "example": "Jane Customer"
                                    },
                                    "email": {
                                        "description": "Must not belong to another account",
                                        "type": "string",
                                        "format": "email",
                                        "example": "jane@customer.test"
                                    },
                                    "password": {
                                        "description": "At least 8 characters",
                                        "type": "string",
                                        "format": "password",
                                        "example": "a-new-passphrase"
                                    },
                                    "role": {
                                        "type": "string",
                                        "enum": [
                                            "user",
                                            "admin",
                                            "superadmin"
                                        ],
                                        "example": "admin"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "message",
                                        "data"
                                    ],
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "User updated successfully"
                                        },
                                        "data": {
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "example": 57
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "example": "Jane Customer"
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "example": "jane@customer.test"
                                                },
                                                "role": {
                                                    "type": "string",
                                                    "example": "admin"
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "example": "2026-10-20T09:00:00.000000Z"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "description": "An account the key does not reach, an admin key assigning superadmin, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "description": "The operation's own refusals",
                                            "type": "string",
                                            "example": "Forbidden"
                                        },
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "description": "Sent with the role refusal and the suspended-account refusal",
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "user": {
                                        "summary": "An account the key does not reach",
                                        "value": {
                                            "error": "Forbidden"
                                        }
                                    },
                                    "superadmin": {
                                        "summary": "An admin key assigning the superadmin role",
                                        "value": {
                                            "error": "You cannot assign superadmin role"
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No account with this id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "User not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation. This body has errors alone, no message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "errors"
                                    ],
                                    "properties": {
                                        "errors": {
                                            "description": "Each field that failed, with its messages",
                                            "type": "object",
                                            "example": {
                                                "password": [
                                                    "The password field must be at least 8 characters."
                                                ]
                                            },
                                            "additionalProperties": {
                                                "type": "array",
                                                "items": {
                                                    "type": "string"
                                                }
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "An unexpected failure; message carries the reason when debug mode is on and is null in production",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "error",
                                        "message"
                                    ],
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "An error occurred while updating the user"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Users"
                ],
                "summary": "Delete a user",
                "description": "Deletes a customer account you created (or, one hop down, an account created by one of them). Refused with 409 while it still has mailboxes, domains or aliases, or customer accounts under it, and with 403 for your own account or one held for identity verification. Its own refusals carry an error key rather than message. Needs an admin or superadmin key.",
                "operationId": "deleteUser",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "User deleted successfully",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "User deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No API key, or an unknown one",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "API key is missing"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "missing": {
                                        "summary": "No X-API-KEY header",
                                        "value": {
                                            "message": "API key is missing"
                                        }
                                    },
                                    "invalid": {
                                        "summary": "A key that is unknown, revoked or expired",
                                        "value": {
                                            "message": "Invalid API key"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Your own account, an account the key did not create, one held for identity verification, a key on a user-role account, or a suspended account",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "description": "The operation's own refusals",
                                            "type": "string",
                                            "example": "You can only delete users you created"
                                        },
                                        "success": {
                                            "description": "Sent with the role refusal only",
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "description": "Sent with the role refusal and the suspended-account refusal",
                                            "type": "string",
                                            "example": "User does not have the required permissions."
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "not_created": {
                                        "summary": "An account the key did not create",
                                        "value": {
                                            "error": "You can only delete users you created"
                                        }
                                    },
                                    "self": {
                                        "summary": "The key's own account",
                                        "value": {
                                            "error": "You cannot delete yourself"
                                        }
                                    },
                                    "held": {
                                        "summary": "An account held for identity verification that has customer accounts",
                                        "value": {
                                            "error": "This account is waiting for identity verification and cannot be deleted."
                                        }
                                    },
                                    "role": {
                                        "summary": "A key on a user-role account",
                                        "value": {
                                            "success": false,
                                            "message": "User does not have the required permissions."
                                        }
                                    },
                                    "suspended": {
                                        "summary": "The key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended. Contact support for assistance."
                                        }
                                    },
                                    "manager_suspended": {
                                        "summary": "The account that manages the key's account is suspended",
                                        "value": {
                                            "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "User not found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "User not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The account still has mailboxes, domains or aliases (error: Delete this user's mailboxes, domains and aliases before deleting the user.), or customer accounts created by it or owned by it (error: Delete this user's customer accounts before deleting the user.); delete those first",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Delete this user's mailboxes, domains and aliases before deleting the user."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The delete failed unexpectedly; nothing was removed",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "An error occurred while deleting the user"
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKeyAuth": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "Error": {
                "required": [
                    "message"
                ],
                "properties": {
                    "message": {
                        "type": "string",
                        "example": "Error message"
                    },
                    "errors": {
                        "type": "object",
                        "example": {
                            "field": [
                                "The field is required."
                            ]
                        }
                    }
                },
                "type": "object"
            },
            "ValidationFailed": {
                "required": [
                    "message",
                    "errors"
                ],
                "properties": {
                    "message": {
                        "type": "string",
                        "example": "Validation failed"
                    },
                    "errors": {
                        "description": "Each field that failed, with its messages",
                        "type": "object",
                        "example": {
                            "domain_id": [
                                "The domain id field is required."
                            ]
                        },
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                },
                "type": "object"
            },
            "PageLinks": {
                "description": "The first, last, previous and next pages of a list, as full URLs",
                "required": [
                    "first",
                    "last",
                    "prev",
                    "next"
                ],
                "properties": {
                    "first": {
                        "type": "string",
                        "example": "https://panel.provider.example/api/v1/forwarders?page=1"
                    },
                    "last": {
                        "type": "string",
                        "example": "https://panel.provider.example/api/v1/forwarders?page=3"
                    },
                    "prev": {
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "next": {
                        "type": "string",
                        "example": "https://panel.provider.example/api/v1/forwarders?page=2",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "PageMeta": {
                "description": "Where this page sits in the list. Only page is carried into the link URLs, so repeat any filter when following one.",
                "required": [
                    "current_page",
                    "from",
                    "last_page",
                    "links",
                    "path",
                    "per_page",
                    "to",
                    "total"
                ],
                "properties": {
                    "current_page": {
                        "type": "integer",
                        "example": 1
                    },
                    "from": {
                        "type": "integer",
                        "example": 1,
                        "nullable": true
                    },
                    "last_page": {
                        "type": "integer",
                        "example": 3
                    },
                    "links": {
                        "type": "array",
                        "items": {
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "nullable": true
                                },
                                "label": {
                                    "type": "string"
                                },
                                "page": {
                                    "type": "integer",
                                    "nullable": true
                                },
                                "active": {
                                    "type": "boolean"
                                }
                            },
                            "type": "object"
                        }
                    },
                    "path": {
                        "type": "string",
                        "example": "https://panel.provider.example/api/v1/forwarders"
                    },
                    "per_page": {
                        "type": "integer",
                        "example": 15
                    },
                    "to": {
                        "type": "integer",
                        "example": 15,
                        "nullable": true
                    },
                    "total": {
                        "type": "integer",
                        "example": 42
                    },
                    "pagination": {
                        "description": "Sent by the domain and catch-all lists, when the list has more than one page",
                        "properties": {
                            "total": {
                                "type": "integer",
                                "example": 42
                            },
                            "count": {
                                "type": "integer",
                                "example": 15
                            },
                            "per_page": {
                                "type": "integer",
                                "example": 15
                            },
                            "current_page": {
                                "type": "integer",
                                "example": 1
                            },
                            "total_pages": {
                                "type": "integer",
                                "example": 3
                            },
                            "has_more_pages": {
                                "type": "boolean",
                                "example": true
                            }
                        },
                        "type": "object"
                    }
                },
                "type": "object"
            },
            "RevocationStep": {
                "required": [
                    "status",
                    "detail"
                ],
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "done",
                            "skipped",
                            "failed",
                            "queued",
                            "unavailable"
                        ],
                        "example": "done"
                    },
                    "detail": {
                        "type": "string",
                        "example": "The password was changed."
                    }
                },
                "type": "object"
            },
            "MailboxRevocation": {
                "description": "One entry per step, in the order they run. A failed step leaves the others as reported.",
                "required": [
                    "suspended",
                    "password_changed",
                    "app_passwords_deleted",
                    "sessions_closed",
                    "auth_cache_flushed"
                ],
                "properties": {
                    "suspended": {
                        "$ref": "#/components/schemas/RevocationStep"
                    },
                    "password_changed": {
                        "$ref": "#/components/schemas/RevocationStep"
                    },
                    "app_passwords_deleted": {
                        "required": [
                            "status",
                            "detail",
                            "count"
                        ],
                        "properties": {
                            "status": {
                                "type": "string",
                                "enum": [
                                    "done",
                                    "failed"
                                ],
                                "example": "done"
                            },
                            "detail": {
                                "type": "string",
                                "example": "Deleted 2 app password(s)."
                            },
                            "count": {
                                "type": "integer",
                                "example": 2
                            }
                        },
                        "type": "object"
                    },
                    "sessions_closed": {
                        "$ref": "#/components/schemas/RevocationStep"
                    },
                    "auth_cache_flushed": {
                        "$ref": "#/components/schemas/RevocationStep"
                    }
                },
                "type": "object"
            },
            "User": {
                "description": "An account as GET /api/v1/users and GET /api/v1/users/{id} send it",
                "required": [
                    "id",
                    "name",
                    "email",
                    "role",
                    "created_at",
                    "created_by"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 57
                    },
                    "name": {
                        "type": "string",
                        "example": "Jane Customer"
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "example": "jane@customer.test"
                    },
                    "role": {
                        "type": "string",
                        "enum": [
                            "user",
                            "admin",
                            "superadmin"
                        ],
                        "example": "user"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "created_by": {
                        "description": "The account that created this one",
                        "type": "integer",
                        "example": 12,
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "Domain": {
                "description": "A domain as every domain endpoint sends it (DomainResource). Storage is in MB throughout.",
                "required": [
                    "id",
                    "domain_name",
                    "description",
                    "active",
                    "created_at",
                    "updated_at",
                    "created_by",
                    "owner_id",
                    "provisioning_state",
                    "ses_processing_status",
                    "ses_error_message",
                    "max_mailboxes",
                    "storage_quota_mb",
                    "mailboxes_used",
                    "storage_allocated_mb",
                    "storage_used_mb"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 1
                    },
                    "domain_name": {
                        "type": "string",
                        "example": "example.com"
                    },
                    "description": {
                        "type": "string",
                        "example": "My company domain",
                        "nullable": true
                    },
                    "active": {
                        "description": "Switched on on the mail server",
                        "type": "boolean",
                        "example": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "created_by": {
                        "description": "The account that added the domain",
                        "type": "integer",
                        "example": 12,
                        "nullable": true
                    },
                    "owner_id": {
                        "description": "The account the domain belongs to; a reseller sets it on create to put the domain under a customer",
                        "type": "integer",
                        "example": 34,
                        "nullable": true
                    },
                    "provisioning_state": {
                        "description": "Mailbox creation answers 409 until this reads ready. screening clears within minutes and is worth retrying, review waits for a person, rejected is final.",
                        "type": "string",
                        "enum": [
                            "screening",
                            "review",
                            "ready",
                            "rejected"
                        ],
                        "example": "ready"
                    },
                    "ses_processing_status": {
                        "description": "Where setting up outgoing mail for the domain stands",
                        "type": "string",
                        "enum": [
                            "pending",
                            "processing",
                            "completed",
                            "skipped",
                            "failed"
                        ],
                        "example": "completed",
                        "nullable": true
                    },
                    "ses_error_message": {
                        "description": "Why that setup failed, when it did",
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "max_mailboxes": {
                        "description": "The plan's mailbox limit; null is uncapped",
                        "type": "integer",
                        "example": 10,
                        "nullable": true
                    },
                    "storage_quota_mb": {
                        "description": "The plan's storage limit in MB; null is uncapped",
                        "type": "integer",
                        "example": 30720,
                        "nullable": true
                    },
                    "mailboxes_used": {
                        "description": "Mailboxes on the domain now",
                        "type": "integer",
                        "example": 3
                    },
                    "storage_allocated_mb": {
                        "description": "Storage handed to the domain's mailboxes, in MB",
                        "type": "integer",
                        "example": 6144
                    },
                    "storage_used_mb": {
                        "description": "Storage the domain's mailboxes hold, in MB",
                        "type": "integer",
                        "example": 1270
                    },
                    "mailboxes_count": {
                        "description": "Sent in lists only: GET /api/v1/domains and the domains of GET /api/v1/search",
                        "type": "integer",
                        "example": 3
                    },
                    "aliases_count": {
                        "description": "Sent by GET /api/v1/domains with with_counts=1 only",
                        "type": "integer",
                        "example": 5
                    }
                },
                "type": "object"
            },
            "Mailbox": {
                "description": "A mailbox as every mailbox endpoint sends it (MailboxResource). The password is never sent back.",
                "required": [
                    "id",
                    "username",
                    "name",
                    "domain",
                    "domain_id",
                    "active",
                    "quota",
                    "quota_used",
                    "created_at",
                    "updated_at",
                    "created_by",
                    "mailcow_id",
                    "sync_status",
                    "synced_at"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 1
                    },
                    "username": {
                        "description": "The full address",
                        "type": "string",
                        "format": "email",
                        "example": "john@example.com"
                    },
                    "name": {
                        "type": "string",
                        "example": "John Doe",
                        "nullable": true
                    },
                    "domain": {
                        "description": "The domain name",
                        "type": "string",
                        "example": "example.com"
                    },
                    "domain_id": {
                        "type": "integer",
                        "example": 1,
                        "nullable": true
                    },
                    "active": {
                        "description": "Switched on on the mail server",
                        "type": "boolean",
                        "example": true
                    },
                    "quota": {
                        "description": "Storage limit in MB",
                        "type": "integer",
                        "example": 2048
                    },
                    "quota_used": {
                        "description": "Storage in use, in bytes. Null in the response to the POST that created the mailbox; 0 or more from then on.",
                        "type": "integer",
                        "example": 52428800,
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "created_by": {
                        "type": "integer",
                        "example": 12,
                        "nullable": true
                    },
                    "mailcow_id": {
                        "description": "The mailbox's id on the mail server; null until a sync with the mail server fills it in",
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "sync_status": {
                        "description": "synced when the mail server has the mailbox as stored here; pending, error or failed otherwise",
                        "type": "string",
                        "example": "synced"
                    },
                    "synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "Forwarder": {
                "description": "A forwarder as every forwarder endpoint sends it (ForwarderResource)",
                "required": [
                    "id",
                    "address",
                    "goto",
                    "goto_array",
                    "active",
                    "is_catch_all",
                    "private_comment",
                    "public_comment",
                    "domain_id",
                    "created_at",
                    "updated_at",
                    "created_by",
                    "mailcow_id",
                    "sync_status",
                    "synced_at"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 1
                    },
                    "address": {
                        "type": "string",
                        "format": "email",
                        "example": "sales@example.com"
                    },
                    "goto": {
                        "description": "The destinations, comma-separated",
                        "type": "string",
                        "example": "john@example.com,jane@example.com",
                        "nullable": true
                    },
                    "goto_array": {
                        "description": "The same destinations as a list",
                        "type": "array",
                        "items": {
                            "type": "string",
                            "example": "john@example.com"
                        }
                    },
                    "active": {
                        "type": "boolean",
                        "example": true
                    },
                    "is_catch_all": {
                        "type": "boolean",
                        "example": false
                    },
                    "private_comment": {
                        "type": "string",
                        "example": "Sales department forwarder",
                        "nullable": true
                    },
                    "public_comment": {
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "domain": {
                        "description": "The domain name; sent when the operation loads the domain",
                        "type": "string",
                        "example": "example.com"
                    },
                    "domain_id": {
                        "type": "integer",
                        "example": 1,
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "created_by": {
                        "type": "integer",
                        "example": 12,
                        "nullable": true
                    },
                    "mailcow_id": {
                        "description": "The forwarder's id on the mail server",
                        "type": "string",
                        "example": "17",
                        "nullable": true
                    },
                    "sync_status": {
                        "description": "synced when the mail server has the forwarder as stored here; pending, error or failed otherwise",
                        "type": "string",
                        "example": "synced"
                    },
                    "synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "CatchAll": {
                "description": "A catch-all as every catch-all endpoint sends it (CatchAllResource)",
                "required": [
                    "id",
                    "address",
                    "domain",
                    "domain_id",
                    "goto",
                    "goto_array",
                    "active",
                    "is_catch_all",
                    "private_comment",
                    "created_at",
                    "updated_at",
                    "created_by",
                    "mailcow_id",
                    "sync_status",
                    "synced_at"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 1
                    },
                    "address": {
                        "type": "string",
                        "example": "@example.com"
                    },
                    "domain": {
                        "type": "string",
                        "example": "example.com",
                        "nullable": true
                    },
                    "domain_id": {
                        "type": "integer",
                        "example": 1,
                        "nullable": true
                    },
                    "goto": {
                        "description": "The destinations, comma-separated",
                        "type": "string",
                        "example": "john@example.com,jane@example.com",
                        "nullable": true
                    },
                    "goto_array": {
                        "description": "The same destinations as a list",
                        "type": "array",
                        "items": {
                            "type": "string",
                            "example": "john@example.com"
                        }
                    },
                    "active": {
                        "type": "boolean",
                        "example": true
                    },
                    "is_catch_all": {
                        "description": "Always true",
                        "type": "boolean",
                        "example": true
                    },
                    "private_comment": {
                        "type": "string",
                        "example": "Catch-all for example.com",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    },
                    "created_by": {
                        "type": "integer",
                        "example": 12,
                        "nullable": true
                    },
                    "mailcow_id": {
                        "description": "The catch-all's id on the mail server",
                        "type": "string",
                        "example": "18",
                        "nullable": true
                    },
                    "sync_status": {
                        "description": "synced when the mail server has the catch-all as stored here; pending, error or failed otherwise",
                        "type": "string",
                        "example": "synced"
                    },
                    "synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-20T09:00:00.000000Z",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "SesDnsRecord": {
                "description": "A record that verifies the domain for outgoing mail: one TXT, then one CNAME per DKIM key",
                "required": [
                    "type",
                    "name",
                    "value",
                    "ttl"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "TXT",
                            "CNAME"
                        ],
                        "example": "CNAME"
                    },
                    "name": {
                        "description": "Fully qualified record name",
                        "type": "string",
                        "example": "abcdefgh12345678._domainkey.example.com"
                    },
                    "value": {
                        "type": "string",
                        "example": "abcdefgh12345678.dkim.amazonses.com"
                    },
                    "ttl": {
                        "type": "integer",
                        "example": 1800
                    }
                },
                "type": "object"
            },
            "MailcowDkimRecord": {
                "description": "The domain's DKIM TXT record. Null when no key is available right now: either the mail server has not issued one yet or it could not be reached. Never treat null as 'remove the record': leave an already-published record in place.",
                "required": [
                    "type",
                    "host",
                    "name",
                    "value",
                    "ttl"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "example": "TXT"
                    },
                    "host": {
                        "description": "Record name relative to the zone",
                        "type": "string",
                        "example": "dkim._domainkey"
                    },
                    "name": {
                        "description": "Fully qualified record name",
                        "type": "string",
                        "example": "dkim._domainkey.example.com"
                    },
                    "value": {
                        "type": "string",
                        "example": "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkq..."
                    },
                    "ttl": {
                        "type": "integer",
                        "example": 1800
                    }
                },
                "type": "object",
                "nullable": true
            },
            "DnsPropagationCheck": {
                "required": [
                    "status",
                    "message",
                    "expected",
                    "found"
                ],
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "success",
                            "error"
                        ],
                        "example": "error"
                    },
                    "message": {
                        "type": "string",
                        "example": "SPF record value mismatch"
                    },
                    "expected": {
                        "type": "string",
                        "example": "SPF record"
                    },
                    "found": {
                        "type": "string",
                        "example": "v=spf1 include:_spf.google.com ~all"
                    }
                },
                "type": "object"
            },
            "Token": {
                "required": [
                    "token"
                ],
                "properties": {
                    "token": {
                        "type": "string",
                        "example": "1|yPmMhRhGvqBObW4FmCPqrxVEKzQvM5NeaiGBZtVf"
                    },
                    "user": {
                        "$ref": "#/components/schemas/User"
                    }
                },
                "type": "object"
            },
            "DnsCheckWindow": {
                "required": [
                    "limit",
                    "used",
                    "remaining"
                ],
                "properties": {
                    "limit": {
                        "type": "integer",
                        "example": 24
                    },
                    "used": {
                        "type": "integer",
                        "example": 3
                    },
                    "remaining": {
                        "type": "integer",
                        "example": 21
                    },
                    "resets_at": {
                        "description": "When the oldest counted check leaves the window; null when nothing is counted",
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-09-05T08:12:00+00:00",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "DnsCheckQuota": {
                "required": [
                    "domains",
                    "daily",
                    "weekly",
                    "burst"
                ],
                "properties": {
                    "domains": {
                        "description": "Domains the key can list; the allowance is derived from it",
                        "type": "integer",
                        "example": 12
                    },
                    "daily": {
                        "$ref": "#/components/schemas/DnsCheckWindow"
                    },
                    "weekly": {
                        "$ref": "#/components/schemas/DnsCheckWindow"
                    },
                    "generic": {
                        "description": "Checks of domains outside the account count here too, capped at the minimums regardless of domain count",
                        "properties": {
                            "daily": {
                                "$ref": "#/components/schemas/DnsCheckWindow"
                            },
                            "weekly": {
                                "$ref": "#/components/schemas/DnsCheckWindow"
                            }
                        },
                        "type": "object"
                    },
                    "burst": {
                        "properties": {
                            "per_minute": {
                                "type": "integer",
                                "example": 30
                            },
                            "scope": {
                                "type": "string",
                                "example": "ip"
                            }
                        },
                        "type": "object"
                    },
                    "cache_seconds": {
                        "type": "integer",
                        "example": 60
                    }
                },
                "type": "object"
            },
            "DnsCheckRecord": {
                "required": [
                    "key",
                    "label",
                    "type",
                    "host",
                    "name",
                    "required",
                    "status",
                    "code",
                    "message"
                ],
                "properties": {
                    "key": {
                        "description": "mx, spf, dkim, dmarc, ses_verification, ses_dkim_1 ... ses_dkim_N",
                        "type": "string",
                        "example": "spf"
                    },
                    "label": {
                        "type": "string",
                        "example": "SPF"
                    },
                    "type": {
                        "type": "string",
                        "example": "TXT"
                    },
                    "host": {
                        "description": "Record name relative to the zone",
                        "type": "string",
                        "example": "@"
                    },
                    "name": {
                        "description": "Fully qualified record name",
                        "type": "string",
                        "example": "customer.com"
                    },
                    "required": {
                        "description": "False for recommended records (DMARC); they never fail the domain",
                        "type": "boolean",
                        "example": true
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pass",
                            "warn",
                            "fail",
                            "unknown"
                        ],
                        "example": "fail"
                    },
                    "code": {
                        "description": "Stable reason: ok, missing, mismatch, multiple, quoted, syntax, not_primary, extra_hosts, not_authorising, permissive, no_terminal, too_many_lookups, present, present_unverified, inherited, flattened, not_ready, lookup_failed",
                        "type": "string",
                        "example": "not_authorising"
                    },
                    "expected": {
                        "type": "string",
                        "example": "v=spf1 mx a:mail.atriomail.com ~all",
                        "nullable": true
                    },
                    "found": {
                        "description": "Values the zone serves; null when the lookup failed",
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "nullable": true
                    },
                    "message": {
                        "type": "string",
                        "example": "SPF record found, but it does not authorise mail.atriomail.com."
                    },
                    "fix": {
                        "type": "string",
                        "example": "Add a:mail.atriomail.com to your existing SPF record, before the all mechanism.",
                        "nullable": true
                    },
                    "notes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "type": "object"
            },
            "DnsCheckReport": {
                "required": [
                    "domain",
                    "mode",
                    "mail_host",
                    "checked_at",
                    "cached",
                    "summary",
                    "records",
                    "quota"
                ],
                "properties": {
                    "domain": {
                        "type": "string",
                        "example": "customer.com"
                    },
                    "domain_id": {
                        "description": "Null for a generic check",
                        "type": "integer",
                        "example": 123,
                        "nullable": true
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "account",
                            "generic"
                        ],
                        "example": "account"
                    },
                    "mail_host": {
                        "description": "The mail host the records are checked against",
                        "type": "string",
                        "example": "mail.atriomail.com"
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "cached": {
                        "description": "True when served from the 60 second cache; such a response is not counted",
                        "type": "boolean",
                        "example": false
                    },
                    "cache_expires_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "summary": {
                        "properties": {
                            "status": {
                                "type": "string",
                                "enum": [
                                    "pass",
                                    "warn",
                                    "fail",
                                    "unknown"
                                ],
                                "example": "fail"
                            },
                            "required_total": {
                                "type": "integer",
                                "example": 6
                            },
                            "required_passed": {
                                "type": "integer",
                                "example": 4
                            },
                            "percentage": {
                                "type": "integer",
                                "example": 67
                            }
                        },
                        "type": "object"
                    },
                    "records": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DnsCheckRecord"
                        }
                    },
                    "ses": {
                        "description": "Null for a generic check",
                        "properties": {
                            "enabled": {
                                "type": "boolean",
                                "example": true
                            },
                            "processing_status": {
                                "type": "string",
                                "example": "completed",
                                "nullable": true
                            },
                            "verification_status": {
                                "type": "string",
                                "example": "pending",
                                "nullable": true
                            }
                        },
                        "type": "object",
                        "nullable": true
                    },
                    "quota": {
                        "$ref": "#/components/schemas/DnsCheckQuota"
                    }
                },
                "type": "object"
            },
            "DnsCheckQuotaExceeded": {
                "required": [
                    "success",
                    "error",
                    "window",
                    "message",
                    "retry_after",
                    "quota"
                ],
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": false
                    },
                    "error": {
                        "type": "string",
                        "example": "dns_check_quota_exceeded"
                    },
                    "window": {
                        "type": "string",
                        "enum": [
                            "daily",
                            "weekly",
                            "generic_daily",
                            "generic_weekly"
                        ],
                        "example": "daily"
                    },
                    "message": {
                        "type": "string",
                        "example": "DNS check allowance used up: 24 checks per 24 hours for 12 domains. Try again in 3 hours 12 minutes. Results from the last 60 seconds are still returned."
                    },
                    "retry_after": {
                        "description": "Seconds until one more check is allowed; also sent as the Retry-After header",
                        "type": "integer",
                        "example": 11520
                    },
                    "quota": {
                        "$ref": "#/components/schemas/DnsCheckQuota"
                    }
                },
                "type": "object"
            },
            "MigrationJob": {
                "description": "The fields of a sync job this API and the panel read; the mail server may send more, and most numeric settings arrive as strings.",
                "properties": {
                    "id": {
                        "description": "The IMAP migrations of the v1 API: each one is a Mailcow sync job that pulls a\nremote IMAP account into a mailbox on this platform. The annotations document\nthe routes registered in routes/api.php and the bodies these methods send;\nswagger-php reads only the docblock attached to a method, so they sit on them.",
                        "type": "integer",
                        "example": 7
                    },
                    "user2": {
                        "description": "The destination mailbox on this platform",
                        "type": "string",
                        "example": "john@example.com"
                    },
                    "host1": {
                        "description": "The remote IMAP host",
                        "type": "string",
                        "example": "imap.old-provider.com"
                    },
                    "port1": {
                        "type": "string",
                        "example": "993"
                    },
                    "user1": {
                        "description": "The login on the remote host",
                        "type": "string",
                        "example": "john@old-provider.com"
                    },
                    "enc1": {
                        "type": "string",
                        "enum": [
                            "TLS",
                            "SSL",
                            "PLAIN"
                        ],
                        "example": "SSL"
                    },
                    "mins_interval": {
                        "description": "Minutes between runs",
                        "type": "string",
                        "example": "60"
                    },
                    "subfolder2": {
                        "description": "Folder in the destination mailbox to sync into; empty for the root",
                        "type": "string",
                        "example": ""
                    },
                    "maxage": {
                        "description": "Only mail newer than this many days; 0 for everything",
                        "type": "string",
                        "example": "0"
                    },
                    "maxbytespersecond": {
                        "description": "Transfer cap; 0 for none",
                        "type": "string",
                        "example": "0"
                    },
                    "timeout1": {
                        "type": "string",
                        "example": "600"
                    },
                    "timeout2": {
                        "type": "string",
                        "example": "600"
                    },
                    "exclude": {
                        "description": "Regular expression of folders to skip",
                        "type": "string",
                        "example": "(?i)spam|(?i)junk"
                    },
                    "custom_params": {
                        "type": "string",
                        "example": ""
                    },
                    "delete2duplicates": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 1
                    },
                    "delete1": {
                        "description": "Delete each message from the remote account once it is copied",
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 0
                    },
                    "delete2": {
                        "description": "Delete from the destination mailbox what the remote account does not have",
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 0
                    },
                    "automap": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 1
                    },
                    "skipcrossduplicates": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 0
                    },
                    "subscribeall": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 1
                    },
                    "active": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 1
                    },
                    "is_running": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ],
                        "example": 0
                    },
                    "last_run": {
                        "type": "string",
                        "example": "2026-07-01 12:00:00",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "MigrationJobRequest": {
                "description": "The body of POST /api/v1/migrations. Booleans default to false, mins_interval to 60, the timeouts to 600 and the other settings to empty or 0, so a job is created switched off unless active is true.",
                "required": [
                    "username",
                    "host1",
                    "port1",
                    "user1",
                    "password1",
                    "enc1"
                ],
                "properties": {
                    "username": {
                        "description": "A mailbox on this platform the key can manage: the destination",
                        "type": "string",
                        "example": "john@example.com"
                    },
                    "host1": {
                        "description": "The remote IMAP host",
                        "type": "string",
                        "maxLength": 255,
                        "example": "imap.old-provider.com"
                    },
                    "port1": {
                        "type": "integer",
                        "maximum": 65535,
                        "minimum": 1,
                        "example": 993
                    },
                    "user1": {
                        "description": "The login on the remote host",
                        "type": "string",
                        "maxLength": 255,
                        "example": "john@old-provider.com"
                    },
                    "password1": {
                        "description": "The remote login's password; stored on the mail server, never returned",
                        "type": "string",
                        "format": "password",
                        "example": "remote-password"
                    },
                    "enc1": {
                        "type": "string",
                        "enum": [
                            "TLS",
                            "SSL",
                            "PLAIN"
                        ],
                        "example": "SSL"
                    },
                    "mins_interval": {
                        "description": "Minutes between runs",
                        "type": "integer",
                        "minimum": 1,
                        "example": 60
                    },
                    "subfolder2": {
                        "description": "Folder in the destination mailbox to sync into; empty for the root",
                        "type": "string",
                        "example": ""
                    },
                    "maxage": {
                        "description": "Only mail newer than this many days; 0 for everything",
                        "type": "integer",
                        "minimum": 0,
                        "example": 0
                    },
                    "maxbytespersecond": {
                        "description": "Transfer cap; 0 for none",
                        "type": "integer",
                        "minimum": 0,
                        "example": 0
                    },
                    "timeout1": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 600
                    },
                    "timeout2": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 600
                    },
                    "exclude": {
                        "description": "Regular expression of folders to skip",
                        "type": "string",
                        "example": "(?i)spam|(?i)junk"
                    },
                    "custom_params": {
                        "type": "string",
                        "example": ""
                    },
                    "delete2duplicates": {
                        "type": "boolean",
                        "example": true
                    },
                    "delete1": {
                        "description": "Delete each message from the remote account once it is copied",
                        "type": "boolean",
                        "example": false
                    },
                    "delete2": {
                        "description": "Delete from the destination mailbox what the remote account does not have",
                        "type": "boolean",
                        "example": false
                    },
                    "automap": {
                        "type": "boolean",
                        "example": true
                    },
                    "skipcrossduplicates": {
                        "type": "boolean",
                        "example": false
                    },
                    "subscribeall": {
                        "type": "boolean",
                        "example": true
                    },
                    "active": {
                        "description": "Whether the job runs on its interval",
                        "type": "boolean",
                        "example": true
                    }
                },
                "type": "object"
            },
            "MigrationJobUpdate": {
                "description": "The body of PUT /api/v1/migrations/{id}: the same settings, every one optional, only the ones sent change. The destination mailbox cannot be changed; an empty password1 is ignored.",
                "properties": {
                    "host1": {
                        "type": "string",
                        "maxLength": 255,
                        "example": "imap.old-provider.com"
                    },
                    "port1": {
                        "type": "integer",
                        "maximum": 65535,
                        "minimum": 1,
                        "example": 993
                    },
                    "user1": {
                        "type": "string",
                        "maxLength": 255,
                        "example": "john@old-provider.com"
                    },
                    "password1": {
                        "type": "string",
                        "format": "password",
                        "example": "remote-password"
                    },
                    "enc1": {
                        "type": "string",
                        "enum": [
                            "TLS",
                            "SSL",
                            "PLAIN"
                        ],
                        "example": "SSL"
                    },
                    "mins_interval": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 60
                    },
                    "subfolder2": {
                        "type": "string",
                        "example": ""
                    },
                    "maxage": {
                        "type": "integer",
                        "minimum": 0,
                        "example": 0
                    },
                    "maxbytespersecond": {
                        "type": "integer",
                        "minimum": 0,
                        "example": 0
                    },
                    "timeout1": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 600
                    },
                    "timeout2": {
                        "type": "integer",
                        "minimum": 1,
                        "example": 600
                    },
                    "exclude": {
                        "type": "string",
                        "example": "(?i)spam|(?i)junk"
                    },
                    "custom_params": {
                        "type": "string",
                        "example": ""
                    },
                    "delete2duplicates": {
                        "type": "boolean",
                        "example": true
                    },
                    "delete1": {
                        "type": "boolean",
                        "example": false
                    },
                    "delete2": {
                        "type": "boolean",
                        "example": false
                    },
                    "automap": {
                        "type": "boolean",
                        "example": true
                    },
                    "skipcrossduplicates": {
                        "type": "boolean",
                        "example": false
                    },
                    "subscribeall": {
                        "type": "boolean",
                        "example": true
                    },
                    "active": {
                        "type": "boolean",
                        "example": true
                    }
                },
                "type": "object"
            },
            "MigrationError": {
                "description": "The body of a 404: no job with that id among the ones the key can manage",
                "required": [
                    "status",
                    "message"
                ],
                "properties": {
                    "status": {
                        "type": "string",
                        "example": "error"
                    },
                    "message": {
                        "type": "string",
                        "example": "Migration job not found or not accessible"
                    }
                },
                "type": "object"
            }
        },
        "responses": {
            "Unauthenticated": {
                "description": "No X-API-KEY header, or a key that is unknown, revoked or expired. Five wrong keys from one address within five minutes answer 429 instead, with retry_after in seconds.",
                "content": {
                    "application/json": {
                        "schema": {
                            "required": [
                                "message"
                            ],
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "example": "API key is missing"
                                }
                            },
                            "type": "object"
                        },
                        "examples": {
                            "missing": {
                                "summary": "No X-API-KEY header",
                                "value": {
                                    "message": "API key is missing"
                                }
                            },
                            "invalid": {
                                "summary": "A key that is unknown, revoked or expired",
                                "value": {
                                    "message": "Invalid API key"
                                }
                            }
                        }
                    }
                }
            },
            "RoleRefused": {
                "description": "Needs an admin or superadmin key: a key on a user-role account answers {success: false, message}. A suspended account, or a key that may not act for the account named in its X-Laravel-User-* headers, answers {message} alone.",
                "content": {
                    "application/json": {
                        "schema": {
                            "required": [
                                "message"
                            ],
                            "properties": {
                                "success": {
                                    "description": "Sent with the role refusal only",
                                    "type": "boolean",
                                    "example": false
                                },
                                "message": {
                                    "type": "string",
                                    "example": "User does not have the required permissions."
                                }
                            },
                            "type": "object"
                        },
                        "examples": {
                            "role": {
                                "summary": "A key on a user-role account",
                                "value": {
                                    "success": false,
                                    "message": "User does not have the required permissions."
                                }
                            },
                            "suspended": {
                                "summary": "The key's account is suspended",
                                "value": {
                                    "message": "This account is suspended. Contact support for assistance."
                                }
                            },
                            "manager_suspended": {
                                "summary": "The account that manages the key's account is suspended",
                                "value": {
                                    "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                }
                            }
                        }
                    }
                }
            },
            "AccountRefused": {
                "description": "The key's account is suspended (or the account that manages it is), or the key may not act for the account named in its X-Laravel-User-* headers. Any role's key can call this operation.",
                "content": {
                    "application/json": {
                        "schema": {
                            "required": [
                                "message"
                            ],
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "example": "This account is suspended. Contact support for assistance."
                                }
                            },
                            "type": "object"
                        },
                        "examples": {
                            "suspended": {
                                "summary": "The key's account is suspended",
                                "value": {
                                    "message": "This account is suspended. Contact support for assistance."
                                }
                            },
                            "manager_suspended": {
                                "summary": "The account that manages the key's account is suspended",
                                "value": {
                                    "message": "This account is suspended because the account that manages it is suspended. Contact support for assistance."
                                }
                            }
                        }
                    }
                }
            }
        },
        "securitySchemes": {
            "apiKeyAuth": {
                "type": "apiKey",
                "description": "An API key from the panel's API Keys page. The only scheme: every documented route reads X-API-KEY and refuses a Bearer token, so the Authorize dialog offers nothing else.",
                "name": "X-API-KEY",
                "in": "header"
            }
        }
    },
    "tags": [
        {
            "name": "Domains",
            "description": "API Endpoints for managing email domains"
        },
        {
            "name": "Mailboxes",
            "description": "API Endpoints for managing email mailboxes"
        },
        {
            "name": "Forwarders",
            "description": "API Endpoints for managing email forwarders"
        },
        {
            "name": "Catch-All",
            "description": "API Endpoints for managing catch-all email configurations"
        },
        {
            "name": "DNS checks",
            "description": "Check a domain's mail DNS records (MX, SPF, DKIM, DMARC, Amazon SES) against what the platform expects"
        },
        {
            "name": "Quotas",
            "description": "API Endpoints for managing mailbox quotas"
        },
        {
            "name": "Single sign-on",
            "description": "One-time links that sign a customer in to the control panel"
        },
        {
            "name": "Users",
            "description": "API Endpoints for managing users"
        },
        {
            "name": "Migrations",
            "description": "Migrations"
        },
        {
            "name": "Status",
            "description": "Status"
        }
    ]
}