{
  "openapi": "3.0.0",
  "paths": {
    "/api/namespaces": {
      "get": {
        "operationId": "ApiController_listNamespaces",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListNamespacesResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List namespaces",
        "tags": [
          "Api",
          "Namespaces"
        ]
      }
    },
    "/api/emails/{namespace}/inbox": {
      "get": {
        "description": "This endpoint returns the latest emails from a specific namespace's inbox.\nWhen the `wait` query flag is set to `true` and no emails are found yet, the endpoint waits briefly and redirects back to the same URL so the client can retry the same request automatically.",
        "operationId": "ApiController_searchInbox",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": true,
            "in": "query",
            "description": "The maximum number of emails that can be returned in this request. Must be between 1 and 20",
            "schema": {
              "minimum": 1,
              "maximum": 20,
              "default": 10,
              "example": 10,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": true,
            "in": "query",
            "description": "The number of emails to skip/ignore, useful for pagination",
            "schema": {
              "minimum": 0,
              "default": 0,
              "example": 0,
              "type": "number"
            }
          },
          {
            "name": "from_timestamp",
            "required": false,
            "in": "query",
            "description": "Filter emails by starting unix timestamp in seconds",
            "schema": {
              "minimum": 0,
              "example": 1714857600,
              "type": "number"
            }
          },
          {
            "name": "to_timestamp",
            "required": false,
            "in": "query",
            "description": "Filter emails by ending unix timestamp in seconds",
            "schema": {
              "minimum": 0,
              "example": 1714857600,
              "type": "number"
            }
          },
          {
            "name": "to_addr_prefix",
            "required": false,
            "in": "query",
            "description": "Filter emails by 'to' address. Address must start with this. Example: 'foo' would return for 'foobar@...' but not 'barfoo@...'",
            "schema": {
              "example": "john@example.com",
              "type": "string"
            }
          },
          {
            "name": "from_addr_includes",
            "required": false,
            "in": "query",
            "description": "Filter emails by 'from' address. Address must contain this. Example: 'foo' would return for 'foobar@...' but not 'barfoo@...'",
            "schema": {
              "example": "john@example.com",
              "type": "string"
            }
          },
          {
            "name": "subject_includes",
            "required": false,
            "in": "query",
            "description": "Filter emails by subject. This is case insensitive. Subject must include this. Example: 'password' would return for 'Password reset', 'Reset password notification' but not 'Reset'",
            "schema": {
              "example": "example",
              "type": "string"
            }
          },
          {
            "name": "wait",
            "required": false,
            "in": "query",
            "description": "If this flag is true then the request will keep waiting till at least one response is returned",
            "schema": {
              "example": true,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchInboxResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Search inbox",
        "tags": [
          "Api",
          "Emails"
        ]
      }
    },
    "/api/emails/{emailId}": {
      "get": {
        "operationId": "ApiController_getInboundEmail",
        "parameters": [
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetInboundEmailResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get inbound email",
        "tags": [
          "Api",
          "Emails"
        ]
      }
    },
    "/api/emails/{emailId}/deliverability-report": {
      "post": {
        "operationId": "ApiController_requestInboundDeliverabilityReport",
        "parameters": [
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverabilityReportResponseDto"
                }
              }
            }
          },
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverabilityReportResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Generate deliverability report",
        "tags": [
          "Api",
          "Emails"
        ]
      },
      "get": {
        "operationId": "ApiController_getInboundDeliverabilityReport",
        "parameters": [
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverabilityReportResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get deliverability report",
        "tags": [
          "Api",
          "Emails"
        ]
      }
    },
    "/api/emails/{emailId}/attachments": {
      "get": {
        "operationId": "ApiController_getInboundEmailAttachments",
        "parameters": [
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetEmailAttachmentsResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get email attachments",
        "tags": [
          "Api",
          "Emails"
        ]
      }
    },
    "/api/emails/{namespace}/{emailId}/deliverability-report/raw-source": {
      "get": {
        "operationId": "ApiController_getDeliverabilityRawSourceDownload",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "received_timestamp",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get raw EML download URL",
        "tags": [
          "Api",
          "Emails"
        ]
      }
    },
    "/api/attachments/{id}": {
      "get": {
        "operationId": "ApiController_getAttachment",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the attachment to retrieve",
            "schema": {
              "format": "uuid",
              "example": "5e0c23bc-dc1c-49f3-8d92-9a0d85527019",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetAttachmentResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get attachment by id",
        "tags": [
          "Api",
          "Emails"
        ]
      }
    },
    "/api/namespace/{namespace}/settings": {
      "post": {
        "operationId": "ApiController_updateNamespaceSettings",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateNamespaceSettingsDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateNamespaceSettingsResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update namespace",
        "tags": [
          "Api",
          "Namespaces"
        ]
      }
    },
    "/api/emails/send": {
      "post": {
        "description": "Create and queue a new outbound email from the requested namespace. Recipients must be verified external destinations or addresses under the same namespace, and the request must include at least one recipient plus either `html` or `text` content. Attachments can be included by passing base64 encoded file bytes in `attachments[].content_base64`; use `application/octet-stream` when the file should be preserved as a downloadable attachment. If `from` is omitted, Mailisk sends from `outbound-delivery@{namespace}.mailisk.net`; sender overrides must belong to the requested namespace. Messages sent only to same-namespace recipients do not consume outbound usage because they are counted as inbound email when delivered.",
        "operationId": "OutboundEmailController_sendEmail",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "query",
            "description": "Namespace to send from.",
            "schema": {
              "maxLength": 253,
              "example": "mynamespace",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendOutboundEmailDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundEmailResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Send email",
        "tags": [
          "Outbound Emails"
        ]
      }
    },
    "/api/emails/outbound": {
      "get": {
        "description": "Return newest-first outbound emails for an organisation, including their recipients and current delivery states. Session-authenticated users must provide `organisation_id`; organisation API keys infer their organisation automatically. Results can be filtered by outbound email status or composition type.",
        "operationId": "OutboundEmailController_listEmails",
        "parameters": [
          {
            "name": "organisation_id",
            "required": false,
            "in": "query",
            "description": "Organisation whose outbound emails should be returned. Required for session-authenticated users.",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "The maximum number of outbound emails that can be returned in this request.",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "The number of matching outbound emails to skip.",
            "schema": {
              "minimum": 0,
              "default": 0,
              "example": 0,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Filter outbound emails by their queue status.",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "sending",
                "sent",
                "failed"
              ]
            }
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "description": "Filter outbound emails by how they were composed.",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "reply",
                "forward"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListOutboundEmailsResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List outbound emails",
        "tags": [
          "Outbound Emails"
        ]
      }
    },
    "/api/emails/outbound/{outboundEmailId}": {
      "get": {
        "description": "Return the current delivery state for an outbound email, including sender details, provider identifiers, timestamps, recipient status, a delivery summary, and provider delivery events. Only outbound emails accessible to the API key can be retrieved.",
        "operationId": "OutboundEmailController_getEmail",
        "parameters": [
          {
            "name": "outboundEmailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundEmailDetailResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get outbound email",
        "tags": [
          "Outbound Emails"
        ]
      }
    },
    "/api/emails/outbound/{outboundEmailId}/attachments/{attachmentId}": {
      "get": {
        "description": "Return stored attachment bytes for an accessible outbound email. Attachment metadata remains available after the bytes expire, but this endpoint then returns 410.",
        "operationId": "OutboundEmailController_getEmailAttachmentContent",
        "parameters": [
          {
            "name": "outboundEmailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundEmailAttachmentContentResponseDto"
                }
              }
            }
          },
          "410": {
            "description": "The attachment content has expired."
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get outbound email attachment content",
        "tags": [
          "Outbound Emails"
        ]
      }
    },
    "/api/emails/{emailId}/reply": {
      "post": {
        "description": "Create and queue a reply to an inbound email. Mailisk derives the reply recipient, sender namespace, and threading headers from the source email, defaults the subject to `Re: {original subject}`, and requires either `html` or `text` content. Attachments can be included by passing base64 encoded file bytes in `attachments[].content_base64`; use `application/octet-stream` when the file should be preserved as a downloadable attachment. Replies sent only to same-namespace recipients do not consume outbound usage because they are counted as inbound email when delivered.",
        "operationId": "OutboundEmailController_replyToEmail",
        "parameters": [
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplyOutboundEmailDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundEmailResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Reply to an email",
        "tags": [
          "Outbound Emails"
        ]
      }
    },
    "/api/emails/{emailId}/forward": {
      "post": {
        "description": "Create and queue a forwarded copy of an existing inbound email. Mailisk derives the sender namespace from the source email. The `to` list is required, optional `html` or `text` content is prepended before the forwarded message, and recipients must be verified external destinations or same-namespace addresses. Attachments can be included by passing base64 encoded file bytes in `attachments[].content_base64`; use `application/octet-stream` when the file should be preserved as a downloadable attachment. Forwards sent only to same-namespace recipients do not consume outbound usage because they are counted as inbound email when delivered.",
        "operationId": "OutboundEmailController_forwardEmail",
        "parameters": [
          {
            "name": "emailId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForwardOutboundEmailDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboundEmailResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Forward an email",
        "tags": [
          "Outbound Emails"
        ]
      }
    },
    "/api/sms/numbers": {
      "get": {
        "operationId": "SmsApiController_listNumbers",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSmsNumbersResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List SMS numbers",
        "tags": [
          "SmsApi",
          "SMS"
        ]
      }
    },
    "/api/sms/{phone_number}/messages": {
      "get": {
        "description": "This endpoint returns the latest SMS messages for a specific phone number.\nWhen the `wait` query flag is set to `true` and no messages are found yet, the endpoint waits briefly and redirects back to the same URL so the client can retry the same request automatically.",
        "operationId": "SmsApiController_searchMessages",
        "parameters": [
          {
            "name": "phone_number",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": true,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": true,
            "in": "query",
            "schema": {
              "minimum": 0,
              "default": 0,
              "type": "number"
            }
          },
          {
            "name": "body",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from_number",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from_date",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to_date",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wait",
            "required": false,
            "in": "query",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchSmsMessagesResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Search SMS messages",
        "tags": [
          "SmsApi",
          "SMS"
        ]
      }
    },
    "/api/sms/virtual": {
      "post": {
        "operationId": "SmsApiController_sendVirtualSms",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendVirtualSmsDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": ""
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Simulate SMS message",
        "tags": [
          "SmsApi",
          "SMS"
        ]
      }
    },
    "/api/devices": {
      "get": {
        "description": "The Authenticator (TOTP) API lets you generate one-time passwords and manage virtual 2FA devices for testing authentication systems.",
        "operationId": "TotpApiController_listDevices",
        "parameters": [
          {
            "name": "username",
            "required": false,
            "in": "query",
            "description": "Filter devices by username or account label. This is case insensitive and matches partial values.",
            "schema": {
              "maxLength": 240,
              "example": "qa@example.com",
              "type": "string"
            }
          },
          {
            "name": "issuer",
            "required": false,
            "in": "query",
            "description": "Filter devices by issuer. This is case insensitive and matches partial values.",
            "schema": {
              "maxLength": 240,
              "example": "GitHub",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "The maximum number of virtual security devices that can be returned in this request.",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 100,
              "example": 100,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "The number of virtual security devices to skip, useful for pagination.",
            "schema": {
              "minimum": 0,
              "default": 0,
              "example": 0,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpDeviceListResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List authenticator devices",
        "tags": [
          "Authenticator (TOTP)"
        ]
      },
      "post": {
        "description": "Create a saved virtual 2FA authenticator device from a Base32 shared secret.",
        "operationId": "TotpApiController_createDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTotpDeviceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpDeviceResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create authenticator device",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    },
    "/api/devices/custom": {
      "post": {
        "description": "Create a saved virtual 2FA authenticator device with custom TOTP metadata and parameters.",
        "operationId": "TotpApiController_createCustomDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomTotpDeviceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpDeviceResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create custom authenticator device",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    },
    "/api/devices/base32-secret-key": {
      "post": {
        "description": "Create a saved virtual 2FA authenticator device from a Base32 secret key.",
        "operationId": "TotpApiController_createBase32SecretKeyDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBase32SecretKeyTotpDeviceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpDeviceResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create authenticator device from Base32 secret key",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    },
    "/api/devices/otpauth-url": {
      "post": {
        "description": "Create a saved virtual 2FA authenticator device from an otpauth://totp URL.",
        "operationId": "TotpApiController_createOtpAuthUrlDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOtpAuthUrlTotpDeviceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpDeviceResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create authenticator device from otpauth URL",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    },
    "/api/devices/otp": {
      "post": {
        "description": "Generate a current one-time password from a Base32 shared secret without saving a device. Optionally wait for the next TOTP period when the current code is too close to expiry.",
        "operationId": "TotpApiController_getOtpBySharedSecret",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTotpOtpDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpOtpResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Generate OTP from shared secret",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    },
    "/api/devices/{deviceId}/otp": {
      "get": {
        "description": "Generate the current one-time password for a saved virtual 2FA authenticator device. Optionally wait for the next TOTP period when the current code is too close to expiry.",
        "operationId": "TotpApiController_getDeviceOtp",
        "parameters": [
          {
            "name": "deviceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "name": "min_seconds_until_expire",
            "required": false,
            "in": "query",
            "description": "Minimum number of seconds the generated TOTP code must remain valid. Defaults to 0, which returns the current code immediately.",
            "schema": {
              "minimum": 0,
              "example": 10,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TotpOtpResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get authenticator device OTP",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    },
    "/api/devices/{deviceId}": {
      "delete": {
        "description": "Permanently delete a saved virtual 2FA authenticator device.",
        "operationId": "TotpApiController_deleteDevice",
        "parameters": [
          {
            "name": "deviceId",
            "required": true,
            "in": "path",
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete authenticator device",
        "tags": [
          "Authenticator (TOTP)"
        ]
      }
    }
  },
  "info": {
    "title": "Mailisk REST API",
    "description": "REST API for Mailisk",
    "version": "1.0",
    "contact": {
      "name": "Mailisk",
      "url": "https://mailisk.com",
      "email": "support@mailisk.com"
    }
  },
  "tags": [],
  "servers": [
    {
      "url": "https://api.mailisk.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key"
      }
    },
    "schemas": {
      "ListNamespacesResponseDataDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "namespace": {
            "type": "string"
          },
          "shared": {
            "type": "boolean"
          },
          "shared_organisation_id": {
            "type": "string"
          },
          "settings": {
            "type": "object",
            "properties": {
              "retention_time": {
                "type": "number"
              },
              "quota_limit": {
                "type": "number",
                "nullable": true
              },
              "capture_raw_email": {
                "type": "boolean"
              }
            },
            "required": [
              "retention_time",
              "capture_raw_email"
            ]
          }
        },
        "required": [
          "id",
          "namespace",
          "shared",
          "settings"
        ]
      },
      "ListNamespacesResponseDto": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "number"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ListNamespacesResponseDataDto"
            }
          }
        },
        "required": [
          "total_count",
          "data"
        ]
      },
      "SearchInboxResponseOptionsDto": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "number",
            "description": "The maximum number of emails that can be returned in this request",
            "example": 10
          },
          "offset": {
            "type": "number",
            "description": "The number of emails skipped in this response",
            "example": 0
          },
          "from_timestamp": {
            "type": "number",
            "description": "Applied starting unix timestamp filter in seconds",
            "example": 1714857600
          },
          "to_timestamp": {
            "type": "number",
            "description": "Applied ending unix timestamp filter in seconds",
            "example": 1714857600
          },
          "to_addr_prefix": {
            "type": "string",
            "description": "Applied filter for email 'to' address prefix",
            "example": "john@example.com"
          },
          "from_addr_includes": {
            "type": "string",
            "description": "Applied filter for email 'from' address substring",
            "example": "john@example.com"
          },
          "subject_includes": {
            "type": "string",
            "description": "Applied case-insensitive subject filter",
            "example": "password"
          },
          "wait": {
            "type": "boolean",
            "description": "Whether long-poll waiting was enabled for the request",
            "example": true
          }
        },
        "required": [
          "limit",
          "offset"
        ]
      },
      "EmailAddressDto": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "Email address",
            "example": "john@example.com"
          },
          "name": {
            "type": "string",
            "description": "Display name, if one is specified",
            "example": "John Doe"
          }
        },
        "required": [
          "address"
        ]
      },
      "EmailAttachmentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the attachment",
            "example": "att_123"
          },
          "filename": {
            "type": "string",
            "description": "Filename of the attachment",
            "example": "invoice.pdf"
          },
          "content_type": {
            "type": "string",
            "description": "Content type of the attachment",
            "example": "application/pdf"
          },
          "size": {
            "type": "number",
            "description": "Size in bytes of the attachment",
            "example": 1024
          }
        },
        "required": [
          "id",
          "filename",
          "content_type",
          "size"
        ]
      },
      "EmailDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Namespace scoped ID",
            "example": "email_123"
          },
          "from": {
            "description": "Sender of email",
            "allOf": [
              {
                "$ref": "#/components/schemas/EmailAddressDto"
              }
            ]
          },
          "to": {
            "description": "Recipients of email",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressDto"
            }
          },
          "cc": {
            "description": "Carbon-copied recipients for email message",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressDto"
            }
          },
          "bcc": {
            "description": "Blind carbon-copied recipients for email message",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressDto"
            }
          },
          "subject": {
            "type": "string",
            "description": "Subject of email",
            "example": "Password reset"
          },
          "html": {
            "type": "string",
            "description": "Email content that was sent in HTML format"
          },
          "text": {
            "type": "string",
            "description": "Email content that was sent in plain text format"
          },
          "received_date": {
            "format": "date-time",
            "type": "string",
            "description": "The datetime that this email was received",
            "example": "2026-04-25T08:30:00.000Z"
          },
          "received_timestamp": {
            "type": "number",
            "description": "The timestamp that this email was received",
            "example": 1714857600
          },
          "expires_timestamp": {
            "type": "number",
            "description": "The timestamp when this email will be deleted",
            "example": 1714944000
          },
          "spam_score": {
            "type": "number",
            "description": "Not supported.",
            "example": null
          },
          "headers": {
            "type": "object",
            "description": "The raw email headers",
            "additionalProperties": {
              "type": "string"
            }
          },
          "attachments": {
            "description": "Attachments of the email",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAttachmentDto"
            }
          }
        },
        "required": [
          "id",
          "from",
          "to",
          "received_date",
          "received_timestamp",
          "expires_timestamp"
        ]
      },
      "SearchInboxResponseDto": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "number",
            "description": "Total number of emails matching the query",
            "example": 1
          },
          "options": {
            "description": "Normalized query options applied to this response",
            "allOf": [
              {
                "$ref": "#/components/schemas/SearchInboxResponseOptionsDto"
              }
            ]
          },
          "data": {
            "description": "Emails returned by the inbox search",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailDto"
            }
          }
        },
        "required": [
          "total_count",
          "options",
          "data"
        ]
      },
      "GetInboundEmailResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Inbound email matching the requested ID",
            "allOf": [
              {
                "$ref": "#/components/schemas/EmailDto"
              }
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "DeliverabilityReportResponseDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "object"
          },
          "analysis_version": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "nullable": true
          },
          "report": {
            "type": "object"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "status",
          "analysis_version",
          "expires_at"
        ]
      },
      "GetAttachmentResponseDataDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the attachment",
            "example": "5e0c23bc-dc1c-49f3-8d92-9a0d85527019"
          },
          "filename": {
            "type": "string",
            "description": "Filename of the attachment",
            "example": "lorem-ipsum.txt"
          },
          "content_type": {
            "type": "string",
            "description": "Content type of the attachment",
            "example": "text/plain"
          },
          "size": {
            "type": "number",
            "description": "Size in bytes of the attachment",
            "example": 446
          },
          "expires_at": {
            "type": "string",
            "nullable": true,
            "description": "The datetime when this attachment will be deleted",
            "example": "2026-04-28T08:24:58.000Z"
          },
          "download_url": {
            "type": "string",
            "description": "The URL to the attachment",
            "example": "https://example.com/attachments/1777112698913_5e0c23bc-dc1c-49f3-8d92-9a0d85527019.txt"
          }
        },
        "required": [
          "id",
          "filename",
          "content_type",
          "size",
          "expires_at",
          "download_url"
        ]
      },
      "GetEmailAttachmentsResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Attachment response payloads for the email",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GetAttachmentResponseDataDto"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "GetAttachmentResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Attachment response payload",
            "allOf": [
              {
                "$ref": "#/components/schemas/GetAttachmentResponseDataDto"
              }
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "UpdateNamespaceSettingsDto": {
        "type": "object",
        "properties": {
          "retention_time": {
            "type": "number"
          },
          "quota_limit": {
            "type": "number",
            "nullable": true
          },
          "capture_raw_email": {
            "type": "boolean"
          }
        }
      },
      "UpdateNamespaceSettingsResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "namespace": {
            "type": "string"
          },
          "shared": {
            "type": "boolean"
          },
          "settings": {
            "type": "object",
            "properties": {
              "retention_time": {
                "type": "number"
              },
              "quota_limit": {
                "type": "number",
                "nullable": true
              },
              "capture_raw_email": {
                "type": "boolean"
              }
            },
            "required": [
              "retention_time",
              "capture_raw_email"
            ]
          }
        },
        "required": [
          "id",
          "namespace",
          "shared",
          "settings"
        ]
      },
      "OutboundEmailAddressDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email",
            "example": "support@mynamespace.mailisk.net"
          },
          "name": {
            "type": "string",
            "maxLength": 200,
            "example": "Support"
          }
        },
        "required": [
          "email"
        ]
      },
      "OutboundEmailAttachmentDto": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string",
            "maxLength": 255,
            "description": "Attachment filename shown to recipients.",
            "example": "invoice.pdf"
          },
          "content_type": {
            "type": "string",
            "maxLength": 255,
            "description": "MIME type for the attachment. Use `application/octet-stream` when you need the file to remain a downloadable attachment across mail clients and parsers.",
            "example": "application/octet-stream"
          },
          "content_base64": {
            "type": "string",
            "format": "base64",
            "description": "Base64 encoded file bytes. For example, in Node.js use `fs.readFileSync(\"invoice.pdf\").toString(\"base64\")`; in Cypress use `cy.fixture(\"invoice.pdf\", \"base64\")`.",
            "example": "SGVsbG8sIE1haWxpc2sh"
          },
          "content_id": {
            "type": "string",
            "maxLength": 255,
            "description": "Optional Content-ID for inline attachments referenced from HTML.",
            "example": "logo"
          },
          "disposition": {
            "enum": [
              "attachment",
              "inline"
            ],
            "type": "string",
            "description": "Attachment disposition. Defaults to `attachment`."
          }
        },
        "required": [
          "filename",
          "content_type",
          "content_base64"
        ]
      },
      "SendOutboundEmailDto": {
        "type": "object",
        "properties": {
          "from": {
            "description": "Optional sender override. If supplied, the email address must end with `{namespace}.mailisk.net`, for example `example@mynamespace.mailisk.net`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OutboundEmailAddressDto"
              }
            ]
          },
          "to": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace recipient email addresses.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "verified@example.com"
            }
          },
          "cc": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace CC recipient email addresses.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "optional@example.com"
            }
          },
          "bcc": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace BCC recipient email addresses.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "optional-bcc@example.com"
            }
          },
          "attachments": {
            "description": "Optional attachments to include with the outbound email. Encode file bytes as base64 in `content_base64`; use `application/octet-stream` for files that should be preserved as downloadable attachments. At most 20 attachments are allowed, and the total encoded message size must not exceed 5 MB.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailAttachmentDto"
            }
          },
          "reply_to": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "subject": {
            "type": "string",
            "maxLength": 998
          },
          "html": {
            "type": "string"
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "OutboundEmailResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organisation_id": {
            "type": "string"
          },
          "type": {
            "enum": [
              "new",
              "reply",
              "forward"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "sending",
              "sent",
              "failed"
            ],
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "reply_to": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "subject": {
            "type": "string"
          },
          "recipient_count": {
            "type": "number"
          },
          "attachment_count": {
            "type": "number"
          },
          "message_id": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "provider_message_id": {
            "type": "string"
          },
          "failure_reason": {
            "type": "string"
          },
          "queued_at": {
            "type": "string"
          },
          "sending_at": {
            "type": "string"
          },
          "sent_at": {
            "type": "string"
          },
          "failed_at": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "organisation_id",
          "type",
          "status",
          "from",
          "subject",
          "recipient_count",
          "attachment_count",
          "message_id",
          "queued_at",
          "created_at",
          "updated_at"
        ]
      },
      "ListOutboundEmailsResponseOptionsDto": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "number",
            "description": "The maximum number of outbound emails returned in this response.",
            "example": 20
          },
          "offset": {
            "type": "number",
            "description": "The number of matching outbound emails skipped in this response.",
            "example": 0
          },
          "status": {
            "enum": [
              "queued",
              "sending",
              "sent",
              "failed"
            ],
            "type": "string",
            "description": "Applied outbound email queue status filter."
          },
          "type": {
            "enum": [
              "new",
              "reply",
              "forward"
            ],
            "type": "string",
            "description": "Applied outbound email composition type filter."
          }
        },
        "required": [
          "limit",
          "offset"
        ]
      },
      "OutboundEmailRecipientResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "to",
              "cc",
              "bcc"
            ]
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "delivery_status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted",
              "queued",
              "sent",
              "delayed",
              "deferred",
              "delivered",
              "bounced",
              "expired",
              "complained",
              "unsubscribed",
              "suppressed",
              "rejected",
              "failed",
              "cancelled"
            ]
          },
          "last_event_type": {
            "type": "string"
          },
          "last_event_at": {
            "type": "string"
          },
          "accepted_at": {
            "type": "string"
          },
          "queued_at": {
            "type": "string"
          },
          "sent_at": {
            "type": "string"
          },
          "delayed_at": {
            "type": "string"
          },
          "deferred_at": {
            "type": "string"
          },
          "delivered_at": {
            "type": "string"
          },
          "bounced_at": {
            "type": "string"
          },
          "expired_at": {
            "type": "string"
          },
          "complained_at": {
            "type": "string"
          },
          "unsubscribed_at": {
            "type": "string"
          },
          "suppressed_at": {
            "type": "string"
          },
          "rejected_at": {
            "type": "string"
          },
          "failed_at": {
            "type": "string"
          },
          "cancelled_at": {
            "type": "string"
          },
          "last_smtp_code": {
            "type": "string"
          },
          "last_enhanced_status_code": {
            "type": "string"
          },
          "last_smtp_response": {
            "type": "string"
          },
          "attempt_count": {
            "type": "number"
          },
          "bounce_type": {
            "type": "string"
          },
          "bounce_subtype": {
            "type": "string"
          },
          "bounce_classification": {
            "type": "string"
          },
          "complaint_feedback_type": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "email",
          "delivery_status",
          "attempt_count"
        ]
      },
      "OutboundEmailListItemResponseDto": {
        "type": "object",
        "properties": {
          "recipients": {
            "description": "Recipients and their latest delivery states.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailRecipientResponseDto"
            }
          },
          "id": {
            "type": "string"
          },
          "organisation_id": {
            "type": "string"
          },
          "type": {
            "enum": [
              "new",
              "reply",
              "forward"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "sending",
              "sent",
              "failed"
            ],
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "reply_to": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "subject": {
            "type": "string"
          },
          "recipient_count": {
            "type": "number"
          },
          "attachment_count": {
            "type": "number"
          },
          "message_id": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "provider_message_id": {
            "type": "string"
          },
          "failure_reason": {
            "type": "string"
          },
          "queued_at": {
            "type": "string"
          },
          "sending_at": {
            "type": "string"
          },
          "sent_at": {
            "type": "string"
          },
          "failed_at": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "recipients",
          "id",
          "organisation_id",
          "type",
          "status",
          "from",
          "subject",
          "recipient_count",
          "attachment_count",
          "message_id",
          "queued_at",
          "created_at",
          "updated_at"
        ]
      },
      "ListOutboundEmailsResponseDto": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "number",
            "description": "Total number of outbound emails matching the applied filters.",
            "example": 1
          },
          "options": {
            "description": "Normalized pagination and filter options applied to this response.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ListOutboundEmailsResponseOptionsDto"
              }
            ]
          },
          "data": {
            "description": "Outbound emails returned by the list request.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailListItemResponseDto"
            }
          }
        },
        "required": [
          "total_count",
          "options",
          "data"
        ]
      },
      "OutboundEmailAttachmentResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "filename": {
            "type": "string",
            "example": "invoice.pdf"
          },
          "content_type": {
            "type": "string",
            "example": "application/pdf"
          },
          "size": {
            "type": "number",
            "minimum": 0,
            "description": "Decoded attachment size in bytes.",
            "example": 24576
          },
          "content_id": {
            "type": "string",
            "description": "Content-ID used by inline attachments."
          },
          "disposition": {
            "enum": [
              "attachment",
              "inline"
            ],
            "type": "string"
          },
          "content_expired_at": {
            "type": "string",
            "description": "When Mailisk removed the stored attachment bytes after the email was sent.",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "filename",
          "content_type",
          "size",
          "disposition"
        ]
      },
      "OutboundEmailDeliverySummaryDto": {
        "type": "object",
        "properties": {
          "pending": {
            "type": "number"
          },
          "accepted": {
            "type": "number"
          },
          "queued": {
            "type": "number"
          },
          "sent": {
            "type": "number"
          },
          "delayed": {
            "type": "number"
          },
          "deferred": {
            "type": "number"
          },
          "delivered": {
            "type": "number"
          },
          "bounced": {
            "type": "number"
          },
          "expired": {
            "type": "number"
          },
          "complained": {
            "type": "number"
          },
          "unsubscribed": {
            "type": "number"
          },
          "suppressed": {
            "type": "number"
          },
          "rejected": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "cancelled": {
            "type": "number"
          }
        },
        "required": [
          "pending",
          "accepted",
          "queued",
          "sent",
          "delayed",
          "deferred",
          "delivered",
          "bounced",
          "expired",
          "complained",
          "unsubscribed",
          "suppressed",
          "rejected",
          "failed",
          "cancelled"
        ]
      },
      "OutboundEmailEventRecipientResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "outbound_email_recipient_id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "smtp_code": {
            "type": "string"
          },
          "enhanced_status_code": {
            "type": "string"
          },
          "smtp_response": {
            "type": "string"
          },
          "diagnostic_code": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "attempt_count": {
            "type": "number"
          },
          "bounce_classification": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "email"
        ]
      },
      "OutboundEmailEventResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "provider_message_id": {
            "type": "string"
          },
          "provider_event_id": {
            "type": "string"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "accepted",
              "queued",
              "sent",
              "failed",
              "rejected",
              "delayed",
              "deferred",
              "delivered",
              "bounced",
              "expired",
              "complained",
              "unsubscribed",
              "suppressed",
              "cancelled",
              "opened",
              "clicked"
            ]
          },
          "event_subtype": {
            "type": "string"
          },
          "occurred_at": {
            "type": "string"
          },
          "recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailEventRecipientResponseDto"
            }
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "provider",
          "event_type",
          "occurred_at",
          "recipients",
          "created_at"
        ]
      },
      "OutboundEmailDetailResponseDto": {
        "type": "object",
        "properties": {
          "html": {
            "type": "string",
            "description": "HTML body supplied for the outbound email."
          },
          "text": {
            "type": "string",
            "description": "Plain-text body supplied for the outbound email."
          },
          "attachments": {
            "description": "Attachment metadata and content expiry state. Stored bytes are fetched separately.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailAttachmentResponseDto"
            }
          },
          "delivery_summary": {
            "$ref": "#/components/schemas/OutboundEmailDeliverySummaryDto"
          },
          "recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailRecipientResponseDto"
            }
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailEventResponseDto"
            }
          },
          "id": {
            "type": "string"
          },
          "organisation_id": {
            "type": "string"
          },
          "type": {
            "enum": [
              "new",
              "reply",
              "forward"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "sending",
              "sent",
              "failed"
            ],
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "reply_to": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "subject": {
            "type": "string"
          },
          "recipient_count": {
            "type": "number"
          },
          "attachment_count": {
            "type": "number"
          },
          "message_id": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "provider_message_id": {
            "type": "string"
          },
          "failure_reason": {
            "type": "string"
          },
          "queued_at": {
            "type": "string"
          },
          "sending_at": {
            "type": "string"
          },
          "sent_at": {
            "type": "string"
          },
          "failed_at": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "attachments",
          "delivery_summary",
          "recipients",
          "events",
          "id",
          "organisation_id",
          "type",
          "status",
          "from",
          "subject",
          "recipient_count",
          "attachment_count",
          "message_id",
          "queued_at",
          "created_at",
          "updated_at"
        ]
      },
      "OutboundEmailAttachmentContentResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "filename": {
            "type": "string",
            "example": "invoice.pdf"
          },
          "content_type": {
            "type": "string",
            "example": "application/pdf"
          },
          "size": {
            "type": "number",
            "minimum": 0,
            "description": "Decoded attachment size in bytes.",
            "example": 24576
          },
          "content_base64": {
            "type": "string",
            "format": "base64",
            "description": "Base64-encoded attachment bytes."
          }
        },
        "required": [
          "id",
          "filename",
          "content_type",
          "size",
          "content_base64"
        ]
      },
      "ReplyOutboundEmailDto": {
        "type": "object",
        "properties": {
          "cc": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace CC recipient email addresses.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "optional@example.com"
            }
          },
          "bcc": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace BCC recipient email addresses.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "optional-bcc@example.com"
            }
          },
          "subject": {
            "type": "string",
            "maxLength": 998,
            "description": "Optional reply subject. Defaults to `Re: {original subject}`."
          },
          "attachments": {
            "description": "Optional attachments to include with the reply. Encode file bytes as base64 in `content_base64`; use `application/octet-stream` for files that should be preserved as downloadable attachments. At most 20 attachments are allowed, and the total encoded message size must not exceed 5 MB.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailAttachmentDto"
            }
          },
          "from": {
            "$ref": "#/components/schemas/OutboundEmailAddressDto"
          },
          "html": {
            "type": "string"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "ForwardOutboundEmailDto": {
        "type": "object",
        "properties": {
          "from": {
            "description": "Optional sender override. If supplied, the email address must end with `{namespace}.mailisk.net`, for example `example@mynamespace.mailisk.net`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/OutboundEmailAddressDto"
              }
            ]
          },
          "to": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "minItems": 1,
            "description": "Verified external or same-namespace email addresses to forward the message to.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "verified@example.com"
            }
          },
          "cc": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace CC recipients.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "optional@example.com"
            }
          },
          "bcc": {
            "type": "array",
            "maxLength": 320,
            "format": "email",
            "description": "Verified external or same-namespace BCC recipients.",
            "items": {
              "type": "string",
              "format": "email",
              "maxLength": 320,
              "example": "optional-bcc@example.com"
            }
          },
          "subject": {
            "type": "string",
            "maxLength": 998,
            "description": "Optional forwarded email subject. Defaults to `Fwd: {original subject}`."
          },
          "html": {
            "type": "string",
            "description": "Optional HTML content to prefix before the forwarded message."
          },
          "text": {
            "type": "string",
            "description": "Optional plain text content to prefix before the forwarded message."
          },
          "attachments": {
            "description": "Optional attachments to include with the forward. Encode file bytes as base64 in `content_base64`; use `application/octet-stream` for files that should be preserved as downloadable attachments. At most 20 attachments are allowed, and the total encoded message size must not exceed 5 MB.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OutboundEmailAttachmentDto"
            }
          }
        },
        "required": [
          "to"
        ]
      },
      "SmsNumberResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "organisation_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "requested",
              "active",
              "disabled"
            ]
          },
          "country": {
            "type": "string"
          },
          "phone_number": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "is_test_number": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "organisation_id",
          "status",
          "country",
          "created_at",
          "updated_at"
        ]
      },
      "ListSmsNumbersResponseDto": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "number"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SmsNumberResponseDto"
            }
          }
        },
        "required": [
          "total_count",
          "data"
        ]
      },
      "SmsMessageResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "sms_phone_number_id": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "from_number": {
            "type": "string"
          },
          "to_number": {
            "type": "string"
          },
          "provider_message_id": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          }
        },
        "required": [
          "id",
          "sms_phone_number_id",
          "body",
          "from_number",
          "to_number",
          "created_at",
          "direction"
        ]
      },
      "SearchSmsMessagesResponseDto": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "number"
          },
          "options": {
            "type": "object"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SmsMessageResponseDto"
            }
          }
        },
        "required": [
          "total_count",
          "options",
          "data"
        ]
      },
      "SendVirtualSmsDto": {
        "type": "object",
        "properties": {
          "from_number": {
            "type": "string"
          },
          "to_number": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "from_number",
          "to_number",
          "body"
        ]
      },
      "TotpDeviceListResponseOptionsDto": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "number",
            "description": "The maximum number of virtual security devices returned in this response.",
            "example": 100
          },
          "offset": {
            "type": "number",
            "description": "The number of virtual security devices skipped in this response.",
            "example": 0
          },
          "username": {
            "type": "string",
            "description": "Applied username/account-label filter.",
            "example": "qa@example.com"
          },
          "issuer": {
            "type": "string",
            "description": "Applied issuer filter.",
            "example": "GitHub"
          }
        },
        "required": [
          "limit",
          "offset"
        ]
      },
      "TotpDeviceResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Saved virtual security device id.",
            "example": "9b1f6ec0-b90d-4bd8-8dd0-f6b2d5138273"
          },
          "organisation_id": {
            "type": "string",
            "format": "uuid",
            "description": "Organisation id that owns this saved virtual security device.",
            "example": "7f0a9c32-66b2-4e25-a4cf-1f77db8f7f3b"
          },
          "name": {
            "type": "string",
            "description": "Human-readable device name.",
            "example": "GitHub staging"
          },
          "username": {
            "type": "string",
            "nullable": true,
            "description": "Username or account label associated with this device.",
            "example": "qa@example.com"
          },
          "issuer": {
            "type": "string",
            "nullable": true,
            "description": "Issuer or application label associated with this device.",
            "example": "GitHub"
          },
          "digits": {
            "type": "number",
            "description": "TOTP code length.",
            "enum": [
              6,
              8
            ],
            "example": 6
          },
          "period": {
            "type": "number",
            "description": "TOTP period in seconds.",
            "example": 30
          },
          "algorithm": {
            "type": "string",
            "description": "TOTP HMAC algorithm.",
            "enum": [
              "SHA1",
              "SHA256",
              "SHA512"
            ],
            "example": "SHA1"
          },
          "source": {
            "type": "string",
            "description": "Creation source for this saved virtual security device.",
            "enum": [
              "shared_secret",
              "custom",
              "base32_secret_key",
              "otpauth_url"
            ],
            "example": "custom"
          },
          "expires_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO timestamp after which this saved virtual security device expires.",
            "example": "2026-05-19T12:00:00.000Z",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "description": "ISO timestamp when this saved virtual security device was created.",
            "example": "2026-05-18T12:00:00.000Z",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO timestamp when this saved virtual security device was last updated.",
            "example": "2026-05-18T12:00:00.000Z",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "organisation_id",
          "name",
          "digits",
          "period",
          "algorithm",
          "source",
          "created_at",
          "updated_at"
        ]
      },
      "TotpDeviceListResponseDto": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "number",
            "description": "Total number of active saved virtual security devices matching the query.",
            "example": 1
          },
          "options": {
            "description": "Normalized query options applied to this response.",
            "allOf": [
              {
                "$ref": "#/components/schemas/TotpDeviceListResponseOptionsDto"
              }
            ]
          },
          "items": {
            "description": "Saved virtual security devices returned by the list request.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TotpDeviceResponseDto"
            }
          }
        },
        "required": [
          "total_count",
          "options",
          "items"
        ]
      },
      "CreateTotpDeviceDto": {
        "type": "object",
        "properties": {
          "expires_at": {
            "type": "string",
            "description": "Optional ISO timestamp after which this saved virtual security device expires.",
            "example": "2026-05-19T12:00:00.000Z",
            "format": "date-time"
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional human-readable name for the saved virtual security device.",
            "example": "GitHub staging"
          },
          "shared_secret": {
            "type": "string",
            "description": "Base32 shared secret used to generate TOTP codes.",
            "example": "JBSWY3DPEHPK3PXP"
          }
        },
        "required": [
          "shared_secret"
        ]
      },
      "CreateCustomTotpDeviceDto": {
        "type": "object",
        "properties": {
          "expires_at": {
            "type": "string",
            "description": "Optional ISO timestamp after which this saved virtual security device expires.",
            "example": "2026-05-19T12:00:00.000Z",
            "format": "date-time"
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional human-readable name for the saved virtual security device.",
            "example": "GitHub staging"
          },
          "username": {
            "type": "string",
            "maxLength": 240,
            "description": "Optional username or account label associated with the TOTP secret.",
            "example": "qa@example.com"
          },
          "issuer": {
            "type": "string",
            "maxLength": 240,
            "description": "Optional issuer or application label associated with the TOTP secret.",
            "example": "GitHub"
          },
          "digits": {
            "type": "number",
            "enum": [
              6,
              8
            ],
            "description": "TOTP code length. Defaults to 6 when omitted.",
            "example": 6
          },
          "period": {
            "type": "number",
            "minimum": 10,
            "maximum": 300,
            "description": "TOTP period in seconds. Defaults to 30 when omitted.",
            "example": 30
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "SHA1",
              "SHA256",
              "SHA512"
            ],
            "description": "TOTP HMAC algorithm. Defaults to SHA1 when omitted.",
            "example": "SHA1"
          },
          "secret": {
            "type": "string",
            "description": "Base32 shared secret used to generate TOTP codes.",
            "example": "JBSWY3DPEHPK3PXP"
          }
        },
        "required": [
          "secret"
        ]
      },
      "CreateBase32SecretKeyTotpDeviceDto": {
        "type": "object",
        "properties": {
          "expires_at": {
            "type": "string",
            "description": "Optional ISO timestamp after which this saved virtual security device expires.",
            "example": "2026-05-19T12:00:00.000Z",
            "format": "date-time"
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional human-readable name for the saved virtual security device.",
            "example": "GitHub staging"
          },
          "username": {
            "type": "string",
            "maxLength": 240,
            "description": "Optional username or account label associated with the TOTP secret.",
            "example": "qa@example.com"
          },
          "issuer": {
            "type": "string",
            "maxLength": 240,
            "description": "Optional issuer or application label associated with the TOTP secret.",
            "example": "GitHub"
          },
          "digits": {
            "type": "number",
            "enum": [
              6,
              8
            ],
            "description": "TOTP code length. Defaults to 6 when omitted.",
            "example": 6
          },
          "period": {
            "type": "number",
            "minimum": 10,
            "maximum": 300,
            "description": "TOTP period in seconds. Defaults to 30 when omitted.",
            "example": 30
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "SHA1",
              "SHA256",
              "SHA512"
            ],
            "description": "TOTP HMAC algorithm. Defaults to SHA1 when omitted.",
            "example": "SHA1"
          },
          "base32_secret_key": {
            "type": "string",
            "description": "Base32 shared secret key used to generate TOTP codes.",
            "example": "JBSWY3DPEHPK3PXP"
          }
        },
        "required": [
          "base32_secret_key"
        ]
      },
      "CreateOtpAuthUrlTotpDeviceDto": {
        "type": "object",
        "properties": {
          "expires_at": {
            "type": "string",
            "description": "Optional ISO timestamp after which this saved virtual security device expires.",
            "example": "2026-05-19T12:00:00.000Z",
            "format": "date-time"
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional human-readable name for the saved virtual security device.",
            "example": "GitHub staging"
          },
          "username": {
            "type": "string",
            "maxLength": 240,
            "description": "Optional username or account label. Used only when missing from the otpauth URL.",
            "example": "qa@example.com"
          },
          "issuer": {
            "type": "string",
            "maxLength": 240,
            "description": "Optional issuer label. Used only when missing from the otpauth URL.",
            "example": "GitHub"
          },
          "digits": {
            "type": "number",
            "enum": [
              6,
              8
            ],
            "description": "TOTP code length. Used only when missing from the otpauth URL.",
            "example": 6
          },
          "period": {
            "type": "number",
            "minimum": 10,
            "maximum": 300,
            "description": "TOTP period in seconds. Used only when missing from the otpauth URL.",
            "example": 30
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "SHA1",
              "SHA256",
              "SHA512"
            ],
            "description": "TOTP HMAC algorithm. Used only when missing from the otpauth URL.",
            "example": "SHA1"
          },
          "otp_auth_url": {
            "type": "string",
            "description": "otpauth://totp URL containing at least a Base32 secret query parameter.",
            "example": "otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub"
          }
        },
        "required": [
          "otp_auth_url"
        ]
      },
      "CreateTotpOtpDto": {
        "type": "object",
        "properties": {
          "shared_secret": {
            "type": "string",
            "description": "Base32 shared secret used to generate the current TOTP code without saving a device.",
            "example": "JBSWY3DPEHPK3PXP"
          },
          "min_seconds_until_expire": {
            "type": "number",
            "minimum": 0,
            "description": "Minimum number of seconds the generated TOTP code must remain valid. Defaults to 0, which returns the current code immediately.",
            "example": 10
          }
        },
        "required": [
          "shared_secret"
        ]
      },
      "TotpOtpResponseDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Current TOTP code.",
            "example": "123456"
          },
          "expires": {
            "type": "string",
            "description": "ISO timestamp when this TOTP code expires.",
            "example": "2026-05-18T12:00:30.000Z",
            "format": "date-time"
          }
        },
        "required": [
          "code",
          "expires"
        ]
      }
    }
  }
}
